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);
}
Exemple #5
0
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;
}