]>
Commit | Line | Data |
---|---|---|
cc04455b DM |
1 | #include <stdlib.h> |
2 | #include <stdio.h> | |
3 | #include <sys/time.h> | |
4 | #include <signal.h> | |
5 | #include <string.h> | |
6 | ||
7 | #include <glib.h> | |
8 | ||
9 | #include <spice/macros.h> | |
cc04455b DM |
10 | #include "basic_event_loop.h" |
11 | ||
0535e191 DM |
12 | int debug = 1; |
13 | ||
cc04455b DM |
14 | #define DPRINTF(x, format, ...) { \ |
15 | if (x <= debug) { \ | |
16 | printf("%s: " format "\n" , __FUNCTION__, ## __VA_ARGS__); \ | |
17 | } \ | |
18 | } | |
19 | ||
0535e191 | 20 | static GMainLoop *main_loop; |
cc04455b DM |
21 | |
22 | static SpiceCoreInterface core; | |
23 | ||
24 | typedef struct SpiceTimer { | |
0535e191 | 25 | GSource *source; |
cc04455b | 26 | SpiceTimerFunc func; |
cc04455b DM |
27 | int ms; |
28 | void *opaque; | |
29 | } Timer; | |
30 | ||
cc04455b DM |
31 | static SpiceTimer* timer_add(SpiceTimerFunc func, void *opaque) |
32 | { | |
0535e191 DM |
33 | g_return_val_if_fail(func != NULL, NULL); |
34 | ||
db8e5ef8 | 35 | SpiceTimer *timer = g_new0(SpiceTimer, 1); |
cc04455b DM |
36 | |
37 | timer->func = func; | |
38 | timer->opaque = opaque; | |
0535e191 | 39 | |
cc04455b DM |
40 | return timer; |
41 | } | |
42 | ||
0535e191 | 43 | static gboolean timer_callback(gpointer data) |
cc04455b | 44 | { |
0535e191 DM |
45 | SpiceTimer *timer = (SpiceTimer *)data; |
46 | g_assert(timer != NULL); | |
47 | g_assert(timer->func != NULL); | |
48 | ||
49 | timer->func(timer->opaque); | |
50 | ||
51 | return FALSE; | |
cc04455b DM |
52 | } |
53 | ||
54 | static void timer_start(SpiceTimer *timer, uint32_t ms) | |
55 | { | |
0535e191 DM |
56 | g_return_if_fail(timer != NULL); |
57 | g_return_if_fail(ms != 0); | |
58 | ||
59 | if (timer->source != NULL) { | |
60 | g_source_destroy(timer->source); | |
61 | } | |
62 | ||
63 | timer->source = g_timeout_source_new(ms); | |
64 | g_assert(timer->source != NULL); | |
65 | ||
66 | g_source_set_callback(timer->source, timer_callback, timer, NULL); | |
67 | ||
68 | g_source_attach(timer->source, NULL); | |
cc04455b DM |
69 | } |
70 | ||
71 | static void timer_cancel(SpiceTimer *timer) | |
72 | { | |
0535e191 DM |
73 | g_return_if_fail(timer != NULL); |
74 | ||
75 | if (timer->source != NULL) { | |
76 | g_source_destroy(timer->source); | |
77 | timer->source = NULL; | |
78 | } | |
79 | ||
cc04455b DM |
80 | timer->ms = 0; |
81 | } | |
82 | ||
83 | static void timer_remove(SpiceTimer *timer) | |
84 | { | |
0535e191 DM |
85 | g_return_if_fail(timer != NULL); |
86 | ||
87 | timer_cancel(timer); | |
88 | g_free(timer); | |
cc04455b DM |
89 | } |
90 | ||
91 | struct SpiceWatch { | |
0535e191 DM |
92 | GIOChannel *channel; |
93 | guint evid; | |
cc04455b DM |
94 | int fd; |
95 | int event_mask; | |
96 | SpiceWatchFunc func; | |
cc04455b DM |
97 | void *opaque; |
98 | }; | |
99 | ||
0535e191 DM |
100 | static gboolean watch_callback(GIOChannel *source, GIOCondition condition, gpointer data) |
101 | { | |
102 | SpiceWatch *watch = (SpiceWatch *)data; | |
103 | ||
104 | g_assert(watch != NULL); | |
105 | g_assert(watch->func != NULL); | |
106 | ||
107 | if (condition & G_IO_OUT) { | |
108 | watch->func(watch->fd, SPICE_WATCH_EVENT_WRITE, watch->opaque); | |
109 | } | |
110 | ||
111 | if (condition & G_IO_IN) { | |
112 | watch->func(watch->fd, SPICE_WATCH_EVENT_READ, watch->opaque); | |
113 | } | |
114 | ||
115 | return TRUE; | |
116 | } | |
117 | ||
118 | static GIOCondition event_mask_to_condition(int event_mask) | |
119 | { | |
120 | GIOCondition condition = 0; | |
121 | ||
122 | if (event_mask & SPICE_WATCH_EVENT_READ) { | |
123 | condition |= G_IO_IN; | |
124 | } | |
125 | ||
126 | if (event_mask & SPICE_WATCH_EVENT_WRITE) { | |
127 | condition |= G_IO_OUT; | |
128 | } | |
cc04455b | 129 | |
0535e191 DM |
130 | return condition; |
131 | } | |
cc04455b DM |
132 | |
133 | static SpiceWatch *watch_add(int fd, int event_mask, SpiceWatchFunc func, void *opaque) | |
134 | { | |
db8e5ef8 | 135 | SpiceWatch *watch = g_new0(SpiceWatch, 1); |
cc04455b | 136 | |
0535e191 DM |
137 | DPRINTF(0, "adding %p, fd=%d", watch, fd); |
138 | ||
cc04455b DM |
139 | watch->fd = fd; |
140 | watch->event_mask = event_mask; | |
141 | watch->func = func; | |
142 | watch->opaque = opaque; | |
0535e191 DM |
143 | watch->channel = g_io_channel_unix_new(fd); |
144 | ||
145 | g_assert(watch->channel != NULL); | |
146 | g_io_channel_set_encoding(watch->channel, NULL, NULL); | |
147 | ||
148 | GIOCondition condition = event_mask_to_condition(event_mask); | |
149 | watch->evid = g_io_add_watch(watch->channel, condition, watch_callback, watch); | |
150 | ||
cc04455b DM |
151 | return watch; |
152 | } | |
153 | ||
154 | static void watch_update_mask(SpiceWatch *watch, int event_mask) | |
155 | { | |
0535e191 DM |
156 | g_assert(watch != NULL); |
157 | ||
cc04455b | 158 | DPRINTF(0, "fd %d to %d", watch->fd, event_mask); |
0535e191 | 159 | |
cc04455b | 160 | watch->event_mask = event_mask; |
cc04455b | 161 | |
0535e191 | 162 | g_source_remove(watch->evid); |
cc04455b | 163 | |
0535e191 DM |
164 | GIOCondition condition = event_mask_to_condition(event_mask); |
165 | watch->evid = g_io_add_watch(watch->channel, condition, watch_callback, watch); | |
cc04455b DM |
166 | } |
167 | ||
0535e191 | 168 | static void watch_remove(SpiceWatch *watch) |
cc04455b | 169 | { |
0535e191 | 170 | g_assert(watch != NULL); |
cc04455b | 171 | |
0535e191 | 172 | DPRINTF(0, "remove %p (fd %d)", watch, watch->fd); |
cc04455b | 173 | |
0535e191 DM |
174 | g_source_remove(watch->evid); |
175 | g_io_channel_unref(watch->channel); | |
cc04455b | 176 | |
0535e191 | 177 | g_free(watch); |
cc04455b DM |
178 | } |
179 | ||
0535e191 | 180 | static void channel_event(int event, SpiceChannelEventInfo *info) |
cc04455b | 181 | { |
abc13312 | 182 | DPRINTF(0, "channel event con, type, id, event: %d, %d, %d, %d", |
0535e191 | 183 | info->connection_id, info->type, info->id, event); |
cc04455b DM |
184 | } |
185 | ||
186 | void basic_event_loop_mainloop(void) | |
187 | { | |
0535e191 | 188 | g_main_loop_run(main_loop); |
cc04455b DM |
189 | } |
190 | ||
191 | static void ignore_sigpipe(void) | |
192 | { | |
193 | struct sigaction act; | |
194 | ||
195 | memset(&act, 0, sizeof(act)); | |
196 | sigfillset(&act.sa_mask); | |
197 | act.sa_handler = SIG_IGN; | |
198 | sigaction(SIGPIPE, &act, NULL); | |
199 | } | |
200 | ||
201 | SpiceCoreInterface *basic_event_loop_init(void) | |
202 | { | |
0535e191 DM |
203 | main_loop = g_main_loop_new(NULL, FALSE); |
204 | ||
cc04455b DM |
205 | memset(&core, 0, sizeof(core)); |
206 | core.base.major_version = SPICE_INTERFACE_CORE_MAJOR; | |
0535e191 | 207 | core.base.minor_version = SPICE_INTERFACE_CORE_MINOR; |
cc04455b DM |
208 | core.timer_add = timer_add; |
209 | core.timer_start = timer_start; | |
210 | core.timer_cancel = timer_cancel; | |
211 | core.timer_remove = timer_remove; | |
212 | core.watch_add = watch_add; | |
213 | core.watch_update_mask = watch_update_mask; | |
214 | core.watch_remove = watch_remove; | |
215 | core.channel_event = channel_event; | |
0535e191 | 216 | |
cc04455b | 217 | ignore_sigpipe(); |
0535e191 | 218 | |
cc04455b DM |
219 | return &core; |
220 | } |