1 #include "qemu/osdep.h"
4 #include "guest-agent-core.h"
7 typedef struct GAChannelReadState
{
11 size_t cur
; /* current buffer start */
12 size_t pending
; /* pending buffered bytes to read */
14 bool ov_pending
; /* whether on async read is outstanding */
21 GAChannelReadState rstate
;
22 GIOCondition pending_events
; /* TODO: use GAWatch.pollfd.revents */
26 typedef struct GAWatch
{
30 GIOCondition events_mask
;
34 * Called by glib prior to polling to set up poll events if polling is needed.
37 static gboolean
ga_channel_prepare(GSource
*source
, gint
*timeout_ms
)
39 GAWatch
*watch
= (GAWatch
*)source
;
40 GAChannel
*c
= (GAChannel
*)watch
->channel
;
41 GAChannelReadState
*rs
= &c
->rstate
;
42 DWORD count_read
, count_to_read
= 0;
44 GIOCondition new_events
= 0;
47 /* go ahead and submit another read if there's room in the buffer
48 * and no previous reads are outstanding
50 if (!rs
->ov_pending
) {
51 if (rs
->cur
+ rs
->pending
>= rs
->buf_size
) {
53 memmove(rs
->buf
, rs
->buf
+ rs
->cur
, rs
->pending
);
57 count_to_read
= rs
->buf_size
- rs
->cur
- rs
->pending
;
60 if (rs
->ov_pending
|| count_to_read
<= 0) {
65 success
= ReadFile(c
->handle
, rs
->buf
+ rs
->cur
+ rs
->pending
,
66 count_to_read
, &count_read
, &rs
->ov
);
68 rs
->pending
+= count_read
;
69 rs
->ov_pending
= false;
71 if (GetLastError() == ERROR_IO_PENDING
) {
72 rs
->ov_pending
= true;
74 new_events
|= G_IO_ERR
;
79 /* don't block forever, iterate the main loop every once in a while */
81 /* if there's data in the read buffer, or another event is pending,
82 * skip polling and issue user cb.
85 new_events
|= G_IO_IN
;
87 c
->pending_events
|= new_events
;
88 return !!c
->pending_events
;
92 * Called by glib after an outstanding read request is completed.
94 static gboolean
ga_channel_check(GSource
*source
)
96 GAWatch
*watch
= (GAWatch
*)source
;
97 GAChannel
*c
= (GAChannel
*)watch
->channel
;
98 GAChannelReadState
*rs
= &c
->rstate
;
99 DWORD count_read
, error
;
102 GIOCondition new_events
= 0;
106 /* failing this implies we issued a read that completed immediately,
107 * yet no data was placed into the buffer (and thus we did not skip
108 * polling). but since EOF is not obtainable until we retrieve an
109 * overlapped result, it must be the case that there was data placed
110 * into the buffer, or an error was generated by Readfile(). in either
111 * case, we should've skipped the polling for this round.
113 g_assert(rs
->ov_pending
);
115 success
= GetOverlappedResult(c
->handle
, &rs
->ov
, &count_read
, FALSE
);
117 g_debug("thread: overlapped result, count_read: %d", (int)count_read
);
118 rs
->pending
+= count_read
;
119 new_events
|= G_IO_IN
;
121 error
= GetLastError();
122 if (error
== 0 || error
== ERROR_HANDLE_EOF
||
123 error
== ERROR_NO_SYSTEM_RESOURCES
||
124 error
== ERROR_OPERATION_ABORTED
) {
125 /* note: On WinXP SP3 with rhel6ga virtio-win-1.1.16 vioser drivers,
126 * ENSR seems to be synonymous with when we'd normally expect
127 * ERROR_HANDLE_EOF. So treat it as such. Microsoft's
128 * recommendation for ERROR_NO_SYSTEM_RESOURCES is to
129 * retry the read, so this happens to work out anyway. On newer
130 * virtio-win driver, this seems to be replaced with EOA, so
131 * handle that in the same fashion.
133 new_events
|= G_IO_HUP
;
134 } else if (error
!= ERROR_IO_INCOMPLETE
) {
135 g_critical("error retrieving overlapped result: %d", (int)error
);
136 new_events
|= G_IO_ERR
;
143 c
->pending_events
|= new_events
;
145 return !!c
->pending_events
;
149 * Called by glib after either prepare or check routines signal readiness
151 static gboolean
ga_channel_dispatch(GSource
*source
, GSourceFunc unused
,
154 GAWatch
*watch
= (GAWatch
*)source
;
155 GAChannel
*c
= (GAChannel
*)watch
->channel
;
156 GAChannelReadState
*rs
= &c
->rstate
;
160 success
= c
->cb(watch
->pollfd
.revents
, c
->user_data
);
162 if (c
->pending_events
& G_IO_ERR
) {
163 g_critical("channel error, removing source");
167 /* TODO: replace rs->pending with watch->revents */
168 c
->pending_events
&= ~G_IO_HUP
;
170 c
->pending_events
&= ~G_IO_IN
;
172 c
->pending_events
= 0;
177 static void ga_channel_finalize(GSource
*source
)
182 GSourceFuncs ga_channel_watch_funcs
= {
189 static GSource
*ga_channel_create_watch(GAChannel
*c
)
191 GSource
*source
= g_source_new(&ga_channel_watch_funcs
, sizeof(GAWatch
));
192 GAWatch
*watch
= (GAWatch
*)source
;
195 watch
->pollfd
.fd
= (gintptr
) c
->rstate
.ov
.hEvent
;
196 g_source_add_poll(source
, &watch
->pollfd
);
201 GIOStatus
ga_channel_read(GAChannel
*c
, char *buf
, size_t size
, gsize
*count
)
203 GAChannelReadState
*rs
= &c
->rstate
;
207 if (c
->pending_events
& G_IO_ERR
) {
208 return G_IO_STATUS_ERROR
;
211 *count
= to_read
= MIN(size
, rs
->pending
);
213 memcpy(buf
, rs
->buf
+ rs
->cur
, to_read
);
215 rs
->pending
-= to_read
;
216 status
= G_IO_STATUS_NORMAL
;
218 status
= G_IO_STATUS_AGAIN
;
224 static GIOStatus
ga_channel_write(GAChannel
*c
, const char *buf
, size_t size
,
232 ov
.hEvent
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
233 ret
= WriteFile(c
->handle
, buf
, size
, &written
, &ov
);
235 if (GetLastError() == ERROR_IO_PENDING
) {
236 /* write is pending */
237 ret
= GetOverlappedResult(c
->handle
, &ov
, &written
, TRUE
);
239 if (!GetLastError()) {
240 status
= G_IO_STATUS_AGAIN
;
242 status
= G_IO_STATUS_ERROR
;
245 /* write is complete */
246 status
= G_IO_STATUS_NORMAL
;
250 status
= G_IO_STATUS_ERROR
;
253 /* write returned immediately */
254 status
= G_IO_STATUS_NORMAL
;
259 CloseHandle(ov
.hEvent
);
265 GIOStatus
ga_channel_write_all(GAChannel
*c
, const char *buf
, size_t size
)
267 GIOStatus status
= G_IO_STATUS_NORMAL
;
271 status
= ga_channel_write(c
, buf
, size
, &count
);
272 if (status
== G_IO_STATUS_NORMAL
) {
275 } else if (status
!= G_IO_STATUS_AGAIN
) {
283 static gboolean
ga_channel_open(GAChannel
*c
, GAChannelMethod method
,
286 COMMTIMEOUTS comTimeOut
= {0};
287 gchar newpath
[MAXPATHLEN
] = {0};
288 comTimeOut
.ReadIntervalTimeout
= 1;
290 if (method
!= GA_CHANNEL_VIRTIO_SERIAL
&& method
!= GA_CHANNEL_ISA_SERIAL
) {
291 g_critical("unsupported communication method");
295 if (method
== GA_CHANNEL_ISA_SERIAL
) {
296 snprintf(newpath
, sizeof(newpath
), "\\\\.\\%s", path
);
298 g_strlcpy(newpath
, path
, sizeof(newpath
));
301 c
->handle
= CreateFile(newpath
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
303 FILE_FLAG_NO_BUFFERING
| FILE_FLAG_OVERLAPPED
, NULL
);
304 if (c
->handle
== INVALID_HANDLE_VALUE
) {
305 g_autofree gchar
*emsg
= g_win32_error_message(GetLastError());
306 g_critical("error opening path %s: %s", newpath
, emsg
);
310 if (method
== GA_CHANNEL_ISA_SERIAL
311 && !SetCommTimeouts(c
->handle
, &comTimeOut
)) {
312 g_autofree gchar
*emsg
= g_win32_error_message(GetLastError());
313 g_critical("error setting timeout for com port: %s", emsg
);
314 CloseHandle(c
->handle
);
321 GAChannel
*ga_channel_new(GAChannelMethod method
, const gchar
*path
,
322 int listen_fd
, GAChannelCallback cb
, gpointer opaque
)
324 GAChannel
*c
= g_new0(GAChannel
, 1);
325 SECURITY_ATTRIBUTES sec_attrs
;
327 if (!ga_channel_open(c
, method
, path
)) {
328 g_critical("error opening channel");
334 c
->user_data
= opaque
;
336 sec_attrs
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
337 sec_attrs
.lpSecurityDescriptor
= NULL
;
338 sec_attrs
.bInheritHandle
= false;
340 c
->rstate
.buf_size
= QGA_READ_COUNT_DEFAULT
;
341 c
->rstate
.buf
= g_malloc(QGA_READ_COUNT_DEFAULT
);
342 c
->rstate
.ov
.hEvent
= CreateEvent(&sec_attrs
, FALSE
, FALSE
, NULL
);
344 c
->source
= ga_channel_create_watch(c
);
345 g_source_attach(c
->source
, NULL
);
349 void ga_channel_free(GAChannel
*c
)
352 g_source_destroy(c
->source
);
354 if (c
->rstate
.ov
.hEvent
) {
355 CloseHandle(c
->rstate
.ov
.hEvent
);
357 g_free(c
->rstate
.buf
);