]> git.proxmox.com Git - mirror_qemu.git/blame - ui/spice-core.c
spice: core bits
[mirror_qemu.git] / ui / spice-core.c
CommitLineData
29b0040b
GH
1/*
2 * Copyright (C) 2010 Red Hat, Inc.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 or
7 * (at your option) version 3 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <spice.h>
19#include <spice-experimental.h>
20
21#include "qemu-common.h"
22#include "qemu-spice.h"
23#include "qemu-timer.h"
24#include "qemu-queue.h"
25#include "monitor.h"
26
27/* core bits */
28
29static SpiceServer *spice_server;
30int using_spice = 0;
31
32struct SpiceTimer {
33 QEMUTimer *timer;
34 QTAILQ_ENTRY(SpiceTimer) next;
35};
36static QTAILQ_HEAD(, SpiceTimer) timers = QTAILQ_HEAD_INITIALIZER(timers);
37
38static SpiceTimer *timer_add(SpiceTimerFunc func, void *opaque)
39{
40 SpiceTimer *timer;
41
42 timer = qemu_mallocz(sizeof(*timer));
43 timer->timer = qemu_new_timer(rt_clock, func, opaque);
44 QTAILQ_INSERT_TAIL(&timers, timer, next);
45 return timer;
46}
47
48static void timer_start(SpiceTimer *timer, uint32_t ms)
49{
50 qemu_mod_timer(timer->timer, qemu_get_clock(rt_clock) + ms);
51}
52
53static void timer_cancel(SpiceTimer *timer)
54{
55 qemu_del_timer(timer->timer);
56}
57
58static void timer_remove(SpiceTimer *timer)
59{
60 qemu_del_timer(timer->timer);
61 qemu_free_timer(timer->timer);
62 QTAILQ_REMOVE(&timers, timer, next);
63 qemu_free(timer);
64}
65
66struct SpiceWatch {
67 int fd;
68 int event_mask;
69 SpiceWatchFunc func;
70 void *opaque;
71 QTAILQ_ENTRY(SpiceWatch) next;
72};
73static QTAILQ_HEAD(, SpiceWatch) watches = QTAILQ_HEAD_INITIALIZER(watches);
74
75static void watch_read(void *opaque)
76{
77 SpiceWatch *watch = opaque;
78 watch->func(watch->fd, SPICE_WATCH_EVENT_READ, watch->opaque);
79}
80
81static void watch_write(void *opaque)
82{
83 SpiceWatch *watch = opaque;
84 watch->func(watch->fd, SPICE_WATCH_EVENT_WRITE, watch->opaque);
85}
86
87static void watch_update_mask(SpiceWatch *watch, int event_mask)
88{
89 IOHandler *on_read = NULL;
90 IOHandler *on_write = NULL;
91
92 watch->event_mask = event_mask;
93 if (watch->event_mask & SPICE_WATCH_EVENT_READ) {
94 on_read = watch_read;
95 }
96 if (watch->event_mask & SPICE_WATCH_EVENT_WRITE) {
97 on_read = watch_write;
98 }
99 qemu_set_fd_handler(watch->fd, on_read, on_write, watch);
100}
101
102static SpiceWatch *watch_add(int fd, int event_mask, SpiceWatchFunc func, void *opaque)
103{
104 SpiceWatch *watch;
105
106 watch = qemu_mallocz(sizeof(*watch));
107 watch->fd = fd;
108 watch->func = func;
109 watch->opaque = opaque;
110 QTAILQ_INSERT_TAIL(&watches, watch, next);
111
112 watch_update_mask(watch, event_mask);
113 return watch;
114}
115
116static void watch_remove(SpiceWatch *watch)
117{
118 watch_update_mask(watch, 0);
119 QTAILQ_REMOVE(&watches, watch, next);
120 qemu_free(watch);
121}
122
123static SpiceCoreInterface core_interface = {
124 .base.type = SPICE_INTERFACE_CORE,
125 .base.description = "qemu core services",
126 .base.major_version = SPICE_INTERFACE_CORE_MAJOR,
127 .base.minor_version = SPICE_INTERFACE_CORE_MINOR,
128
129 .timer_add = timer_add,
130 .timer_start = timer_start,
131 .timer_cancel = timer_cancel,
132 .timer_remove = timer_remove,
133
134 .watch_add = watch_add,
135 .watch_update_mask = watch_update_mask,
136 .watch_remove = watch_remove,
137};
138
139/* functions for the rest of qemu */
140
141void qemu_spice_init(void)
142{
143 QemuOpts *opts = QTAILQ_FIRST(&qemu_spice_opts.head);
144 const char *password;
145 int port;
146
147 if (!opts) {
148 return;
149 }
150 port = qemu_opt_get_number(opts, "port", 0);
151 if (!port) {
152 return;
153 }
154 password = qemu_opt_get(opts, "password");
155
156 spice_server = spice_server_new();
157 spice_server_set_port(spice_server, port);
158 if (password) {
159 spice_server_set_ticket(spice_server, password, 0, 0, 0);
160 }
161 if (qemu_opt_get_bool(opts, "disable-ticketing", 0)) {
162 spice_server_set_noauth(spice_server);
163 }
164
165 /* TODO: make configurable via cmdline */
166 spice_server_set_image_compression(spice_server, SPICE_IMAGE_COMPRESS_AUTO_GLZ);
167
168 spice_server_init(spice_server, &core_interface);
169 using_spice = 1;
170}
171
172int qemu_spice_add_interface(SpiceBaseInstance *sin)
173{
174 return spice_server_add_interface(spice_server, sin);
175}
176
177static void spice_register_config(void)
178{
179 qemu_add_opts(&qemu_spice_opts);
180}
181machine_init(spice_register_config);
182
183static void spice_initialize(void)
184{
185 qemu_spice_init();
186}
187device_init(spice_initialize);