コード例 #1
0
ファイル: permission.c プロジェクト: IOT-DSA/sdk-dslink-c
void permission_groups_free(PermissionGroups* groups) {
    if (groups->groups) {
        for (size_t i = 0; i < groups->groupLen; ++i) {
            dslink_free((void *)groups->groups[i]);
        }
        dslink_free(groups->groups);
    }
}
コード例 #2
0
ファイル: server.c プロジェクト: vikasga/sdk-dslink-c
static
void broker_server_new_client(uv_poll_t *poll,
                              int status, int events) {
    (void) status;
    (void) events;

    Server *server = poll->data;
    Client *client = dslink_calloc(1, sizeof(Client));
    if (!client) {
        goto fail;
    }

    client->server = server;
    client->sock = dslink_socket_init(0);
    if (!client->sock) {
        dslink_free(client);
        goto fail;
    }

    if (mbedtls_net_accept(&server->srv, &client->sock->socket_ctx,
                           NULL, 0, NULL) != 0) {
        log_warn("Failed to accept a client connection\n");
        goto fail_poll_setup;
    }

    uv_poll_t *clientPoll = dslink_malloc(sizeof(uv_poll_t));
    if (!clientPoll) {
        goto fail_poll_setup;
    }

    uv_loop_t *loop = poll->loop;
    if (uv_poll_init(loop, clientPoll,
                     client->sock->socket_ctx.fd) != 0) {
        dslink_free(clientPoll);
        goto fail_poll_setup;
    }

    clientPoll->data = client;
    client->poll = clientPoll;
    uv_poll_start(clientPoll, UV_READABLE, broker_server_client_ready);

    log_debug("Accepted a client connection\n");
    return;
fail:
    {
        mbedtls_net_context tmp;
        mbedtls_net_init(&tmp);
        mbedtls_net_accept(&server->srv, &tmp, NULL, 0, NULL);
        mbedtls_net_free(&tmp);
    }
    return;
fail_poll_setup:
    dslink_socket_free(client->sock);
    dslink_free(client);
}
コード例 #3
0
ファイル: permission.c プロジェクト: IOT-DSA/sdk-dslink-c
// permission list for node or virtual node
void permission_list_free(List* list) {
    if (!list) {
        return;
    }
    dslink_list_foreach(list) {
        PermissionPair * pair = ((ListNode*)node)->value;
        dslink_free(pair->group);
        dslink_free(pair);
    }
    dslink_list_free(list);
}
コード例 #4
0
ファイル: map.c プロジェクト: IOT-DSA/sdk-dslink-c
static
void dslink_map_entry_clear(Map *map) {
    for (MapEntry *entry = (MapEntry *) map->list.head.next;
         (void *) entry != &map->list.head;) {
        MapEntry *tmp = entry->next;
        dslink_decref(entry->key);
        dslink_decref(entry->value);
        dslink_free(entry->node);
        dslink_free(entry);
        entry = tmp;
    }
}
コード例 #5
0
ファイル: broker.c プロジェクト: ghalwasi/c-mlib
void broker_close_link(RemoteDSLink *link) {
    if (!link) {
        return;
    }
    if (link->client) {
        dslink_socket_close_nofree(link->client->sock);
    }
    if (link->dsId) {
        log_info("DSLink `%s` has disconnected\n", (char *) link->dsId->data);
    } else {
        log_info("DSLink `%s` has disconnected\n", (char *) link->name);
    }

    ref_t *ref;
    if (link->isUpstream) {
        ref = dslink_map_get(link->broker->upstream->children, (void *) link->name);
    } else {
       ref = dslink_map_get(link->broker->downstream->children, (void *) link->name);
    }

    broker_remote_dslink_free(link);
    // it's possible that free link still rely on node->link to close related streams
    // so link need to be freed before disconnected from node
    if (ref) {
        DownstreamNode *node = ref->data;
        broker_dslink_disconnect(node);
    }

    dslink_free(link);
}
コード例 #6
0
ファイル: main.c プロジェクト: ghalwasi/c-mlib
void on_list_update(struct DSLink *link, ref_t *req_ref, json_t *resp) {
    (void) link;
    RequestHolder *holder = req_ref->data;

    json_t *updates = json_object_get(resp, "updates");
    size_t index;
    json_t *value;

    const char* path = json_string_value(json_object_get(holder->req, "path"));

    printf("======= List %s =======\n", path);
    json_array_foreach(updates, index, value) {
        json_t *name = json_array_get(value, 0);
        json_t *val = json_array_get(value, 1);

        if (val->type == JSON_ARRAY || val->type == JSON_OBJECT) {
            char *data = json_dumps(val, JSON_INDENT(0));
            printf("%s = %s\n", json_string_value(name), data);
            dslink_free(data);
        } else if (val->type == JSON_STRING) {
            printf("%s = %s\n", json_string_value(name), json_string_value(val));
        } else if (val->type == JSON_INTEGER) {
            printf("%s = %lli\n", json_string_value(name), json_integer_value(val));
        } else if (val->type == JSON_REAL) {
            printf("%s = %f\n", json_string_value(name), json_real_value(val));
        } else if (val->type == JSON_NULL) {
            printf("%s = NULL\n", json_string_value(name));
        } else if (val->type == JSON_TRUE) {
            printf("%s = true\n", json_string_value(name));
        } else if (val->type == JSON_FALSE) {
            printf("%s = false\n", json_string_value(name));
        } else {
            printf("%s = (Unknown Type)\n", json_string_value(name));
        }
    }
コード例 #7
0
ファイル: permission.c プロジェクト: IOT-DSA/sdk-dslink-c
static
void get_virtual_permission(const char* path, VirtualDownstreamNode* node,
                            const char **groups, PermissionLevel *levels, size_t glen) {
    if (node->permissionList) {
        if (get_current_permission(node->permissionList, groups, levels, glen)) {
            return;
        }
    }
    if (!path || *path == 0) {
        return;
    }

    const char* next = strstr(path, "/");
    char* name;
    if (next) {
        name = dslink_calloc(next - path + 1, 1);
        memcpy(name, path, next-path);
        next ++; // remove '/'
    } else {
        name = (char*)path;
    }

    ref_t *ref = dslink_map_get(&node->childrenNode, name);
    if (ref && ref->data) {
        VirtualDownstreamNode *child = ref->data;
        get_virtual_permission(next, child, groups, levels, glen);
    }

    if (name != path) {
        dslink_free(name);
    }

}
コード例 #8
0
ファイル: map.c プロジェクト: IOT-DSA/sdk-dslink-c
ref_t *dslink_map_removel_get(Map *map, void *key, size_t len) {
    if (!map || map->locked) {
        return NULL;
    }
    size_t index = dslink_map_index_of_key(map, key, len);
    for (MapNode *node = map->table[index]; node != NULL; node = node->next) {
        if (map->cmp(node->entry->key->data, key, len) != 0) {
            continue;
        }
        if (node->prev == NULL) {
            if (node->next) {
                MapNode *tmp = node->next;
                tmp->prev = NULL;
                map->table[index] = tmp;
            } else {
                map->table[index] = NULL;
            }
        } else {
            node->prev->next = node->next;
            if (node->next) {
                node->next->prev = node->prev;
            }
        }

        ref_t *ref = node->entry->value;
        dslink_decref(node->entry->key);
        list_free_node(node->entry);
        dslink_free(node);
        map->size--;
        return ref;
    }
    return NULL;
}
コード例 #9
0
ファイル: main.c プロジェクト: ghalwasi/c-mlib
void on_invoke_updates(struct DSLink *link, ref_t *req_ref, json_t *resp) {
    (void) link;
    (void) req_ref;
    char *data = json_dumps(resp, JSON_INDENT(2));
    printf("Got invoke %s\n", data);
    dslink_free(data);
}
コード例 #10
0
ファイル: server.c プロジェクト: vikasga/sdk-dslink-c
static
void broker_server_client_ready(uv_poll_t *poll,
                                int status,
                                int events) {
    (void) status;
    Client *client = poll->data;
    Server *server = client->server;

    if (events & UV_READABLE) {
        server->data_ready(client, poll->loop->data);
        if (client->sock->socket_ctx.fd == -1) {
            // The callback closed the connection
            dslink_socket_free(client->sock);
            dslink_free(client);
            client = NULL;
            uv_close((uv_handle_t *) poll, broker_free_handle);
        }
    }

    if (client && (events & UV_WRITABLE)) {
        RemoteDSLink *link = client->sock_data;
        if (link) {
            link->ws->write_enabled = 1;
            wslay_event_send(link->ws);
        }
    }

}
コード例 #11
0
ファイル: map.c プロジェクト: IOT-DSA/sdk-dslink-c
void dslink_map_free(Map *map) {
    if (!(map && map->table)) {
        return;
    }
    dslink_map_entry_clear(map);
    dslink_free(map->table);
}
コード例 #12
0
ファイル: msg_subscribe.c プロジェクト: IOT-DSA/sdk-dslink-c
static
void subs_list_free(void *p) {
    List *subs = p;
    dslink_list_foreach_nonext(subs) {
        ListNode *entry = (ListNode *) node;
        entry->list = NULL; //avoid list_remove_node
        SubRequester *sub = entry->value;
        sub->pendingNode = NULL;
        ListNodeBase *tmp = node->next;
        if ((intptr_t) node != (intptr_t) subs) {
            dslink_free(node);
        }
        node = tmp;
    }

    dslink_free(subs);
}
コード例 #13
0
ファイル: broker.c プロジェクト: ghalwasi/c-mlib
static
void handle_conn(Broker *broker, HttpRequest *req, Socket *sock) {
    json_error_t err;

    json_t *body;
    {
        const char *start = strchr(req->body, '{');
        const char *end = strrchr(req->body, '}');
        if (!(start && end)) {
            goto exit;
        }
        body = json_loadb(start, end - start + 1, 0, &err);
        if (!body) {
            broker_send_internal_error(sock);
            goto exit;
        }
    }

    const char *dsId = broker_http_param_get(&req->uri, "dsId");
    if (!dsId) {
        goto exit;
    }
    log_info("%s connecting \n", dsId);
    const char *token = broker_http_param_get(&req->uri, "token");
    json_t *resp = broker_handshake_handle_conn(broker, dsId, token, body);
    json_decref(body);
    if (!resp) {
        broker_send_internal_error(sock);
        goto exit;
    }

    char *data = json_dumps(resp, JSON_INDENT(2));
    json_decref(resp);
    if (!data) {
        broker_send_internal_error(sock);
        goto exit;
    }

    char buf[1024];
    int len = snprintf(buf, sizeof(buf) - 1,
                       CONN_RESP, (int) strlen(data), data);
    buf[len] = '\0';
    dslink_free(data);
    dslink_socket_write(sock, buf, (size_t) len);

exit:
    return;
}
コード例 #14
0
ファイル: permission.c プロジェクト: IOT-DSA/sdk-dslink-c
PermissionLevel get_permission(const char* path, BrokerNode* rootNode, RemoteDSLink *reqLink) {
    if (!rootNode->permissionList) {
        return PERMISSION_CONFIG;
    }
    if (*path != '/') {
        return PERMISSION_NONE;
    }
    size_t glen = reqLink->permission_groups.groupLen;
    PermissionLevel *levels = dslink_calloc(glen, sizeof(PermissionLevel));
    get_node_permission(path+1, rootNode, reqLink->permission_groups.groups, levels, glen);
    PermissionLevel maxLevel = PERMISSION_NONE;
    for (size_t i = 0; i < glen; ++i) {
        if (levels[i] > maxLevel) {
            maxLevel = levels[i];
        }
    }
    dslink_free(levels);
    return maxLevel;
}
コード例 #15
0
ファイル: ws.c プロジェクト: IOT-DSA/sdk-dslink-c
int dslink_ws_send_obj(wslay_event_context_ptr ctx, json_t *obj) {
    DSLink *link = ctx->user_data;
    uint32_t msg = dslink_incr_msg(link);

    json_t *jsonMsg = json_integer(msg);
    json_object_set(obj, "msg", jsonMsg);

    char *data = json_dumps(obj, JSON_PRESERVE_ORDER);
    if (!data) {
        return DSLINK_ALLOC_ERR;
    }

    dslink_ws_send(ctx, data);
    dslink_free(data);

    json_object_del(obj, "msg");
    json_delete(jsonMsg);

    return 0;
}
コード例 #16
0
ファイル: utils.c プロジェクト: ghalwasi/c-mlib
static
char *dslink_str_replace_all_rep(const char *haystack,
                                 const char *needle,
                                 const size_t needleLen,
                                 const char *replacement,
                                 const size_t replacementLen,
                                 const int shouldDup) {

    char *start = strstr(haystack, needle);
    if (!start) {
        if (shouldDup) {
            return dslink_strdup(haystack);
        } else {
            return (char *) haystack;
        }
    }

    const size_t haystackLen = strlen(haystack);
    char *dup = dslink_malloc(haystackLen - needleLen + replacementLen + 1);
    if (!dup) {
        return NULL;
    }

    size_t len = start - haystack;
    memcpy(dup, haystack, len);
    memcpy(dup + len, replacement, replacementLen);
    len += replacementLen;

    size_t remainder = (haystack + haystackLen) - (start + needleLen);
    memcpy(dup + len, start + needleLen, remainder);
    dup[haystackLen - needleLen + replacementLen] = '\0';

    if (!shouldDup) {
        dslink_free((char *) haystack);
    }
    return dslink_str_replace_all_rep(dup, needle, needleLen,
                                      replacement, replacementLen, 0);
}
コード例 #17
0
ファイル: map.c プロジェクト: IOT-DSA/sdk-dslink-c
static
int dslink_map_rehash_table(Map *map) {
    size_t oldCapacity = map->capacity;
    MapNode **oldTable = map->table;

    size_t newCapacity = oldCapacity * 2;
    MapNode **newTable = dslink_calloc(newCapacity, sizeof(MapNode*));
    if (!newTable) {
        return DSLINK_ALLOC_ERR;
    }

    map->capacity = newCapacity;
    map->table = newTable;
    for (MapEntry *entry = (MapEntry *) map->list.head.next;
         (void *)entry != &map->list.head; entry = entry->next) {
        size_t len = map->key_len_calc(entry->key->data);
        size_t index = dslink_map_index_of_key(map, entry->key->data, len);
        MapNode *node = newTable[index];
        if (node) {
            while (1) {
                MapNode *tmp = node->next;
                if (tmp == NULL) {
                    break;
                }
                node = tmp;
            }
            node->next = entry->node;
            entry->node->prev = node;
            entry->node->next = NULL;
        } else {
            entry->node->next = NULL;
            entry->node->prev = NULL;
            newTable[index] = entry->node;
        }
    }
    dslink_free(oldTable);
    return 0;
}
コード例 #18
0
void virtual_downstream_node_free(VirtualDownstreamNode *pnode) {
    json_decref(pnode->meta);
    virtual_downstream_free_map(&pnode->childrenNode);
    permission_list_free(pnode->permissionList);
    dslink_free(pnode);
}
コード例 #19
0
ファイル: msg_subscribe.c プロジェクト: IOT-DSA/sdk-dslink-c
static
void handle_subscribe(RemoteDSLink *link, json_t *sub) {
    const char *path = json_string_value(json_object_get(sub, "path"));
    json_t *jSid = json_object_get(sub, "sid");
    if (!(path && jSid)) {
        return;
    }

    PermissionLevel permissionOnPath = get_permission(path, link->broker->root, link);
    if (permissionOnPath < PERMISSION_READ) {
        return;
    }

    DownstreamNode *reqNode = link->node;



    uint32_t sid = (uint32_t) json_integer_value(jSid);

    json_t *jQos = json_object_get(sub, "qos");
    uint8_t qos = 0;

    if (json_is_integer(jQos)) {
        qos = (uint8_t) json_integer_value(jQos);
    }

    // TODO check if sid or path already exist

    ref_t *idsub = dslink_map_get(&reqNode->req_sub_sids, &sid);
    ref_t *pathsub = dslink_map_get(&reqNode->req_sub_paths, (void*)path);

    if (idsub && pathsub && idsub->data == pathsub->data) {
        // update qos only
        SubRequester *reqsub = idsub->data;
        broker_update_sub_qos(reqsub, qos);
        return;
    }

    if (idsub) {
        // remove current sub;
        SubRequester *reqsub = idsub->data;
        broker_free_sub_requester(reqsub);
    }
    if (pathsub) {
        // update sid and qos on existing path;
        SubRequester *reqsub = pathsub->data;
        ref_t *pathidsub = dslink_map_remove_get(&reqNode->req_sub_sids, &reqsub->reqSid);
        if (pathidsub) {
            dslink_free(pathidsub);
        }
        reqsub->reqSid = sid;
        dslink_map_set(&reqNode->req_sub_sids, dslink_int_ref(sid), dslink_ref(reqsub, NULL));
        broker_update_sub_qos(reqsub, qos);
        if (json_array_size(reqsub->qosQueue) > 0) {
            // send qos data
            broker_update_sub_req_qos(reqsub);
        } else if (reqsub->stream && reqsub->stream->last_value) {
            broker_update_sub_req(reqsub, reqsub->stream->last_value);
        }
        return;
    }

    SubRequester *subreq = broker_create_sub_requester(reqNode, path, sid, qos, NULL);
    if (qos & 2) {
        serialize_qos_queue(subreq, 0);
    }
    broker_add_new_subscription(link->broker, subreq);
}
コード例 #20
0
ファイル: handshake.c プロジェクト: ghalwasi/c-mlib
int broker_handshake_handle_ws(Broker *broker,
                               Client *client,
                               const char *dsId,
                               const char *auth,
                               const char *wsAccept) {

    ref_t *oldDsId = NULL;
    ref_t *ref = dslink_map_remove_get(&broker->client_connecting,
                                       (char *) dsId);
    if (!ref) {
        return 1;
    }
    RemoteDSLink *link = ref->data;
    dslink_decref(ref);
    if (link->name) {
        dslink_map_remove(&broker->client_connecting,
                          (char *) link->name);
    }
    if (!(auth && link->auth->pubKey)) {
        return 1;
    }

    uv_timer_t *ping_timer = NULL;
    int ret = 0;
    { // Perform auth check
        char expectedAuth[90];
        if (dslink_handshake_gen_auth_key(&link->auth->tempKey,
                                          link->auth->pubKey,
                                          link->auth->salt,
                                          (unsigned char *) expectedAuth,
                                          sizeof(expectedAuth)) != 0) {
            ret = 1;
            goto exit;
        }

        if (strcmp(expectedAuth, auth) != 0) {
            ret = 1;
            goto exit;
        }
    }

    DownstreamNode *node = NULL;
    int pendingUpdateList = 0;
    { // Handle retrieval of the downstream node
        ref = dslink_map_get(broker->downstream->children,
                                    (char *) link->name);
        if (!ref) {
            node = broker_init_downstream_node(broker->downstream, link->name);
            if (!node) {
                ret = 1;
                goto exit;
            }
            oldDsId = dslink_ref(dslink_strdup(dsId), dslink_free);
            if (broker->downstream->list_stream) {
                pendingUpdateList = 1;
            }
            broker_downstream_nodes_changed(broker);
        } else {
            node = ref->data;
            oldDsId = node->dsId;
        }
    }

    if (node->link) {
        Client *c = node->link->client;
        broker_close_link(node->link);
        uv_poll_t *poll = c->poll;
        dslink_socket_free(c->sock);
        dslink_free(c);
        uv_close((uv_handle_t *) poll, broker_free_handle);
    }
    
    // add permission group to link
    json_t *group = json_object_get(node->meta, "$$group");
    permission_groups_load(&link->permission_groups, dsId, json_string_value(group));

    link->client = client;
    link->dsId = oldDsId;
    link->node = node;
    node->dsId = oldDsId;
    client->sock_data = link;
    json_object_set_new(node->meta, "$$dsId", json_string_nocheck(dsId));

    wslay_event_context_ptr ws;
    if (wslay_event_context_server_init(&ws,
                                        broker_ws_callbacks(),
                                        link) != 0) {
        ret = 1;
        goto exit;
    }
    link->ws = ws;
    broker_ws_send_init(client->sock, wsAccept);

    ping_timer = dslink_malloc(sizeof(uv_timer_t));
    ping_timer->data = link;
    uv_timer_init(link->client->poll->loop, ping_timer);
    uv_timer_start(ping_timer, dslink_handle_ping, 1000, 30000);
    link->pingTimerHandle = ping_timer;

    // set the ->link and update all existing stream
    broker_dslink_connect(node, link);

    if (pendingUpdateList) {
        update_list_child(broker->downstream,
                          broker->downstream->list_stream,
                          link->name);
    }

    log_info("DSLink `%s` has connected\n", dsId);
exit:
    mbedtls_ecdh_free(&link->auth->tempKey);
    dslink_free((void *) link->auth->pubKey);
    dslink_free(link->auth);
    link->auth = NULL;
    if (ret != 0) {
        dslink_map_free(&link->requester_streams);
        dslink_map_free(&link->responder_streams);
        dslink_free((char *)link->path);
        dslink_free(link);

        if (ping_timer) {
            uv_timer_stop(ping_timer);
            uv_close((uv_handle_t *) ping_timer, broker_free_handle);
        }
    }

    return ret;
}
コード例 #21
0
ファイル: handshake.c プロジェクト: ghalwasi/c-mlib
json_t *broker_handshake_handle_conn(Broker *broker,
                                     const char *dsId,
                                     const char *token,
                                     json_t *handshake) {
    if (dslink_map_contains(&broker->client_connecting, (void *) dsId)) {
        ref_t *ref = dslink_map_remove_get(&broker->client_connecting,
                                           (void *) dsId);
        RemoteDSLink *link = ref->data;
        dslink_map_remove(&broker->client_connecting,
                          (void *) link->name);
        broker_remote_dslink_free(link);
        dslink_free(link);
        dslink_decref(ref);
    }

    RemoteDSLink *link = dslink_calloc(1, sizeof(RemoteDSLink));
    json_t *resp = json_object();
    if (!(link && resp)) {
        goto fail;
    }

    if (broker_remote_dslink_init(link) != 0) {
        goto fail;
    }

    link->broker = broker;
    link->auth = dslink_calloc(1, sizeof(RemoteAuth));
    if (!link->auth) {
        goto fail;
    }

    if (dslink_handshake_generate_key_pair(&link->auth->tempKey) != 0) {
        log_err("Failed to create temporary key for DSLink\n");
        goto fail;
    }

    {
        json_t *jsonPubKey = json_object_get(handshake, "publicKey");
        if (!jsonPubKey) {
            goto fail;
        }

        const char *tmp = json_string_value(jsonPubKey);
        if (!tmp) {
            goto fail;
        }
        tmp = dslink_strdup(tmp);
        if (!tmp) {
            goto fail;
        }
        link->auth->pubKey = tmp;
    }

    char tempKey[90];
    size_t tempKeyLen = 0;
    if (dslink_handshake_encode_pub_key(&link->auth->tempKey, tempKey,
                                        sizeof(tempKey), &tempKeyLen) != 0) {
        goto fail;
    }

    if (generate_salt((unsigned char *) link->auth->salt,
                      sizeof(link->auth->salt)) != 0) {
        goto fail;
    }

    json_object_set_new_nocheck(resp, "wsUri", json_string_nocheck("/ws"));
    json_object_set_new_nocheck(resp, "tempKey", json_string_nocheck(tempKey));
    json_object_set_new_nocheck(resp, "salt", json_string_nocheck(link->auth->salt));
    if (json_boolean_value(json_object_get(handshake, "isResponder"))) {
        link->isResponder = 1;
    }

    if (json_boolean_value(json_object_get(handshake, "isRequester"))) {
        link->isRequester = 1;
    }

    json_t *linkData = json_object_get(handshake, "linkData");
    if (json_is_object(linkData)) {
        json_incref(linkData);
        link->linkData = linkData;
    }

    {
        char buf[512] = {0};
        snprintf(buf, sizeof(buf), "/downstream/");
        char *name = buf + sizeof("/downstream/")-1;

        size_t dsIdLen = strlen(dsId);
        if (dsIdLen < 44) {
            goto fail;
        }
        size_t nameLen = dsIdLen - 43;
        if (dsId[nameLen - 1] == '-') {
            nameLen--;
        }
        int nodeExists = 0;
        // find a valid name from broker->client_names
        memcpy(name, dsId, nameLen);
        while (1) {
            ref_t *ref = dslink_map_get(&broker->client_connecting, name);
            if (ref) {
                RemoteDSLink *l = ref->data;
                if (l && l->dsId && strcmp(l->dsId->data, dsId) == 0) {
                    dslink_map_remove(&broker->client_connecting, name);
                    broker_remote_dslink_free(l);
                    break;
                } else {
                    name[nameLen] = dsId[nameLen];
                    nameLen++;
                }
            }
            ref = dslink_map_get(broker->downstream->children,
                                 (void *) name);
            if (ref == NULL) {
                break;
            }
            if (!((DownstreamNode *) ref->data)->dsId || strcmp(dsId, ((DownstreamNode *) ref->data)->dsId->data) == 0) {
                nodeExists = 1;
                break;
            }

            name[nameLen] = dsId[nameLen];
            nameLen++;
        }
        if (!nodeExists && broker_enable_token) {
            if (!token) {
                log_err("Failed to connet, need token\n");
                goto fail;
            }
            BrokerNode* tokenNode = get_token_node(token, dsId);
            if (tokenNode) {
                DownstreamNode *node = broker_init_downstream_node(broker->downstream, name);

                if (json_is_true(json_object_get(node->meta, "$$managed"))) {
                    json_object_set_new_nocheck(node->meta, "$$token", json_string_nocheck(tokenNode->name));
                }

                node->dsId = dslink_str_ref(dsId);
                if (broker->downstream->list_stream) {
                    update_list_child(broker->downstream,
                                      broker->downstream->list_stream,
                                      link->name);
                }

                json_t *group = json_object_get(tokenNode->meta, "$$group");
                if (json_is_string(group)) {
                    json_object_set_nocheck(node->meta, "$$group", group);
                }

                token_used(tokenNode);

                broker_downstream_nodes_changed(broker);
            } else {
                log_err("Invalid token: %s\n", token);
                goto fail;
            }
        }
        json_object_set_new_nocheck(resp, "path", json_string_nocheck(buf));

        link->path = dslink_strdup(buf);
        if (!link->path) {
            goto fail;
        }
        link->name = link->path + sizeof("/downstream/") - 1;

        // add to connecting map with the name
        if (dslink_map_set(&broker->client_connecting,
                           dslink_ref((void *) link->name, NULL),
                           dslink_ref(link, NULL)) != 0) {
            dslink_free((void *) link->path);
            goto fail;
        }
    }

    {
        ref_t *tmp = dslink_ref(dslink_strdup(dsId), dslink_free);
        if (!tmp) {
            goto fail;
        }
        // add to connecting map with dsId
        if (dslink_map_set(&broker->client_connecting, tmp,
                           dslink_ref(link, NULL)) != 0) {
            dslink_free(tmp);
            goto fail;
        }
    }

    return resp;
fail:
    if (link) {
        broker_remote_dslink_free(link);
        dslink_free((void *) link->path);
        dslink_free(link);
    }
    DSLINK_CHECKED_EXEC(json_decref, resp);
    return NULL;
}
コード例 #22
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;
}
コード例 #23
0
ファイル: map.c プロジェクト: IOT-DSA/sdk-dslink-c
static
int dslink_map_get_raw_node(Map *map, MapNode **node, ref_t *key) {
    int ret = 0;
    size_t len = map->key_len_calc(key->data);
    size_t index = dslink_map_index_of_key(map, key->data, len);
    *node = map->table[index];
    if (!(*node)) {
        *node = map->table[index] = dslink_malloc(sizeof(MapNode));
        if (*node) {
            (*node)->entry = dslink_malloc(sizeof(MapEntry));
            if (!(*node)->entry) {
                map->table[index] = NULL;
                dslink_free(*node);
                *node = NULL;
                goto exit;
            }
            (*node)->entry->node = *node;
            (*node)->entry->key = key;
            (*node)->entry->value = NULL;

            (*node)->next = NULL;
            (*node)->prev = NULL;
        }
    } else {
        while (1) {
            if (map->cmp((*node)->entry->key->data, key->data, len) == 0) {
                dslink_decref((*node)->entry->key);
                (*node)->entry->key = key;
                return 1;
            }
            MapNode *tmp = (*node)->next;
            if (tmp == NULL) {
                tmp = dslink_malloc(sizeof(MapNode));
                if (!tmp) {
                    *node = NULL;
                    break;
                }
                tmp->entry = dslink_malloc(sizeof(MapEntry));
                if (!tmp->entry) {
                    dslink_free(*node);
                    *node = NULL;
                    break;
                }

                tmp->entry->key = key;
                tmp->entry->value = NULL;
                tmp->entry->node = tmp;

                tmp->next = NULL;
                tmp->prev = *node;

                (*node)->next = tmp;
                *node = tmp;
                break;
            }
            *node = tmp;
        }
    }

exit:
    if (!(*node)) {
        return DSLINK_ALLOC_ERR;
    }
    map->size++;
    list_insert_node(&map->list, (*node)->entry);
    return ret;
}
コード例 #24
0
ファイル: ws.c プロジェクト: IOT-DSA/sdk-dslink-c
int dslink_handshake_connect_ws(Url *url,
                                mbedtls_ecdh_context *key,
                                const char *uri,
                                const char *tempKey,
                                const char *salt,
                                const char *dsId,
                                const char *token,
                                Socket **sock) {
    *sock = NULL;
    int ret = 0;
    unsigned char auth[90];
    if (tempKey && salt)
    if ((ret = dslink_handshake_gen_auth_key(key, tempKey, salt,
                            auth, sizeof(auth))) != 0) {
        goto exit;
    }

    char req[512];
    size_t reqLen;
    {
        char builtUri[256];
        char * encodedDsId = dslink_str_escape(dsId);
        if (tempKey && salt) {
            snprintf(builtUri, sizeof(builtUri) - 1, "%s?auth=%s&dsId=%s",
                     uri, auth, encodedDsId);
        } else {
            // trusted dslink
            snprintf(builtUri, sizeof(builtUri) - 1, "%s?dsId=%s&token=%s",
                     uri, encodedDsId, token);
        }
        dslink_free(encodedDsId);


        char wsKey[32];
        if ((ret = gen_ws_key(wsKey, sizeof(wsKey))) != 0) {
            goto exit;
        }

        reqLen = snprintf(req, sizeof(req), DSLINK_WS_REQ,
                          builtUri, url->host, url->port, wsKey);
    }

    if ((ret = dslink_socket_connect(sock, url->host,
                                     url->port, url->secure)) != 0) {
        *sock = NULL;
        goto exit;
    }

    dslink_socket_write(*sock, req, reqLen);

    char buf[1024];
    size_t len = 0;
    memset(buf, 0, sizeof(buf));
    while (len < (sizeof(buf) - 1)) {
        // Read 1 byte at a time to ensure that we don't accidentally
        // read web socket data
        int read = dslink_socket_read(*sock, buf + len, 1);
        if (read <= 0) {
            goto exit;
        }
        if (buf[len++] == '\n' && strstr(buf, "\r\n\r\n")) {
            if (!strstr(buf, "101 Switching Protocols")) {
                ret = DSLINK_HANDSHAKE_INVALID_RESPONSE;
            } if (strstr(buf, "401 Unauthorized")) {
                ret = DSLINK_HANDSHAKE_UNAUTHORIZED;
            }
            goto exit;
        }
    }

    // Failed to find the end of the HTTP response
    ret = DSLINK_HANDSHAKE_INVALID_RESPONSE;
exit:
    if (ret != 0 && *sock) {
        dslink_socket_close(*sock);
        *sock = NULL;
    }
    return ret;
}
コード例 #25
0
static
void free_stream(void* p) {
    Stream *stream = p;
    dslink_free((void*)stream->path);
    dslink_free(stream);
}