1 #include "qemu/osdep.h"
5 #include "qga/guest-agent-core.h"
6 #include "qga/channel.h"
8 typedef struct GAChannelReadState {
12 size_t cur; /* current buffer start */
13 size_t pending; /* pending buffered bytes to read */
15 bool ov_pending; /* whether on async read is outstanding */
22 GAChannelReadState rstate;
23 GIOCondition pending_events; /* TODO: use GAWatch.pollfd.revents */
27 typedef struct GAWatch {
31 GIOCondition events_mask;
35 * Called by glib prior to polling to set up poll events if polling is needed.
38 static gboolean ga_channel_prepare(GSource *source, gint *timeout_ms)
40 GAWatch *watch = (GAWatch *)source;
41 GAChannel *c = (GAChannel *)watch->channel;
42 GAChannelReadState *rs = &c->rstate;
43 DWORD count_read, count_to_read = 0;
45 GIOCondition new_events = 0;
48 /* go ahead and submit another read if there's room in the buffer
49 * and no previous reads are outstanding
51 if (!rs->ov_pending) {
52 if (rs->cur + rs->pending >= rs->buf_size) {
54 memmove(rs->buf, rs->buf + rs->cur, rs->pending);
58 count_to_read = rs->buf_size - rs->cur - rs->pending;
61 if (rs->ov_pending || count_to_read <= 0) {
66 success = ReadFile(c->handle, rs->buf + rs->cur + rs->pending,
67 count_to_read, &count_read, &rs->ov);
69 rs->pending += count_read;
70 rs->ov_pending = false;
72 if (GetLastError() == ERROR_IO_PENDING) {
73 rs->ov_pending = true;
75 new_events |= G_IO_ERR;
80 /* don't block forever, iterate the main loop every once in a while */
82 /* if there's data in the read buffer, or another event is pending,
83 * skip polling and issue user cb.
86 new_events |= G_IO_IN;
88 c->pending_events |= new_events;
89 return !!c->pending_events;
93 * Called by glib after an outstanding read request is completed.
95 static gboolean ga_channel_check(GSource *source)
97 GAWatch *watch = (GAWatch *)source;
98 GAChannel *c = (GAChannel *)watch->channel;
99 GAChannelReadState *rs = &c->rstate;
100 DWORD count_read, error;
103 GIOCondition new_events = 0;
107 /* failing this implies we issued a read that completed immediately,
108 * yet no data was placed into the buffer (and thus we did not skip
109 * polling). but since EOF is not obtainable until we retrieve an
110 * overlapped result, it must be the case that there was data placed
111 * into the buffer, or an error was generated by Readfile(). in either
112 * case, we should've skipped the polling for this round.
114 g_assert(rs->ov_pending);
116 success = GetOverlappedResult(c->handle, &rs->ov, &count_read, FALSE);
118 g_debug("thread: overlapped result, count_read: %d", (int)count_read);
119 rs->pending += count_read;
120 new_events |= G_IO_IN;
122 error = GetLastError();
123 if (error == 0 || error == ERROR_HANDLE_EOF ||
124 error == ERROR_NO_SYSTEM_RESOURCES ||
125 error == ERROR_OPERATION_ABORTED) {
126 /* note: On WinXP SP3 with rhel6ga virtio-win-1.1.16 vioser drivers,
127 * ENSR seems to be synonymous with when we'd normally expect
128 * ERROR_HANDLE_EOF. So treat it as such. Microsoft's
129 * recommendation for ERROR_NO_SYSTEM_RESOURCES is to
130 * retry the read, so this happens to work out anyway. On newer
131 * virtio-win driver, this seems to be replaced with EOA, so
132 * handle that in the same fashion.
134 new_events |= G_IO_HUP;
135 } else if (error != ERROR_IO_INCOMPLETE) {
136 g_critical("error retrieving overlapped result: %d", (int)error);
137 new_events |= G_IO_ERR;
144 c->pending_events |= new_events;
146 return !!c->pending_events;
150 * Called by glib after either prepare or check routines signal readiness
152 static gboolean ga_channel_dispatch(GSource *source, GSourceFunc unused,
155 GAWatch *watch = (GAWatch *)source;
156 GAChannel *c = (GAChannel *)watch->channel;
157 GAChannelReadState *rs = &c->rstate;
161 success = c->cb(watch->pollfd.revents, c->user_data);
163 if (c->pending_events & G_IO_ERR) {
164 g_critical("channel error, removing source");
168 /* TODO: replace rs->pending with watch->revents */
169 c->pending_events &= ~G_IO_HUP;
171 c->pending_events &= ~G_IO_IN;
173 c->pending_events = 0;
178 static void ga_channel_finalize(GSource *source)
183 GSourceFuncs ga_channel_watch_funcs = {
190 static GSource *ga_channel_create_watch(GAChannel *c)
192 GSource *source = g_source_new(&ga_channel_watch_funcs, sizeof(GAWatch));
193 GAWatch *watch = (GAWatch *)source;
196 watch->pollfd.fd = (gintptr) c->rstate.ov.hEvent;
197 g_source_add_poll(source, &watch->pollfd);
202 GIOStatus ga_channel_read(GAChannel *c, char *buf, size_t size, gsize *count)
204 GAChannelReadState *rs = &c->rstate;
208 if (c->pending_events & G_IO_ERR) {
209 return G_IO_STATUS_ERROR;
212 *count = to_read = MIN(size, rs->pending);
214 memcpy(buf, rs->buf + rs->cur, to_read);
216 rs->pending -= to_read;
217 status = G_IO_STATUS_NORMAL;
219 status = G_IO_STATUS_AGAIN;
225 static GIOStatus ga_channel_write(GAChannel *c, const char *buf, size_t size,
233 ov.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
234 ret = WriteFile(c->handle, buf, size, &written, &ov);
236 if (GetLastError() == ERROR_IO_PENDING) {
237 /* write is pending */
238 ret = GetOverlappedResult(c->handle, &ov, &written, TRUE);
240 if (!GetLastError()) {
241 status = G_IO_STATUS_AGAIN;
243 status = G_IO_STATUS_ERROR;
246 /* write is complete */
247 status = G_IO_STATUS_NORMAL;
251 status = G_IO_STATUS_ERROR;
254 /* write returned immediately */
255 status = G_IO_STATUS_NORMAL;
260 CloseHandle(ov.hEvent);
266 GIOStatus ga_channel_write_all(GAChannel *c, const char *buf, size_t size)
268 GIOStatus status = G_IO_STATUS_NORMAL;
272 status = ga_channel_write(c, buf, size, &count);
273 if (status == G_IO_STATUS_NORMAL) {
276 } else if (status != G_IO_STATUS_AGAIN) {
284 static gboolean ga_channel_open(GAChannel *c, GAChannelMethod method,
287 COMMTIMEOUTS comTimeOut = {0};
288 gchar newpath[MAXPATHLEN] = {0};
289 comTimeOut.ReadIntervalTimeout = 1;
291 if (method != GA_CHANNEL_VIRTIO_SERIAL && method != GA_CHANNEL_ISA_SERIAL) {
292 g_critical("unsupported communication method");
296 if (method == GA_CHANNEL_ISA_SERIAL){
297 snprintf(newpath, sizeof(newpath), "\\\\.\\%s", path);
299 g_strlcpy(newpath, path, sizeof(newpath));
302 c->handle = CreateFile(newpath, GENERIC_READ | GENERIC_WRITE, 0, NULL,
304 FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL);
305 if (c->handle == INVALID_HANDLE_VALUE) {
306 g_critical("error opening path %s", newpath);
310 if (method == GA_CHANNEL_ISA_SERIAL && !SetCommTimeouts(c->handle,&comTimeOut)) {
311 g_critical("error setting timeout for com port: %lu",GetLastError());
312 CloseHandle(c->handle);
319 GAChannel *ga_channel_new(GAChannelMethod method, const gchar *path,
320 GAChannelCallback cb, gpointer opaque)
322 GAChannel *c = g_new0(GAChannel, 1);
323 SECURITY_ATTRIBUTES sec_attrs;
325 if (!ga_channel_open(c, method, path)) {
326 g_critical("error opening channel");
332 c->user_data = opaque;
334 sec_attrs.nLength = sizeof(SECURITY_ATTRIBUTES);
335 sec_attrs.lpSecurityDescriptor = NULL;
336 sec_attrs.bInheritHandle = false;
338 c->rstate.buf_size = QGA_READ_COUNT_DEFAULT;
339 c->rstate.buf = g_malloc(QGA_READ_COUNT_DEFAULT);
340 c->rstate.ov.hEvent = CreateEvent(&sec_attrs, FALSE, FALSE, NULL);
342 c->source = ga_channel_create_watch(c);
343 g_source_attach(c->source, NULL);
347 void ga_channel_free(GAChannel *c)
350 g_source_destroy(c->source);
352 if (c->rstate.ov.hEvent) {
353 CloseHandle(c->rstate.ov.hEvent);
355 g_free(c->rstate.buf);