Beispiel #1
0
int virtual_stream_read(Channel * c, char * token, char * id, size_t size) {
    int err = 0;
    StreamClient * client = find_client(id, c);

    if (client == NULL) err = errno;
    if (!err && (client->stream->access & VS_ENABLE_REMOTE_READ) == 0) err = ERR_UNSUPPORTED;

    if (err == 0) {
        VirtualStream * stream = client->stream;
        if (client->pos == stream->pos && !stream->eos_inp) {
            ReadRequest * r = (ReadRequest *)loc_alloc_zero(sizeof(ReadRequest));
            list_init(&r->link_client);
            r->client = client;
            r->size = size;
            strlcpy(r->token, token, sizeof(r->token));
            list_add_last(&r->link_client, &client->read_requests);
        }
        else {
            assert(list_is_empty(&client->read_requests));
            assert(client->channel == c);
            send_read_reply(client, token, size);
            advance_stream_buffer(stream);
        }
    }
    else errno = err;

    return err == 0 ? 0 : -1;
}
Beispiel #2
0
int virtual_stream_add_data(VirtualStream * stream, char * buf, size_t buf_size, size_t * data_size, int eos) {
    int err = 0;

    assert(stream->magic == STREAM_MAGIC);
    if (stream->eos_inp) err = ERR_EOF;

    if (!err) {
        size_t len = (stream->buf_out + stream->buf_len - stream->buf_inp - 1) % stream->buf_len;
        assert(len < stream->buf_len);
        if (buf_size < len) len = buf_size;
        if (stream->buf_inp + len <= stream->buf_len) {
            memcpy(stream->buf + stream->buf_inp, buf, len);
        }
        else {
            size_t x = stream->buf_len - stream->buf_inp;
            size_t y = len - x;
            memcpy(stream->buf + stream->buf_inp, buf, x);
            memcpy(stream->buf, buf + x, y);
        }
        stream->buf_inp = (stream->buf_inp + len) % stream->buf_len;
        stream->pos += len;
        *data_size = len;
        if (eos && buf_size == len) stream->eos_inp = 1;
    }

    if (stream->access & VS_ENABLE_REMOTE_READ) {
        if (!err && (stream->eos_inp || *data_size > 0)) {
            LINK * l;
            for (l = stream->clients.next; l != &stream->clients; l = l->next) {
                StreamClient * client = stream2client(l);
                while (!list_is_empty(&client->read_requests) && (client->pos < stream->pos || stream->eos_inp)) {
                    ReadRequest * r = client2read_request(client->read_requests.next);
                    list_remove(&r->link_client);
                    send_read_reply(client, r->token, r->size);
                    loc_free(r);
                }
            }
            advance_stream_buffer(stream);
        }
    }
    else if (!stream->data_available_posted) {
        post_event(notify_data_available, stream);
        stream->data_available_posted = 1;
    }

    errno = err;
    return err ? -1 : 0;
}
static void command_read(char * token, Channel * c) {
    char id[256];
    size_t size = 0;
    StreamClient * client = NULL;
    int err = 0;

    json_read_string(&c->inp, id, sizeof(id));
    if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
    size = json_read_ulong(&c->inp);
    if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
    if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);

    client = find_client(id, c);
    if (client == NULL) err = errno;
    if (!err && (client->stream->access & VS_ENABLE_REMOTE_READ) == 0) err = ERR_UNSUPPORTED;

    if (err == 0) {
        VirtualStream * stream = client->stream;
        if (client->pos == stream->pos && !stream->eos) {
            ReadRequest * r = loc_alloc_zero(sizeof(ReadRequest));
            list_init(&r->link_client);
            r->client = client;
            r->size = size;
            strncpy(r->token, token, sizeof(r->token) - 1);
            list_add_last(&r->link_client, &client->read_requests);
        }
        else {
            assert(list_is_empty(&client->read_requests));
            assert(client->channel == c);
            send_read_reply(client, token, size);
            advance_stream_buffer(stream);
        }
    }
    else {
        write_stringz(&c->out, "R");
        write_stringz(&c->out, token);
        write_stringz(&c->out, "null");
        write_errno(&c->out, err);
        json_write_long(&c->out, 0);
        write_stream(&c->out, 0);
        json_write_boolean(&c->out, 0);
        write_stream(&c->out, 0);
        write_stream(&c->out, MARKER_EOM);
    }
}