Example #1
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 delete_client(StreamClient * client) {
    VirtualStream * stream = client->stream;
    Trap trap;
    LINK * n;

    assert(stream->ref_cnt > 0);
    if (set_trap(&trap)) {
        send_event_stream_disposed(&client->channel->out, stream);
        clear_trap(&trap);
    }
    else {
        trace(LOG_ALWAYS, "Exception sending stream deleted event: %d %s",
              trap.error, errno_to_str(trap.error));
    }
    list_remove(&client->link_hash);
    list_remove(&client->link_stream);
    list_remove(&client->link_all);
    for (n = client->read_requests.next; n != &client->read_requests;) {
        ReadRequest * r = client2read_request(n);
        n = n->next;
        delete_read_request(r);
    }
    for (n = client->write_requests.next; n != &client->write_requests;) {
        WriteRequest * r = client2write_request(n);
        n = n->next;
        delete_write_request(r, ERR_COMMAND_CANCELLED);
    }
    loc_free(client);
    if (--stream->ref_cnt == 0) {
        assert(list_is_empty(&stream->clients));
        assert(stream->deleted);
        post_event(delete_stream, stream);
    }
    else if (stream->access & VS_ENABLE_REMOTE_READ) {
        advance_stream_buffer(stream);
    }
}