static void read_stream_done(Channel *c, void *client_data, int error) { PortConnection * conn = ((PortReadInfo *) client_data)->conn; int idx = ((PortReadInfo *) client_data)->idx; size_t read_size = 0; conn->pending_read_request &= ~(1 << idx); if (error) { trace(LOG_ALWAYS, "Reply error %d: %s\n", error, errno_to_str(error)); read_packet_callback(conn, error, idx, 0); } else { int end; InputStream *inp = &conn->server->channel->inp; int ch = peek_stream(inp); if (ch == 'n') { (void) read_stream(inp); if (read_stream(inp) != 'u') goto err_json_syntax; if (read_stream(inp) != 'l') goto err_json_syntax; if (read_stream(inp) != 'l') goto err_json_syntax; } else { JsonReadBinaryState state; json_read_binary_start(&state, inp); for (;;) { size_t rd = json_read_binary_data(&state, conn->read_buffer[idx] + read_size, sizeof conn->read_buffer[idx]); if (rd == 0) break; read_size += rd; } assert(state.size_start <= 0 || read_size == state.size_start); json_read_binary_end(&state); } json_test_char(&c->inp, MARKER_EOA); error = read_errno(inp); (void)json_read_long(inp); if (read_stream(inp) != 0) goto err_json_syntax; end = json_read_boolean(inp); json_test_char(&c->inp, MARKER_EOA); json_test_char(&c->inp, MARKER_EOM); #if 0 if (read_stream(inp) != 0 || read_stream(inp) != MARKER_EOM) goto err_json_syntax; #endif if (end) read_packet_callback(conn, 0, idx, 0); else read_packet_callback(conn, 0, idx, read_size); } return; err_json_syntax: return; }
static void command_write(char * token, Channel * c) { char id[256]; OpenFileInfo * h = NULL; int64_t offset; unsigned long len = 0; JsonReadBinaryState state; static size_t buf_size = 0; static char * buf = NULL; json_read_string(&c->inp, id, sizeof(id)); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); offset = json_read_int64(&c->inp); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); json_read_binary_start(&state, &c->inp); h = find_open_file_info(id); for (;;) { int rd; if (buf_size < len + BUF_SIZE) { buf_size += BUF_SIZE; buf = loc_realloc(buf, buf_size); } rd = json_read_binary_data(&state, buf + len, buf_size - len); if (rd == 0) break; len += rd; } json_read_binary_end(&state); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); if (h == NULL) { reply_write(token, &c->out, EBADF); } else { IORequest * req = create_io_request(token, h, REQ_WRITE); if (offset < 0) { req->info.type = AsyncReqWrite; } else { req->info.type = AsyncReqSeekWrite; req->info.u.fio.offset = (off_t)offset; } req->info.u.fio.fd = h->file; req->info.u.fio.bufp = loc_alloc(len); req->info.u.fio.bufsz = len; memcpy(req->info.u.fio.bufp, buf, len); post_io_requst(h); } }
static void command_write(char * token, Channel * c) { char id[256]; StreamClient * client = NULL; long size = 0; long offs = 0; char * data = 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_long(&c->inp); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); client = find_client(id, c); if (client == NULL) err = errno; if (!err && (client->stream->access & VS_ENABLE_REMOTE_WRITE) == 0) err = ERR_UNSUPPORTED; { JsonReadBinaryState state; unsigned data_pos = 0; if (!err && !list_is_empty(&client->write_requests)) data = loc_alloc(size); json_read_binary_start(&state, &c->inp); for (;;) { if (data != NULL) { size_t rd = json_read_binary_data(&state, data + data_pos, size - offs - data_pos); if (rd == 0) break; data_pos += rd; } else { char buf[256]; size_t rd = json_read_binary_data(&state, buf, sizeof(buf)); if (rd == 0) break; if (!err) { size_t done = 0; if (virtual_stream_add_data(client->stream, buf, rd, &done, 0) < 0) err = errno; assert(done <= rd); offs += done; if (!err && done < rd) { data = loc_alloc(size - offs); memcpy(data, buf + done, rd - done); data_pos = rd - done; } } } } json_read_binary_end(&state); } if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); if (data != NULL) { WriteRequest * r = loc_alloc_zero(sizeof(WriteRequest)); list_init(&r->link_client); r->client = client; r->data = data; r->size = size - offs; strncpy(r->token, token, sizeof(r->token) - 1); list_add_last(&r->link_client, &client->write_requests); } else { write_stringz(&c->out, "R"); write_stringz(&c->out, token); write_errno(&c->out, err); write_stream(&c->out, MARKER_EOM); } }
static void safe_memory_set(void * parm) { MemoryCommandArgs * args = (MemoryCommandArgs *)parm; Channel * c = args->c; Context * ctx = args->ctx; if (!is_channel_closed(c)) { Trap trap; if (set_trap(&trap)) { InputStream * inp = &c->inp; OutputStream * out = &c->out; char * token = args->token; ContextAddress addr0 = args->addr; ContextAddress addr = args->addr; unsigned long size = 0; char buf[BUF_SIZE]; int err = 0; MemoryErrorInfo err_info; JsonReadBinaryState state; memset(&err_info, 0, sizeof(err_info)); if (ctx->exiting || ctx->exited) err = ERR_ALREADY_EXITED; json_read_binary_start(&state, inp); for (;;) { int rd = json_read_binary_data(&state, buf, sizeof(buf)); if (rd == 0) break; if (err == 0) { /* TODO: word size, mode */ if (context_write_mem(ctx, addr, buf, rd) < 0) { err = errno; #if ENABLE_ExtendedMemoryErrorReports context_get_mem_error_info(&err_info); #endif } else { addr += rd; } } size += rd; } json_read_binary_end(&state); json_test_char(inp, MARKER_EOA); json_test_char(inp, MARKER_EOM); send_event_memory_changed(ctx, addr0, size); write_stringz(out, "R"); write_stringz(out, token); write_errno(out, err); if (err == 0) { write_stringz(out, "null"); } else { write_ranges(out, addr0, (int)(addr - addr0), BYTE_CANNOT_WRITE, &err_info); } write_stream(out, MARKER_EOM); clear_trap(&trap); } else { trace(LOG_ALWAYS, "Exception in Memory.set: %s", errno_to_str(trap.error)); channel_close(c); } } channel_unlock(c); context_unlock(ctx); loc_free(args); }
int virtual_stream_write(Channel * c, char * token, char * id, size_t size, InputStream * inp) { char * data = NULL; int err = 0; long offs = 0; StreamClient * client = find_client(id, c); if (client == NULL) err = errno; if (!err && (client->stream->access & VS_ENABLE_REMOTE_WRITE) == 0) err = ERR_UNSUPPORTED; { JsonReadBinaryState state; size_t data_pos = 0; if (!err && !list_is_empty(&client->write_requests)) data = (char *)loc_alloc(size); json_read_binary_start(&state, inp); for (;;) { if (data != NULL) { size_t rd = json_read_binary_data(&state, data + data_pos, size - offs - data_pos); if (rd == 0) break; data_pos += rd; } else { char buf[256]; size_t rd = json_read_binary_data(&state, buf, sizeof(buf)); if (rd == 0) break; if (!err) { size_t done = 0; if (virtual_stream_add_data(client->stream, buf, rd, &done, 0) < 0) err = errno; assert(done <= rd); offs += done; if (!err && done < rd) { data = (char *)loc_alloc(size - offs); memcpy(data, buf + done, rd - done); data_pos = rd - done; } } } } json_read_binary_end(&state); } if (data != NULL) { WriteRequest * r = (WriteRequest *)loc_alloc_zero(sizeof(WriteRequest)); list_init(&r->link_client); r->client = client; r->data = data; r->size = size - offs; strlcpy(r->token, token, sizeof(r->token)); list_add_last(&r->link_client, &client->write_requests); } else if (err == 0) { write_stringz(&c->out, "R"); write_stringz(&c->out, token); write_errno(&c->out, err); write_stream(&c->out, MARKER_EOM); } if (err != 0) errno = err; return err == 0 ? 0 : -1; }