master
c 318 lines 8.86 KB
Raw
1 #include "qemu/osdep.h"
2 #include "qemu/cutils.h"
3 #include <termios.h>
4 #include "qapi/error.h"
5 #include "qemu/sockets.h"
6 #include "channel.h"
7 #include "cutils.h"
8
9 #ifdef CONFIG_SOLARIS
10 #include <stropts.h>
11 #endif
12
13 #define GA_CHANNEL_BAUDRATE_DEFAULT B38400 /* for isa-serial channels */
14
15 struct GAChannel {
16 GIOChannel *listen_channel;
17 GIOChannel *client_channel;
18 GAChannelMethod method;
19 GAChannelCallback event_cb;
20 gpointer user_data;
21 };
22
23 static int ga_channel_client_add(GAChannel *c, int fd);
24
25 static gboolean ga_channel_listen_accept(GIOChannel *channel,
26 GIOCondition condition, gpointer data)
27 {
28 GAChannel *c = data;
29 int ret, client_fd;
30 bool accepted = false;
31 Error *err = NULL;
32
33 g_assert(channel != NULL);
34
35 client_fd = qemu_accept(g_io_channel_unix_get_fd(channel), NULL, NULL);
36 if (client_fd == -1) {
37 g_warning("error converting fd to gsocket: %s", strerror(errno));
38 goto out;
39 }
40 if (!qemu_set_blocking(client_fd, false, &err)) {
41 g_warning("%s", error_get_pretty(err));
42 error_free(err);
43 goto out;
44 }
45 ret = ga_channel_client_add(c, client_fd);
46 if (ret) {
47 g_warning("error setting up connection");
48 close(client_fd);
49 goto out;
50 }
51 accepted = true;
52
53 out:
54 /* only accept 1 connection at a time */
55 return !accepted;
56 }
57
58 /* start polling for readable events on listen fd, new==true
59 * indicates we should use the existing s->listen_channel
60 */
61 static void ga_channel_listen_add(GAChannel *c, int listen_fd, bool create)
62 {
63 if (create) {
64 c->listen_channel = g_io_channel_unix_new(listen_fd);
65 }
66 g_io_add_watch(c->listen_channel, G_IO_IN, ga_channel_listen_accept, c);
67 }
68
69 static void ga_channel_listen_close(GAChannel *c)
70 {
71 g_assert(c->listen_channel);
72 g_io_channel_shutdown(c->listen_channel, true, NULL);
73 g_io_channel_unref(c->listen_channel);
74 c->listen_channel = NULL;
75 }
76
77 /* cleanup state for closed connection/session, start accepting new
78 * connections if we're in listening mode
79 */
80 static void ga_channel_client_close(GAChannel *c)
81 {
82 g_assert(c->client_channel);
83 g_io_channel_shutdown(c->client_channel, true, NULL);
84 g_io_channel_unref(c->client_channel);
85 c->client_channel = NULL;
86 if (c->listen_channel) {
87 ga_channel_listen_add(c, 0, false);
88 }
89 }
90
91 static gboolean ga_channel_client_event(GIOChannel *channel,
92 GIOCondition condition, gpointer data)
93 {
94 GAChannel *c = data;
95 gboolean client_cont;
96
97 g_assert(c);
98 if (c->event_cb) {
99 client_cont = c->event_cb(condition, c->user_data);
100 if (!client_cont) {
101 ga_channel_client_close(c);
102 return false;
103 }
104 }
105 return true;
106 }
107
108 static int ga_channel_client_add(GAChannel *c, int fd)
109 {
110 GIOChannel *client_channel;
111 GError *err = NULL;
112
113 g_assert(c && !c->client_channel);
114 client_channel = g_io_channel_unix_new(fd);
115 g_assert(client_channel);
116 g_io_channel_set_encoding(client_channel, NULL, &err);
117 if (err != NULL) {
118 g_warning("error setting channel encoding to binary");
119 g_error_free(err);
120 return -1;
121 }
122 g_io_add_watch(client_channel, G_IO_IN | G_IO_HUP,
123 ga_channel_client_event, c);
124 c->client_channel = client_channel;
125 return 0;
126 }
127
128 static gboolean ga_channel_open(GAChannel *c, const gchar *path,
129 GAChannelMethod method, int fd, Error **errp)
130 {
131 int ret;
132 c->method = method;
133
134 switch (c->method) {
135 case GA_CHANNEL_VIRTIO_SERIAL: {
136 assert(fd < 0);
137 fd = qga_open_cloexec(
138 path,
139 #ifndef CONFIG_SOLARIS
140 O_ASYNC |
141 #endif
142 O_RDWR | O_NONBLOCK,
143 0
144 );
145 if (fd == -1) {
146 error_setg_errno(errp, errno, "error opening channel '%s'", path);
147 return false;
148 }
149 #ifdef CONFIG_SOLARIS
150 ret = ioctl(fd, I_SETSIG, S_OUTPUT | S_INPUT | S_HIPRI);
151 if (ret == -1) {
152 error_setg_errno(errp, errno, "error setting event mask for channel");
153 close(fd);
154 return false;
155 }
156 #endif
157 #ifdef __FreeBSD__
158 /*
159 * In the default state channel sends echo of every command to a
160 * client. The client program doesn't expect this and raises an
161 * error. Suppress echo by resetting ECHO terminal flag.
162 */
163 struct termios tio;
164 if (tcgetattr(fd, &tio) < 0) {
165 error_setg_errno(errp, errno, "error getting channel termios attrs");
166 close(fd);
167 return false;
168 }
169 tio.c_lflag &= ~ECHO;
170 if (tcsetattr(fd, TCSAFLUSH, &tio) < 0) {
171 error_setg_errno(errp, errno, "error setting channel termios attrs");
172 close(fd);
173 return false;
174 }
175 #endif /* __FreeBSD__ */
176 ret = ga_channel_client_add(c, fd);
177 if (ret) {
178 error_setg(errp, "error adding channel to main loop");
179 close(fd);
180 return false;
181 }
182 break;
183 }
184 case GA_CHANNEL_ISA_SERIAL: {
185 struct termios tio;
186
187 assert(fd < 0);
188 fd = qga_open_cloexec(path, O_RDWR | O_NOCTTY | O_NONBLOCK, 0);
189 if (fd == -1) {
190 error_setg_errno(errp, errno, "error opening channel '%s'", path);
191 return false;
192 }
193 tcgetattr(fd, &tio);
194 /* set up serial port for non-canonical, dumb byte streaming */
195 tio.c_iflag &= ~(IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP |
196 INLCR | IGNCR | ICRNL | IXON | IXOFF | IXANY |
197 IMAXBEL);
198 tio.c_oflag = 0;
199 tio.c_lflag = 0;
200 tio.c_cflag |= GA_CHANNEL_BAUDRATE_DEFAULT;
201 /* 1 available byte min or reads will block (we'll set non-blocking
202 * elsewhere, else we have to deal with read()=0 instead)
203 */
204 tio.c_cc[VMIN] = 1;
205 tio.c_cc[VTIME] = 0;
206 /* flush everything waiting for read/xmit, it's garbage at this point */
207 tcflush(fd, TCIFLUSH);
208 tcsetattr(fd, TCSANOW, &tio);
209 ret = ga_channel_client_add(c, fd);
210 if (ret) {
211 error_setg(errp, "error adding channel to main loop");
212 close(fd);
213 return false;
214 }
215 break;
216 }
217 case GA_CHANNEL_UNIX_LISTEN: {
218 if (fd < 0) {
219 fd = unix_listen(path, errp);
220 if (fd < 0) {
221 return false;
222 }
223 }
224 ga_channel_listen_add(c, fd, true);
225 break;
226 }
227 case GA_CHANNEL_VSOCK_LISTEN: {
228 if (fd < 0) {
229 SocketAddress *addr;
230 char *addr_str;
231
232 addr_str = g_strdup_printf("vsock:%s", path);
233 addr = socket_parse(addr_str, errp);
234 g_free(addr_str);
235 if (!addr) {
236 return false;
237 }
238
239 fd = socket_listen(addr, 1, errp);
240 qapi_free_SocketAddress(addr);
241 if (fd < 0) {
242 return false;
243 }
244 }
245 ga_channel_listen_add(c, fd, true);
246 break;
247 }
248 default:
249 error_setg(errp, "error binding/listening to specified socket");
250 return false;
251 }
252
253 return true;
254 }
255
256 GIOStatus ga_channel_write_all(GAChannel *c, const gchar *buf, gsize size)
257 {
258 GError *err = NULL;
259 gsize written = 0;
260 GIOStatus status = G_IO_STATUS_NORMAL;
261
262 while (size) {
263 g_debug("sending data, count: %d", (int)size);
264 status = g_io_channel_write_chars(c->client_channel, buf, size,
265 &written, &err);
266 if (status == G_IO_STATUS_NORMAL) {
267 size -= written;
268 buf += written;
269 } else if (status != G_IO_STATUS_AGAIN) {
270 g_warning("error writing to channel: %s", err->message);
271 return status;
272 }
273 }
274
275 do {
276 status = g_io_channel_flush(c->client_channel, &err);
277 } while (status == G_IO_STATUS_AGAIN);
278
279 if (status != G_IO_STATUS_NORMAL) {
280 g_warning("error flushing channel: %s", err->message);
281 }
282
283 return status;
284 }
285
286 GIOStatus ga_channel_read(GAChannel *c, gchar *buf, gsize size, gsize *count)
287 {
288 return g_io_channel_read_chars(c->client_channel, buf, size, count, NULL);
289 }
290
291 GAChannel *ga_channel_new(GAChannelMethod method, const gchar *path,
292 int listen_fd, GAChannelCallback cb, gpointer opaque)
293 {
294 Error *err = NULL;
295 GAChannel *c = g_new0(GAChannel, 1);
296 c->event_cb = cb;
297 c->user_data = opaque;
298
299 if (!ga_channel_open(c, path, method, listen_fd, &err)) {
300 g_critical("%s", error_get_pretty(err));
301 error_free(err);
302 ga_channel_free(c);
303 return NULL;
304 }
305
306 return c;
307 }
308
309 void ga_channel_free(GAChannel *c)
310 {
311 if (c->listen_channel) {
312 ga_channel_listen_close(c);
313 }
314 if (c->client_channel) {
315 ga_channel_client_close(c);
316 }
317 g_free(c);
318 }