Ejemplo n.º 1
0
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);
        }
    }

}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
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;
}