Пример #1
0
static void red_dispatcher_set_display_peer(RedChannel *channel, RedClient *client,
                                            RedsStream *stream, int migration,
                                            int num_common_caps, uint32_t *common_caps, int num_caps,
                                            uint32_t *caps)
{
    RedWorkerMessageDisplayConnect payload;
    RedDispatcher *dispatcher;

    spice_debug("%s", "");
    dispatcher = (RedDispatcher *)channel->data;
    payload.client = client;
    payload.stream = stream;
    payload.migration = migration;
    payload.num_common_caps = num_common_caps;
    payload.common_caps = spice_malloc(sizeof(uint32_t)*num_common_caps);
    payload.num_caps = num_caps;
    payload.caps = spice_malloc(sizeof(uint32_t)*num_caps);

    memcpy(payload.common_caps, common_caps, sizeof(uint32_t)*num_common_caps);
    memcpy(payload.caps, caps, sizeof(uint32_t)*num_caps);

    dispatcher_send_message(&dispatcher->dispatcher,
                            RED_WORKER_MESSAGE_DISPLAY_CONNECT,
                            &payload);
}
Пример #2
0
static SmartCardDeviceState *smartcard_device_state_new(SpiceCharDeviceInstance *sin)
{
    SmartCardDeviceState *st;
    SpiceCharDeviceCallbacks chardev_cbs = { NULL, };

    chardev_cbs.read_one_msg_from_device = smartcard_read_msg_from_device;
    chardev_cbs.ref_msg_to_client = smartcard_ref_msg_to_client;
    chardev_cbs.unref_msg_to_client = smartcard_unref_msg_to_client;
    chardev_cbs.send_msg_to_client = smartcard_send_msg_to_client;
    chardev_cbs.send_tokens_to_client = smartcard_send_tokens_to_client;
    chardev_cbs.remove_client = smartcard_remove_client;

    st = spice_new0(SmartCardDeviceState, 1);
    st->chardev_st = spice_char_device_state_create(sin,
                                                    0, /* tokens interval */
                                                    ~0, /* self tokens */
                                                    &chardev_cbs,
                                                    st);
    st->reader_id = VSCARD_UNDEFINED_READER_ID;
    st->reader_added = FALSE;
    st->buf_size = APDUBufSize + sizeof(VSCMsgHeader);
    st->buf = spice_malloc(st->buf_size);
    st->buf_pos = st->buf;
    st->buf_used = 0;
    st->scc = NULL;
    return st;
}
Пример #3
0
static uint8_t *smartcard_channel_alloc_msg_rcv_buf(RedChannelClient *rcc,
                                                    uint16_t type,
                                                    uint32_t size)
{
    SmartCardChannelClient *scc = SPICE_CONTAINEROF(rcc, SmartCardChannelClient, base);

    /* todo: only one reader is actually supported. When we fix the code to support
     * multiple readers, we will porbably associate different devices to
     * differenc channels */
    if (!scc->smartcard_state) {
        scc->msg_in_write_buf = FALSE;
        return spice_malloc(size);
    } else {
        SmartCardDeviceState *st;

        spice_assert(g_smartcard_readers.num == 1);
        st = scc->smartcard_state;
        spice_assert(st->scc || scc->smartcard_state);
        spice_assert(!scc->write_buf);
        scc->write_buf = spice_char_device_write_buffer_get(st->chardev_st, rcc->client, size);

        if (!scc->write_buf) {
            spice_error("failed to allocate write buffer");
            return NULL;
        }
        scc->msg_in_write_buf = TRUE;
        return scc->write_buf->buf;
    }
}
Пример #4
0
static uint8_t *spicevmc_red_channel_alloc_msg_rcv_buf(RedChannelClient *rcc,
                                                       uint16_t type,
                                                       uint32_t size)
{
    SpiceVmcState *state;

    state = SPICE_CONTAINEROF(rcc->channel, SpiceVmcState, channel);

    switch (type) {
    case SPICE_MSGC_SPICEVMC_DATA:
        assert(!state->recv_from_client_buf);

        state->recv_from_client_buf = spice_char_device_write_buffer_get(state->chardev_st,
                                                                         rcc->client,
                                                                         size);
        if (!state->recv_from_client_buf) {
            spice_error("failed to allocate write buffer");
            return NULL;
        }
        return state->recv_from_client_buf->buf;

    default:
        return spice_malloc(size);
    }

}
Пример #5
0
static char *addr_to_string(const char *format,
                            struct sockaddr_storage *sa,
                            socklen_t salen)
{
    char *addr;
    char host[NI_MAXHOST];
    char serv[NI_MAXSERV];
    int err;
    size_t addrlen;

    if ((err = getnameinfo((struct sockaddr *)sa, salen,
                           host, sizeof(host),
                           serv, sizeof(serv),
                           NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
        spice_warning("Cannot resolve address %d: %s",
                      err, gai_strerror(err));
        return NULL;
    }

    /* Enough for the existing format + the 2 vars we're
     * substituting in. */
    addrlen = strlen(format) + strlen(host) + strlen(serv);
    addr = spice_malloc(addrlen + 1);
    snprintf(addr, addrlen, format, host, serv);
    addr[addrlen] = '\0';

    return addr;
}
Пример #6
0
void *spice_memdup(const void *mem, size_t n_bytes)
{
    void *copy;

    copy = spice_malloc(n_bytes);
    memcpy(copy, mem, n_bytes);
    return copy;
}
Пример #7
0
static void spicevmc_port_send_event(RedChannelClient *rcc, uint8_t event)
{
    PortEventPipeItem *item = spice_malloc(sizeof(PortEventPipeItem));

    red_channel_pipe_item_init(rcc->channel, &item->base, PIPE_ITEM_TYPE_PORT_EVENT);
    item->event = event;
    red_channel_client_pipe_add_push(rcc, &item->base);
}
Пример #8
0
void *spice_malloc_n(size_t n_blocks, size_t n_block_bytes)
{
    if (SIZE_OVERFLOWS (n_blocks, n_block_bytes)) {
        MALLOC_ERROR("spice_malloc_n: overflow allocating %lu*%lu bytes",
                     (unsigned long)n_blocks, (unsigned long)n_block_bytes);
    }

    return spice_malloc(n_blocks * n_block_bytes);
}
Пример #9
0
uint8_t *spice_marshaller_reserve_space(SpiceMarshaller *m, size_t size)
{
    MarshallerItem *item;
    SpiceMarshallerData *d;
    uint8_t *res;

    if (size == 0) {
        return NULL;
    }

    d = m->data;

    /* Check current item */
    item = &m->items[m->n_items - 1];
    if (item == d->current_buffer_item &&
        remaining_buffer_size(d) >= size) {
        assert(m->n_items >= 1);
        /* We can piggy back on existing item+buffer */
        res = item->data + item->len;
        item->len += size;
        d->current_buffer_position += size;
        d->total_size += size;
        m->total_size += size;
        return res;
    }

    item = spice_marshaller_add_item(m);

    if (remaining_buffer_size(d) >= size) {
        /* Fits in current buffer */
        item->data = d->current_buffer->data + d->current_buffer_position;
        item->len = size;
        d->current_buffer_position += size;
        d->current_buffer_item = item;
    } else if (size > MARSHALLER_BUFFER_SIZE / 2) {
        /* Large item, allocate by itself */
        item->data = (uint8_t *)spice_malloc(size);
        item->len = size;
        item->free_data = (spice_marshaller_item_free_func)free;
        item->opaque = NULL;
    } else {
        /* Use next buffer */
        if (d->current_buffer->next == NULL) {
            d->current_buffer->next = spice_new(MarshallerBuffer, 1);
            d->current_buffer->next->next = NULL;
        }
        d->current_buffer = d->current_buffer->next;
        d->current_buffer_position = size;
        d->current_buffer_item = item;
        item->data = d->current_buffer->data;
        item->len = size;
    }

    d->total_size += size;
    m->total_size += size;
    return item->data;
}
Пример #10
0
/* coroutine context */
static void spice_channel_send_link(SpiceChannel *channel)
{
    spice_channel *c = channel->priv;
    uint8_t *buffer, *p;
    int protocol, i;

    c->link_hdr.magic = SPICE_MAGIC;
    c->link_hdr.size = sizeof(c->link_msg);

    g_object_get(c->session, "protocol", &protocol, NULL);
    switch (protocol) {
    case 1: /* protocol 1 == major 1, old 0.4 protocol, last active minor */
        c->link_hdr.major_version = 1;
        c->link_hdr.minor_version = 3;
        c->parser = spice_get_server_channel_parser1(c->channel_type, NULL);
        c->marshallers = spice_message_marshallers_get1();
        break;
    case SPICE_VERSION_MAJOR: /* protocol 2 == current */
        c->link_hdr.major_version = SPICE_VERSION_MAJOR;
        c->link_hdr.minor_version = SPICE_VERSION_MINOR;
        c->parser = spice_get_server_channel_parser(c->channel_type, NULL);
        c->marshallers = spice_message_marshallers_get();
        break;
    default:
        g_critical("unknown major %d", protocol);
        return;
    }

    c->link_msg.connection_id = c->connection_id;
    c->link_msg.channel_type  = c->channel_type;
    c->link_msg.channel_id    = c->channel_id;
    c->link_msg.caps_offset   = sizeof(c->link_msg);

    c->link_msg.num_common_caps = c->common_caps->len;
    c->link_msg.num_channel_caps = c->caps->len;
    c->link_hdr.size += (c->link_msg.num_common_caps +
                         c->link_msg.num_channel_caps) * sizeof(uint32_t);

    buffer = spice_malloc(sizeof(c->link_hdr) + c->link_hdr.size);
    p = buffer;

    memcpy(p, &c->link_hdr, sizeof(c->link_hdr)); p += sizeof(c->link_hdr);
    memcpy(p, &c->link_msg, sizeof(c->link_msg)); p += sizeof(c->link_msg);

    for (i = 0; i < c->common_caps->len; i++) {
        *(uint32_t *)p = g_array_index(c->common_caps, uint32_t, i);
        p += sizeof(uint32_t);
    }
    for (i = 0; i < c->caps->len; i++) {
        *(uint32_t *)p = g_array_index(c->caps, uint32_t, i);
        p += sizeof(uint32_t);
    }

    spice_channel_write(channel, buffer, p - buffer);
}
Пример #11
0
static void spicevmc_port_send_init(RedChannelClient *rcc)
{
    SpiceVmcState *state = SPICE_CONTAINEROF(rcc->channel, SpiceVmcState, channel);
    SpiceCharDeviceInstance *sin = state->chardev_sin;
    PortInitPipeItem *item = spice_malloc(sizeof(PortInitPipeItem));

    red_channel_pipe_item_init(rcc->channel, &item->base, PIPE_ITEM_TYPE_PORT_INIT);
    item->name = strdup(sin->portname);
    item->opened = state->port_opened;
    red_channel_client_pipe_add_push(rcc, &item->base);
}
Пример #12
0
char *spice_strdup(const char *str)
{
    char *copy;

    if (str == NULL) {
        return NULL;
    }

    copy = (char *)spice_malloc(strlen(str) + 1);
    strcpy(copy, str);
    return copy;
}
Пример #13
0
char *spice_strndup(const char *str, size_t n_bytes)
{
    char *copy;

    if (str == NULL) {
        return NULL;
    }

    copy = (char *)spice_malloc(n_bytes + 1);
    strncpy(copy, str, n_bytes);
    copy[n_bytes] = 0;
    return copy;
}
Пример #14
0
static SmartCardDeviceState* smartcard_device_state_new()
{
    SmartCardDeviceState *st;

    st = spice_new0(SmartCardDeviceState, 1);
    st->base.wakeup = smartcard_char_device_wakeup;
    st->reader_id = VSCARD_UNDEFINED_READER_ID;
    st->attached = FALSE;
    st->buf_size = APDUBufSize + sizeof(VSCMsgHeader);
    st->buf = spice_malloc(st->buf_size);
    st->buf_pos = st->buf;
    st->buf_used = 0;
    return st;
}
Пример #15
0
static void red_dispatcher_set_cursor_peer(RedChannel *channel, RedClient *client, RedsStream *stream,
                                           int migration, int num_common_caps,
                                           uint32_t *common_caps, int num_caps,
                                           uint32_t *caps)
{
    RedWorkerMessageCursorConnect payload = {0,};
    RedDispatcher *dispatcher = (RedDispatcher *)channel->data;
    spice_printerr("");
    payload.client = client;
    payload.stream = stream;
    payload.migration = migration;
    payload.num_common_caps = num_common_caps;
    payload.common_caps = spice_malloc(sizeof(uint32_t)*num_common_caps);
    payload.num_caps = num_caps;
    payload.caps = spice_malloc(sizeof(uint32_t)*num_caps);

    memcpy(payload.common_caps, common_caps, sizeof(uint32_t)*num_common_caps);
    memcpy(payload.caps, caps, sizeof(uint32_t)*num_caps);

    dispatcher_send_message(&dispatcher->dispatcher,
                            RED_WORKER_MESSAGE_CURSOR_CONNECT,
                            &payload);
}
Пример #16
0
void *spice_malloc_n_m(size_t n_blocks, size_t n_block_bytes, size_t extra_size)
{
    size_t size1, size2;
    if (SIZE_OVERFLOWS (n_blocks, n_block_bytes)) {
        MALLOC_ERROR("spice_malloc_n: overflow allocating %lu*%lu + %lubytes",
                     (unsigned long)n_blocks, (unsigned long)n_block_bytes, (unsigned long)extra_size);
    }
    size1 = n_blocks * n_block_bytes;
    size2 = size1 + extra_size;
    if (size2 < size1) {
        MALLOC_ERROR("spice_malloc_n: overflow allocating %lu*%lu + %lubytes",
                     (unsigned long)n_blocks, (unsigned long)n_block_bytes, (unsigned long)extra_size);
    }
    return spice_malloc(size2);
}
Пример #17
0
bool reds_sasl_handle_auth_mechlen(RedsStream *stream, AsyncReadDone read_cb, void *opaque)
{
    RedsSASL *sasl = &stream->priv->sasl;

    if (sasl->len < 1 || sasl->len > 100) {
        spice_warning("Got bad client mechname len %d", sasl->len);
        return false;
    }

    sasl->mechname = spice_malloc(sasl->len + 1);

    spice_debug("Wait for client mechname");
    reds_stream_async_read(stream, (uint8_t *)sasl->mechname, sasl->len,
                           read_cb, opaque);

    return true;
}
Пример #18
0
static void smartcard_char_device_attach(
    SpiceCharDeviceInstance *char_device, SmartCardChannel *smartcard_channel)
{
    SmartCardDeviceState *st = SPICE_CONTAINEROF(char_device->st, SmartCardDeviceState, base);

    if (st->attached == TRUE) {
        return;
    }
    st->attached = TRUE;
    VSCMsgHeader vheader = {.type = VSC_ReaderAdd, .reader_id=st->reader_id,
        .length=0};
    smartcard_channel_write_to_reader(smartcard_channel, &vheader);
}

static void smartcard_char_device_detach(
    SpiceCharDeviceInstance *char_device, SmartCardChannel *smartcard_channel)
{
    SmartCardDeviceState *st = SPICE_CONTAINEROF(char_device->st, SmartCardDeviceState, base);

    if (st->attached == FALSE) {
        return;
    }
    st->attached = FALSE;
    VSCMsgHeader vheader = {.type = VSC_ReaderRemove, .reader_id=st->reader_id,
        .length=0};
    smartcard_channel_write_to_reader(smartcard_channel, &vheader);
}

static int smartcard_channel_config_socket(RedChannel *channel)
{
    return TRUE;
}

static uint8_t *smartcard_channel_alloc_msg_rcv_buf(RedChannel *channel, SpiceDataHeader *msg_header)
{
    //red_printf("allocing %d bytes", msg_header->size);
    return spice_malloc(msg_header->size);
}

static void smartcard_channel_release_msg_rcv_buf(RedChannel *channel, SpiceDataHeader *msg_header,
                                               uint8_t *msg)
{
    red_printf("freeing %d bytes", msg_header->size);
    free(msg);
}
Пример #19
0
uint8_t *spice_marshaller_linearize(SpiceMarshaller *m, size_t skip_bytes,
                                    size_t *len, int *free_res)
{
    MarshallerItem *item;
    uint8_t *res, *p;
    int i;

    /* Only supported for root marshaller */
    assert(m->data->marshallers == m);

    if (m->n_items == 1) {
        *free_res = FALSE;
        if (m->items[0].len <= skip_bytes) {
            *len = 0;
            return NULL;
        }
        *len = m->items[0].len - skip_bytes;
        return m->items[0].data + skip_bytes;
    }

    *free_res = TRUE;
    res = (uint8_t *)spice_malloc(m->data->total_size - skip_bytes);
    *len = m->data->total_size - skip_bytes;
    p = res;

    do {
        for (i = 0; i < m->n_items; i++) {
            item = &m->items[i];

            if (item->len <= skip_bytes) {
                skip_bytes -= item->len;
                continue;
            }
            memcpy(p, item->data + skip_bytes, item->len - skip_bytes);
            p += item->len - skip_bytes;
            skip_bytes = 0;
        }
        m = m->next;
    } while (m != NULL);

    return res;
}
Пример #20
0
/* coroutine context */
static void spice_channel_recv_link_hdr(SpiceChannel *channel)
{
    spice_channel *c = channel->priv;
    int rc;

    rc = spice_channel_read(channel, &c->peer_hdr, sizeof(c->peer_hdr));
    if (rc != sizeof(c->peer_hdr)) {
        g_critical("incomplete link header (%d/%" G_GSIZE_FORMAT ")",
                   rc, sizeof(c->peer_hdr));
        goto error;
    }
    if (c->peer_hdr.magic != SPICE_MAGIC) {
        g_critical("invalid SPICE_MAGIC!");
        goto error;
    }

    if (c->peer_hdr.major_version != c->link_hdr.major_version) {
        if (c->peer_hdr.major_version == 1) {
            /* enter spice 0.4 mode */
            g_object_set(c->session, "protocol", 1, NULL);
            SPICE_DEBUG("%s: switching to protocol 1 (spice 0.4)", c->name);
            SPICE_CHANNEL_GET_CLASS(channel)->channel_disconnect(channel);
            spice_channel_connect(channel);
            return;
        }
        g_critical("major mismatch (got %d, expected %d)",
                   c->peer_hdr.major_version, c->link_hdr.major_version);
        goto error;
    }

    c->peer_msg = spice_malloc(c->peer_hdr.size);
    c->state = SPICE_CHANNEL_STATE_LINK_MSG;
    return;

error:
    emit_main_context(channel, SPICE_CHANNEL_EVENT, SPICE_CHANNEL_ERROR_LINK);
}
Пример #21
0
void spice_chunks_linearize(SpiceChunks *chunks)
{
    uint8_t *data, *p;
    unsigned int i;

    if (chunks->num_chunks > 1) {
        data = (uint8_t*)spice_malloc(chunks->data_size);
        for (p = data, i = 0; i < chunks->num_chunks; i++) {
            memcpy(p, chunks->chunk[i].data,
                   chunks->chunk[i].len);
            p += chunks->chunk[i].len;
        }
        if (chunks->flags & SPICE_CHUNKS_FLAGS_FREE) {
            for (i = 0; i < chunks->num_chunks; i++) {
                free(chunks->chunk[i].data);
            }
        }
        chunks->num_chunks = 1;
        chunks->flags |= SPICE_CHUNKS_FLAGS_FREE;
        chunks->flags &= ~SPICE_CHUNKS_FLAGS_UNSTABLE;
        chunks->chunk[0].data = data;
        chunks->chunk[0].len = chunks->data_size;
    }
}
Пример #22
0
/* coroutine context */
G_GNUC_INTERNAL
void spice_channel_recv_msg(SpiceChannel *channel,
                            handler_msg_in msg_handler, gpointer data)
{
    spice_channel *c = channel->priv;
    spice_msg_in *in;
    int rc;

    if (!c->msg_in) {
        c->msg_in = spice_msg_in_new(channel);
    }
    in = c->msg_in;

    /* receive message */
    if (in->hpos < sizeof(in->header)) {
        rc = spice_channel_read(channel, (uint8_t*)&in->header + in->hpos,
                                sizeof(in->header) - in->hpos);
        if (rc < 0) {
            g_critical("recv hdr: %s", strerror(errno));
            return;
        }
        in->hpos += rc;
        if (in->hpos < sizeof(in->header))
            return;
        in->data = spice_malloc(in->header.size);
    }
    if (in->dpos < in->header.size) {
        rc = spice_channel_read(channel, in->data + in->dpos,
                                in->header.size - in->dpos);
        if (rc < 0) {
            g_critical("recv msg: %s", strerror(errno));
            return;
        }
        in->dpos += rc;
        if (in->dpos < in->header.size)
            return;
    }

    if (in->header.sub_list) {
        SpiceSubMessageList *sub_list;
        SpiceSubMessage *sub;
        spice_msg_in *sub_in;
        int i;

        sub_list = (SpiceSubMessageList *)(in->data + in->header.sub_list);
        for (i = 0; i < sub_list->size; i++) {
            sub = (SpiceSubMessage *)(in->data + sub_list->sub_messages[i]);
            sub_in = spice_msg_in_sub_new(channel, in, sub);
            sub_in->parsed = c->parser(sub_in->data, sub_in->data + sub_in->dpos,
                                       sub_in->header.type, c->peer_hdr.minor_version,
                                       &sub_in->psize, &sub_in->pfree);
            if (sub_in->parsed == NULL) {
                g_critical("failed to parse sub-message: %s type %d",
                           c->name, sub_in->header.type);
                return;
            }
            msg_handler(channel, sub_in, data);
            spice_msg_in_unref(sub_in);
        }
    }

    /* ack message */
    if (c->message_ack_count) {
        c->message_ack_count--;
        if (!c->message_ack_count) {
            spice_msg_out *out = spice_msg_out_new(channel, SPICE_MSGC_ACK);
            spice_msg_out_send_internal(out);
            spice_msg_out_unref(out);
            c->message_ack_count = c->message_ack_window;
        }
    }

    /* parse message */
    in->parsed = c->parser(in->data, in->data + in->dpos, in->header.type,
                           c->peer_hdr.minor_version, &in->psize, &in->pfree);
    if (in->parsed == NULL) {
        g_critical("failed to parse message: %s type %d",
                   c->name, in->header.type);
        return;
    }

    /* process message */
    c->msg_in = NULL; /* the function is reentrant, reset state */
    msg_handler(channel, in, data);

    /* release message */
    spice_msg_in_unref(in);
}