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); }
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; }
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; } }
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); } }
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; }
void *spice_memdup(const void *mem, size_t n_bytes) { void *copy; copy = spice_malloc(n_bytes); memcpy(copy, mem, n_bytes); return copy; }
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); }
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); }
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; }
/* 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); }
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); }
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; }
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; }
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; }
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); }
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); }
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; }
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); }
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; }
/* 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); }
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; } }
/* 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); }