int virtual_stream_get_data(VirtualStream * stream, char * buf, size_t buf_size, size_t * data_size, int * eos) { size_t len; assert(stream->magic == STREAM_MAGIC); len = (stream->buf_inp + stream->buf_len - stream->buf_out) % stream->buf_len; if (len > buf_size) { len = buf_size; *eos = 0; } else { *eos = stream->eos_inp; } *data_size = len; if (*eos) stream->eos_out = 1; if (stream->buf_out + len <= stream->buf_len) { memcpy(buf, stream->buf + stream->buf_out, len); } else { size_t x = stream->buf_len - stream->buf_out; size_t y = len - x; memcpy(buf, stream->buf + stream->buf_out, x); memcpy(buf + x, stream->buf, y); } if (stream->access & VS_ENABLE_REMOTE_WRITE) { LINK * l; for (l = stream->clients.next; l != &stream->clients; l = l->next) { StreamClient * client = stream2client(l); if (!list_is_empty(&client->write_requests)) { WriteRequest * r = client2write_request(client->write_requests.next); size_t done = 0; int error = 0; if (virtual_stream_add_data(client->stream, r->data + r->offs, r->size - r->offs, &done, r->eos) < 0) error = errno; r->offs += done; if (error || r->offs >= r->size) { delete_write_request(r, error); } while (error && !list_is_empty(&client->write_requests)) { r = client2write_request(client->write_requests.next); delete_write_request(r, ERR_COMMAND_CANCELLED); } } } } if ((stream->access & VS_ENABLE_REMOTE_READ) == 0 && len > 0) { stream->buf_out = (stream->buf_out + len) % stream->buf_len; assert(!*eos || stream->buf_out == stream->buf_inp); if (!stream->space_available_posted) { post_event(notify_space_available, stream); stream->space_available_posted = 1; } } return 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); } }