/* Register a QEMU graphical console, and key/mouse handler, * connecting up their events to the frontend */ static int xenfb_register_console(struct xenfb *xenfb) { /* Register our keyboard & mouse handlers */ qemu_add_kbd_event_handler(xenfb_key_event, xenfb); qemu_add_mouse_event_handler(xenfb_mouse_event, xenfb, xenfb->abs_pointer_wanted, "Xen PVFB Mouse"); /* Tell QEMU to allocate a graphical console */ graphic_console_init(xenfb->ds, xenfb_update, xenfb_invalidate, xenfb_screen_dump, xenfb); if (xenfb->ds->dpy_resize_shared) dpy_resize_shared(xenfb->ds, xenfb->width, xenfb->height, xenfb->depth, xenfb->row_stride, xenfb->pixels + xenfb->offset); else dpy_resize(xenfb->ds, xenfb->width, xenfb->height); if (qemu_set_fd_handler2(xc_evtchn_fd(xenfb->evt_xch), NULL, xenfb_dispatch_channel, NULL, xenfb) < 0) return -1; if (qemu_set_fd_handler2(xs_fileno(xenfb->xsh), NULL, xenfb_dispatch_store, NULL, xenfb) < 0) return -1; fprintf(stderr, "Xen Framebuffer registered\n"); return 0; }
static ssize_t nbd_co_send_reply(NBDRequest *req, struct nbd_reply *reply, int len) { NBDClient *client = req->client; int csock = client->sock; ssize_t rc, ret; qemu_co_mutex_lock(&client->send_lock); qemu_set_fd_handler2(csock, nbd_can_read, nbd_read, nbd_restart_write, client); client->send_coroutine = qemu_coroutine_self(); if (!len) { rc = nbd_send_reply(csock, reply); } else { socket_set_cork(csock, 1); rc = nbd_send_reply(csock, reply); if (rc >= 0) { ret = qemu_co_send(csock, req->data, len); if (ret != len) { rc = -EIO; } } socket_set_cork(csock, 0); } client->send_coroutine = NULL; qemu_set_fd_handler2(csock, nbd_can_read, nbd_read, NULL, client); qemu_co_mutex_unlock(&client->send_lock); return rc; }
void vncws_handshake_read(void *opaque) { VncState *vs = opaque; uint8_t *handshake_end; long ret; /* Typical HTTP headers from novnc are 512 bytes, so limiting * total header size to 4096 is easily enough. */ size_t want = 4096 - vs->ws_input.offset; buffer_reserve(&vs->ws_input, want); ret = vnc_client_read_buf(vs, buffer_end(&vs->ws_input), want); if (!ret) { if (vs->csock == -1) { vnc_disconnect_finish(vs); } return; } vs->ws_input.offset += ret; handshake_end = (uint8_t *)g_strstr_len((char *)vs->ws_input.buffer, vs->ws_input.offset, WS_HANDSHAKE_END); if (handshake_end) { qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs); vncws_process_handshake(vs, vs->ws_input.buffer, vs->ws_input.offset); buffer_advance(&vs->ws_input, handshake_end - vs->ws_input.buffer + strlen(WS_HANDSHAKE_END)); } else if (vs->ws_input.offset >= 4096) { VNC_DEBUG("End of headers not found in first 4096 bytes\n"); vnc_client_error(vs); } }
static void unmap_disk(struct td_state *s) { tapdev_info_t *info = s->ring_info; fd_list_entry_t *entry; bdrv_close(s->bs); if (info != NULL && info->mem > 0) munmap(info->mem, getpagesize() * BLKTAP_MMAP_REGION_SIZE); entry = s->fd_entry; *entry->pprev = entry->next; if (entry->next) entry->next->pprev = entry->pprev; qemu_set_fd_handler2(info->fd, NULL, NULL, NULL, NULL); close(info->fd); free(s->fd_entry); free(s->blkif); free(s->ring_info); free(s); return; }
void vncws_handshake_read(void *opaque) { VncState *vs = opaque; uint8_t *handshake_end; long ret; buffer_reserve(&vs->ws_input, 4096); ret = vnc_client_read_buf(vs, buffer_end(&vs->ws_input), 4096); if (!ret) { if (vs->csock == -1) { vnc_disconnect_finish(vs); } return; } vs->ws_input.offset += ret; handshake_end = (uint8_t *)g_strstr_len((char *)vs->ws_input.buffer, vs->ws_input.offset, WS_HANDSHAKE_END); if (handshake_end) { qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs); vncws_process_handshake(vs, vs->ws_input.buffer, vs->ws_input.offset); buffer_advance(&vs->ws_input, handshake_end - vs->ws_input.buffer + strlen(WS_HANDSHAKE_END)); } }
static int vnc_start_vencrypt_handshake(struct VncState *vs) { int ret; if ((ret = gnutls_handshake(vs->tls.session)) < 0) { if (!gnutls_error_is_fatal(ret)) { VNC_DEBUG("Handshake interrupted (blocking)\n"); if (!gnutls_record_get_direction(vs->tls.session)) qemu_set_fd_handler(vs->csock, vnc_tls_handshake_io, NULL, vs); else qemu_set_fd_handler(vs->csock, NULL, vnc_tls_handshake_io, vs); return 0; } VNC_DEBUG("Handshake failed %s\n", gnutls_strerror(ret)); vnc_client_error(vs); return -1; } if (vs->vd->tls.x509verify) { if (vnc_tls_validate_certificate(vs) < 0) { VNC_DEBUG("Client verification failed\n"); vnc_client_error(vs); return -1; } else { VNC_DEBUG("Client verification passed\n"); } } VNC_DEBUG("Handshake done, switching to TLS data mode\n"); vs->tls.wiremode = VNC_WIREMODE_TLS; qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs); start_auth_vencrypt_subauth(vs); return 0; }
int tcp_start_incoming_migration(const char *host_port) { SockAddress addr; int s; if (parse_host_port(&addr, host_port) < 0) { fprintf(stderr, "invalid host/port combination: %s\n", host_port); return -EINVAL; } s = socket_create_inet(SOCKET_STREAM); if (s == -1) return -socket_error(); socket_set_xreuseaddr(s); if (socket_bind(s, &addr) == -1) goto err; if (socket_listen(s, 1) == -1) goto err; qemu_set_fd_handler2(s, NULL, tcp_accept_incoming_migration, NULL, (void *)(unsigned long)s); return 0; err: socket_close(s); return -socket_error(); }
static void tcp_accept_incoming_migration(void *opaque) { struct sockaddr_in addr; socklen_t addrlen = sizeof(addr); int s = (unsigned long)opaque; QEMUFile *f; int c; do { c = qemu_accept(s, (struct sockaddr *)&addr, &addrlen); } while (c == -1 && socket_error() == EINTR); DPRINTF("accepted migration\n"); if (c == -1) { fprintf(stderr, "could not accept migration connection\n"); return; } f = qemu_fopen_socket(c); if (f == NULL) { fprintf(stderr, "could not qemu_fopen socket\n"); goto out; } process_incoming_migration(f); qemu_fclose(f); out: qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL); close(s); close(c); }
int migrate_fd_cleanup(FdMigrationState *s) { int ret = 0; qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); if (s->file) { DPRINTF("closing file\n"); if (qemu_fclose(s->file) != 0) { ret = -1; } s->file = NULL; } else { if (s->mon) { monitor_resume(s->mon); } } if (s->fd != -1) { close(s->fd); s->fd = -1; } return ret; }
int tcp_start_incoming_migration(const char *host_port) { struct sockaddr_in addr; int val; int s; if (parse_host_port(&addr, host_port) < 0) { fprintf(stderr, "invalid host/port combination: %s\n", host_port); return -EINVAL; } s = socket(PF_INET, SOCK_STREAM, 0); if (s == -1) return -socket_error(); val = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) goto err; if (listen(s, 1) == -1) goto err; qemu_set_fd_handler2(s, NULL, tcp_accept_incoming_migration, NULL, (void *)(unsigned long)s); return 0; err: close(s); return -socket_error(); }
static void tcp_wait_for_connect(void *opaque) { FdMigrationState *s = opaque; int val, ret; socklen_t valsize = sizeof(val); dprintf("connect completed\n"); do { ret = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, (char *)&val, &valsize); } while (ret == -1 && (s->get_error(s)) == EINTR); if (ret < 0) { migrate_fd_error(s); return; } qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); if (val == 0) migrate_fd_connect(s); else { dprintf("error connecting %d\n", val); migrate_fd_error(s); } }
static int qemu_event_init(void) { int err; int fds[2]; err = pipe(fds); if (err == -1) return -errno; err = fcntl_setfl(fds[0], O_NONBLOCK); if (err < 0) goto fail; err = fcntl_setfl(fds[1], O_NONBLOCK); if (err < 0) goto fail; qemu_set_fd_handler2(fds[0], NULL, qemu_event_read, NULL, (void *)(unsigned long)fds[0]); io_thread_fd = fds[1]; return 0; fail: close(fds[0]); close(fds[1]); return err; }
static void fd_accept_incoming_migration(void *opaque) { QEMUFile *f = opaque; qemu_set_fd_handler2(qemu_get_fd(f), NULL, NULL, NULL, NULL); process_incoming_migration(f); }
static int qemu_event_init(void) { int err; int fds[2]; err = qemu_eventfd(fds); if (err == -1) { return -errno; } err = fcntl_setfl(fds[0], O_NONBLOCK); if (err < 0) { goto fail; } err = fcntl_setfl(fds[1], O_NONBLOCK); if (err < 0) { goto fail; } qemu_set_fd_handler2(fds[0], NULL, qemu_event_read, NULL, (void *)(intptr_t)fds[0]); io_thread_fd = fds[1]; return 0; fail: close(fds[0]); close(fds[1]); return err; }
static int vncws_start_tls_handshake(struct VncState *vs) { int ret = gnutls_handshake(vs->ws_tls.session); if (ret < 0) { if (!gnutls_error_is_fatal(ret)) { VNC_DEBUG("Handshake interrupted (blocking)\n"); if (!gnutls_record_get_direction(vs->ws_tls.session)) { qemu_set_fd_handler(vs->csock, vncws_tls_handshake_io, NULL, vs); } else { qemu_set_fd_handler(vs->csock, NULL, vncws_tls_handshake_io, vs); } return 0; } VNC_DEBUG("Handshake failed %s\n", gnutls_strerror(ret)); vnc_client_error(vs); return -1; } VNC_DEBUG("Handshake done, switching to TLS data mode\n"); vs->ws_tls.wiremode = VNC_WIREMODE_TLS; qemu_set_fd_handler2(vs->csock, NULL, vncws_handshake_read, NULL, vs); return 0; }
int migrate_fd_close(void *opaque) { FdMigrationState *s = opaque; qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); return s->close(s); }
int migrate_fd_cleanup(FdMigrationState *s) { int ret = 0; qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); if (s->file) { DPRINTF("closing file\n"); if (qemu_fclose(s->file) != 0) { ret = -1; } s->file = NULL; } if (s->fd != -1) close(s->fd); /* Don't resume monitor until we've flushed all of the buffers */ if (s->mon) { monitor_resume(s->mon); } s->fd = -1; return ret; }
static void unix_accept_incoming_migration(void *opaque) { struct sockaddr_un addr; socklen_t addrlen = sizeof(addr); int s = (intptr_t)opaque; QEMUFile *f; int c, err; do { c = qemu_accept(s, (struct sockaddr *)&addr, &addrlen); err = errno; } while (c < 0 && err == EINTR); qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL); close(s); DPRINTF("accepted migration\n"); if (c < 0) { error_report("could not accept migration connection (%s)", strerror(err)); return; } f = qemu_fopen_socket(c, "rb"); if (f == NULL) { error_report("could not qemu_fopen socket"); goto out; } process_incoming_migration(f); return; out: close(c); }
static int qemu_signal_init(void) { int sigfd; sigset_t set; /* * SIG_IPI must be blocked in the main thread and must not be caught * by sigwait() in the signal thread. Otherwise, the cpu thread will * not catch it reliably. */ sigemptyset(&set); sigaddset(&set, SIG_IPI); sigaddset(&set, SIGIO); sigaddset(&set, SIGALRM); sigaddset(&set, SIGBUS); pthread_sigmask(SIG_BLOCK, &set, NULL); sigdelset(&set, SIG_IPI); sigfd = qemu_signalfd(&set); if (sigfd == -1) { fprintf(stderr, "failed to create signalfd\n"); return -errno; } fcntl_setfl(sigfd, O_NONBLOCK); qemu_set_fd_handler2(sigfd, NULL, sigfd_handler, NULL, (void *)(intptr_t)sigfd); return 0; }
void migrate_fd_put_notify(void *opaque) { FdMigrationState *s = opaque; qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); qemu_file_put_notify(s->file); }
static void exec_accept_incoming_migration(void *opaque) { QEMUFile *f = opaque; process_incoming_migration(f); qemu_set_fd_handler2(qemu_stdio_fd(f), NULL, NULL, NULL, NULL); qemu_fclose(f); }
static void net_socket_update_fd_handler(NetSocketState *s) { qemu_set_fd_handler2(s->fd, s->read_poll ? net_socket_can_send : NULL, s->read_poll ? s->send_fn : NULL, s->write_poll ? net_socket_writable : NULL, s); }
static void tap_update_fd_handler(TAPState *s) { qemu_set_fd_handler2(s->fd, s->read_poll ? tap_can_send : NULL, s->read_poll ? tap_send : NULL, s->write_poll ? tap_writable : NULL, s); }
int unix_connect_opts(QemuOpts *opts, Error **errp, NonBlockingConnectHandler *callback, void *opaque) { struct sockaddr_un un; const char *path = qemu_opt_get(opts, "path"); ConnectState *connect_state = NULL; int sock, rc; if (path == NULL) { error_setg(errp, "unix connect: no path specified"); return -1; } sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); if (sock < 0) { error_setg_errno(errp, errno, "Failed to create socket"); return -1; } if (callback != NULL) { connect_state = g_malloc0(sizeof(*connect_state)); connect_state->callback = callback; connect_state->opaque = opaque; qemu_set_nonblock(sock); } memset(&un, 0, sizeof(un)); un.sun_family = AF_UNIX; snprintf(un.sun_path, sizeof(un.sun_path), "%s", path); /* connect to peer */ do { rc = 0; if (connect(sock, (struct sockaddr *) &un, sizeof(un)) < 0) { rc = -socket_error(); } } while (rc == -EINTR); if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) { connect_state->fd = sock; qemu_set_fd_handler2(sock, NULL, NULL, wait_for_connect, connect_state); return sock; } else if (rc >= 0) { /* non blocking socket immediate success, call callback */ if (callback != NULL) { callback(sock, NULL, opaque); } } if (rc < 0) { error_setg_errno(errp, -rc, "Failed to connect socket"); close(sock); sock = -1; } g_free(connect_state); return sock; }
MigrationState *tcp_start_outgoing_migration(const char *host_port, int64_t bandwidth_limit, int detach, int blk, int inc) { struct sockaddr_in addr; FdMigrationState *s; int ret; if (parse_host_port(&addr, host_port) < 0) return NULL; s = qemu_mallocz(sizeof(*s)); s->get_error = socket_errno; s->write = socket_write; s->close = tcp_close; s->mig_state.cancel = migrate_fd_cancel; s->mig_state.get_status = migrate_fd_get_status; s->mig_state.release = migrate_fd_release; s->mig_state.blk = blk; s->mig_state.shared = inc; s->state = MIG_STATE_ACTIVE; s->mon_resume = NULL; s->bandwidth_limit = bandwidth_limit; s->fd = socket(PF_INET, SOCK_STREAM, 0); if (s->fd == -1) { qemu_free(s); return NULL; } socket_set_nonblock(s->fd); if (!detach) migrate_fd_monitor_suspend(s); do { ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr)); if (ret == -1) ret = -(s->get_error(s)); if (ret == -EINPROGRESS || ret == -EWOULDBLOCK) qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s); } while (ret == -EINTR); if (ret < 0 && ret != -EINPROGRESS && ret != -EWOULDBLOCK) { dprintf("connect failed\n"); close(s->fd); qemu_free(s); return NULL; } else if (ret >= 0) migrate_fd_connect(s); return &s->mig_state; }
static void vnic_update_fd_handler(VNICState *vsp) { qemu_set_fd_handler2(vsp->vns_fd, vsp->vns_rpoll ? vnic_can_send : NULL, vsp->vns_rpoll ? vnic_send : NULL, vsp->vns_wpoll ? vnic_writable : NULL, vsp); }
static void migrate_fd_put_notify(void *opaque) { MigrationState *s = opaque; qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); qemu_file_put_notify(s->file); if (s->file && qemu_file_get_error(s->file)) { migrate_fd_error(s); } }
static void nbd_client_close(NBDClient *client) { qemu_set_fd_handler2(client->sock, NULL, NULL, NULL, NULL); close(client->sock); client->sock = -1; if (client->close) { client->close(client); } nbd_client_put(client); }
static void migrate_fd_get_notify(void *opaque) { FdMigrationState *s = opaque; qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); qemu_file_get_notify(s->file); if (qemu_file_has_error(s->file)) { migrate_ft_trans_error(s); } }
int migrate_fd_close(void *opaque) { FdMigrationState *s = opaque; if (s->mon) { monitor_resume(s->mon); } qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); return s->close(s); }