コード例 #1
0
ファイル: permission.c プロジェクト: IOT-DSA/sdk-dslink-c
List *permission_list_load(json_t *json) {
    if (!json_is_array(json) || json_array_size(json) == 0) {
        return NULL;
    }
    List *rslt = dslink_calloc(1, sizeof(List));
    list_init(rslt);

    size_t idx;
    json_t *value;
    json_array_foreach(json, idx, value) {
        if (json_array_size(value) == 2) {
            json_t *v0 = json_array_get(value, 0);
            json_t *v1 = json_array_get(value, 1);
            if (json_is_string(v0) && json_is_string(v1)) {
                const char* vc0 = json_string_value(v0);
                const char* vc1 = json_string_value(v1);
                PermissionLevel p = permission_str_level(vc1);
                if (p <= PERMISSION_CONFIG) {
                    PermissionPair * pair = dslink_malloc(sizeof(PermissionPair));
                    pair->group = dslink_strdup(vc0);
                    pair->permission = p;
                    dslink_list_insert(rslt, pair);
                }
            }
        }
    }
    return rslt;
}
コード例 #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
ファイル: utils.c プロジェクト: ghalwasi/c-mlib
char *dslink_strdupl(const char *str, size_t len) {
    if (!str) {
        return NULL;
    }
    char *tmp = dslink_malloc(len + 1);
    if (!tmp) {
        return NULL;
    }
    memcpy(tmp, str, len);
    tmp[len] = '\0';
    return tmp;
}
コード例 #4
0
ファイル: utils.c プロジェクト: ghalwasi/c-mlib
char *dslink_strdup(const char *str) {
    if (!str) {
        return NULL;
    }
    size_t strSize = strlen(str) + 1;
    char *tmp = dslink_malloc(strSize);
    if (!tmp) {
        return NULL;
    }
    memcpy(tmp, str, strSize);
    return tmp;
}
コード例 #5
0
ファイル: permission.c プロジェクト: IOT-DSA/sdk-dslink-c
void permission_groups_load(PermissionGroups* groups, const char *dsId, const char* str) {
    if (groups->groups) {
        permission_groups_free(groups);
    }
    size_t allocatedLen = 1;
    size_t len = 0;

    if (str) {
        allocatedLen = 4;
        groups->groups = dslink_malloc(sizeof(char*) * allocatedLen);

        const char *start = str;
        const char *end = str - 1;

        do {
            ++end;
            if (*end == ',' || *end == '\0')  {
                if (end > start) {
                    // +1 for current value, +1 for the dsId
                    if (len + 2 > allocatedLen) {
                        allocatedLen *= 2;
                        groups->groups = dslink_realloc(groups->groups, sizeof(char*) * allocatedLen);
                    }
                    groups->groups[len] = dslink_strdupl(start, end - start);
                    ++len;
                }
                start = end + 1;
            }
        }while (*end);
    } else {
        groups->groups = dslink_malloc(sizeof(char*));
    }

    // dsId as a permission group
    groups->groups[len] = dslink_strdup(dsId);
    ++len;

    groups->groupLen = len;
}
コード例 #6
0
ファイル: utils.c プロジェクト: vikasga/sdk-dslink-c
char *dslink_str_escape(const char *data) {
    if (!data) {
        return NULL;
    }
    size_t lenoff = 1;
    const char *search = data;
    while (*search) {
        if (*search <= ',' || *search == '/' || *search == ':' || *search == '=') {
            lenoff += 2;
        }
        ++search;
    }
    char *rslt = dslink_malloc((search-data) + lenoff);

    char *pt = rslt;
    while (*data) {
        if (*data <= ',' || *data == '/' || *data == ':' || *data == '=') {
            *pt = '%';
            *(pt + 1) = encodeBase16((*data)>>4);
            *(pt + 2) = encodeBase16((*data)&0xF);
        } else {
コード例 #7
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);
}
コード例 #8
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;
}
コード例 #9
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;
}
コード例 #10
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;
}