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