]> git.proxmox.com Git - spiceterm.git/blob - event_loop.c
white space cleanups
[spiceterm.git] / event_loop.c
1 /*
2
3 Copyright (C) 2013 Proxmox Server Solutions GmbH
4
5 Copyright: spiceterm is under GNU GPL, the GNU General Public License.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; version 2 dated June, 1991.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA.
20
21 Author: Dietmar Maurer <dietmar@proxmox.com>
22
23 */
24
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <sys/time.h>
28 #include <signal.h>
29 #include <string.h>
30
31 #include <glib.h>
32
33 #include <spice/macros.h>
34 #include "event_loop.h"
35
36 static int debug = 0;
37
38 #define DPRINTF(x, format, ...) { \
39 if (x <= debug) { \
40 printf("%s: " format "\n" , __FUNCTION__, ## __VA_ARGS__); \
41 } \
42 }
43
44 static GMainLoop *main_loop;
45
46 static SpiceCoreInterface core;
47
48 typedef struct SpiceTimer {
49 GSource *source;
50 SpiceTimerFunc func;
51 int ms;
52 void *opaque;
53 } Timer;
54
55 static SpiceTimer* timer_add(SpiceTimerFunc func, void *opaque)
56 {
57 g_return_val_if_fail(func != NULL, NULL);
58
59 SpiceTimer *timer = g_new0(SpiceTimer, 1);
60
61 timer->func = func;
62 timer->opaque = opaque;
63
64 return timer;
65 }
66
67 static gboolean timer_callback(gpointer data)
68 {
69 SpiceTimer *timer = (SpiceTimer *)data;
70 g_assert(timer != NULL);
71 g_assert(timer->func != NULL);
72
73 timer->func(timer->opaque);
74
75 return FALSE;
76 }
77
78 static void timer_start(SpiceTimer *timer, uint32_t ms)
79 {
80 g_return_if_fail(timer != NULL);
81 g_return_if_fail(ms != 0);
82
83 if (timer->source != NULL) {
84 g_source_destroy(timer->source);
85 }
86
87 timer->source = g_timeout_source_new(ms);
88 g_assert(timer->source != NULL);
89
90 g_source_set_callback(timer->source, timer_callback, timer, NULL);
91
92 g_source_attach(timer->source, NULL);
93 }
94
95 static void timer_cancel(SpiceTimer *timer)
96 {
97 g_return_if_fail(timer != NULL);
98
99 if (timer->source != NULL) {
100 g_source_destroy(timer->source);
101 timer->source = NULL;
102 }
103
104 timer->ms = 0;
105 }
106
107 static void timer_remove(SpiceTimer *timer)
108 {
109 g_return_if_fail(timer != NULL);
110
111 timer_cancel(timer);
112 g_free(timer);
113 }
114
115 struct SpiceWatch {
116 GIOChannel *channel;
117 guint evid;
118 int fd;
119 int event_mask;
120 SpiceWatchFunc func;
121 void *opaque;
122 };
123
124 static gboolean watch_callback(GIOChannel *source, GIOCondition condition, gpointer data)
125 {
126 SpiceWatch *watch = (SpiceWatch *)data;
127
128 g_assert(watch != NULL);
129 g_assert(watch->func != NULL);
130
131 if (condition & G_IO_OUT) {
132 watch->func(watch->fd, SPICE_WATCH_EVENT_WRITE, watch->opaque);
133 }
134
135 if (condition & G_IO_IN) {
136 watch->func(watch->fd, SPICE_WATCH_EVENT_READ, watch->opaque);
137 }
138
139 return TRUE;
140 }
141
142 static GIOCondition event_mask_to_condition(int event_mask)
143 {
144 GIOCondition condition = 0;
145
146 if (event_mask & SPICE_WATCH_EVENT_READ) {
147 condition |= G_IO_IN;
148 }
149
150 if (event_mask & SPICE_WATCH_EVENT_WRITE) {
151 condition |= G_IO_OUT;
152 }
153
154 return condition;
155 }
156
157 static SpiceWatch *watch_add(int fd, int event_mask, SpiceWatchFunc func, void *opaque)
158 {
159 SpiceWatch *watch = g_new0(SpiceWatch, 1);
160
161 DPRINTF(1, "adding %p, fd=%d", watch, fd);
162
163 watch->fd = fd;
164 watch->event_mask = event_mask;
165 watch->func = func;
166 watch->opaque = opaque;
167 watch->channel = g_io_channel_unix_new(fd);
168
169 g_assert(watch->channel != NULL);
170 g_io_channel_set_encoding(watch->channel, NULL, NULL);
171
172 GIOCondition condition = event_mask_to_condition(event_mask);
173 watch->evid = g_io_add_watch(watch->channel, condition, watch_callback, watch);
174
175 return watch;
176 }
177
178 static void watch_update_mask(SpiceWatch *watch, int event_mask)
179 {
180 g_assert(watch != NULL);
181
182 DPRINTF(1, "fd %d to %d", watch->fd, event_mask);
183
184 watch->event_mask = event_mask;
185
186 g_source_remove(watch->evid);
187
188 GIOCondition condition = event_mask_to_condition(event_mask);
189 watch->evid = g_io_add_watch(watch->channel, condition, watch_callback, watch);
190 }
191
192 static void watch_remove(SpiceWatch *watch)
193 {
194 g_assert(watch != NULL);
195
196 DPRINTF(1, "remove %p (fd %d)", watch, watch->fd);
197
198 g_source_remove(watch->evid);
199 g_io_channel_unref(watch->channel);
200
201 g_free(watch);
202 }
203
204 static void channel_event(int event, SpiceChannelEventInfo *info)
205 {
206 DPRINTF(1, "channel event con, type, id, event: %d, %d, %d, %d",
207 info->connection_id, info->type, info->id, event);
208 }
209
210 void basic_event_loop_mainloop(void)
211 {
212 g_main_loop_run(main_loop);
213 }
214
215 static void ignore_sigpipe(void)
216 {
217 struct sigaction act;
218
219 memset(&act, 0, sizeof(act));
220 sigfillset(&act.sa_mask);
221 act.sa_handler = SIG_IGN;
222 sigaction(SIGPIPE, &act, NULL);
223 }
224
225 SpiceCoreInterface *basic_event_loop_init(void)
226 {
227 main_loop = g_main_loop_new(NULL, FALSE);
228
229 memset(&core, 0, sizeof(core));
230 core.base.major_version = SPICE_INTERFACE_CORE_MAJOR;
231 core.base.minor_version = SPICE_INTERFACE_CORE_MINOR;
232 core.timer_add = timer_add;
233 core.timer_start = timer_start;
234 core.timer_cancel = timer_cancel;
235 core.timer_remove = timer_remove;
236 core.watch_add = watch_add;
237 core.watch_update_mask = watch_update_mask;
238 core.watch_remove = watch_remove;
239 core.channel_event = channel_event;
240
241 ignore_sigpipe();
242
243 return &core;
244 }