]> git.proxmox.com Git - spiceterm.git/blob - basic_event_loop.c
code cleanup - compile with -Wall
[spiceterm.git] / basic_event_loop.c
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>
10 #include "basic_event_loop.h"
11
12 int debug = 1;
13
14 #define DPRINTF(x, format, ...) { \
15 if (x <= debug) { \
16 printf("%s: " format "\n" , __FUNCTION__, ## __VA_ARGS__); \
17 } \
18 }
19
20 static GMainLoop *main_loop;
21
22 static SpiceCoreInterface core;
23
24 typedef struct SpiceTimer {
25 GSource *source;
26 SpiceTimerFunc func;
27 int ms;
28 void *opaque;
29 } Timer;
30
31 static SpiceTimer* timer_add(SpiceTimerFunc func, void *opaque)
32 {
33 g_return_val_if_fail(func != NULL, NULL);
34
35 SpiceTimer *timer = g_new0(SpiceTimer, 1);
36
37 timer->func = func;
38 timer->opaque = opaque;
39
40 return timer;
41 }
42
43 static gboolean timer_callback(gpointer data)
44 {
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;
52 }
53
54 static void timer_start(SpiceTimer *timer, uint32_t ms)
55 {
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);
69 }
70
71 static void timer_cancel(SpiceTimer *timer)
72 {
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
80 timer->ms = 0;
81 }
82
83 static void timer_remove(SpiceTimer *timer)
84 {
85 g_return_if_fail(timer != NULL);
86
87 timer_cancel(timer);
88 g_free(timer);
89 }
90
91 struct SpiceWatch {
92 GIOChannel *channel;
93 guint evid;
94 int fd;
95 int event_mask;
96 SpiceWatchFunc func;
97 void *opaque;
98 };
99
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 }
129
130 return condition;
131 }
132
133 static SpiceWatch *watch_add(int fd, int event_mask, SpiceWatchFunc func, void *opaque)
134 {
135 SpiceWatch *watch = g_new0(SpiceWatch, 1);
136
137 DPRINTF(0, "adding %p, fd=%d", watch, fd);
138
139 watch->fd = fd;
140 watch->event_mask = event_mask;
141 watch->func = func;
142 watch->opaque = opaque;
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
151 return watch;
152 }
153
154 static void watch_update_mask(SpiceWatch *watch, int event_mask)
155 {
156 g_assert(watch != NULL);
157
158 DPRINTF(0, "fd %d to %d", watch->fd, event_mask);
159
160 watch->event_mask = event_mask;
161
162 g_source_remove(watch->evid);
163
164 GIOCondition condition = event_mask_to_condition(event_mask);
165 watch->evid = g_io_add_watch(watch->channel, condition, watch_callback, watch);
166 }
167
168 static void watch_remove(SpiceWatch *watch)
169 {
170 g_assert(watch != NULL);
171
172 DPRINTF(0, "remove %p (fd %d)", watch, watch->fd);
173
174 g_source_remove(watch->evid);
175 g_io_channel_unref(watch->channel);
176
177 g_free(watch);
178 }
179
180 static void channel_event(int event, SpiceChannelEventInfo *info)
181 {
182 DPRINTF(0, "channel event con, type, id, event: %d, %d, %d, %d",
183 info->connection_id, info->type, info->id, event);
184 }
185
186 void basic_event_loop_mainloop(void)
187 {
188 g_main_loop_run(main_loop);
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 {
203 main_loop = g_main_loop_new(NULL, FALSE);
204
205 memset(&core, 0, sizeof(core));
206 core.base.major_version = SPICE_INTERFACE_CORE_MAJOR;
207 core.base.minor_version = SPICE_INTERFACE_CORE_MINOR;
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;
216
217 ignore_sigpipe();
218
219 return &core;
220 }