1 #include "qemu/osdep.h" 2 #include <glib.h> 3 #include <windows.h> 4 #include <io.h> 5 #include "qga/guest-agent-core.h" 6 #include "qga/channel.h" 7 8 typedef struct GAChannelReadState { 9 guint thread_id; 10 uint8_t *buf; 11 size_t buf_size; 12 size_t cur; /* current buffer start */ 13 size_t pending; /* pending buffered bytes to read */ 14 OVERLAPPED ov; 15 bool ov_pending; /* whether on async read is outstanding */ 16 } GAChannelReadState; 17 18 struct GAChannel { 19 HANDLE handle; 20 GAChannelCallback cb; 21 gpointer user_data; 22 GAChannelReadState rstate; 23 GIOCondition pending_events; /* TODO: use GAWatch.pollfd.revents */ 24 GSource *source; 25 }; 26 27 typedef struct GAWatch { 28 GSource source; 29 GPollFD pollfd; 30 GAChannel *channel; 31 GIOCondition events_mask; 32 } GAWatch; 33 34 /* 35 * Called by glib prior to polling to set up poll events if polling is needed. 36 * 37 */ 38 static gboolean ga_channel_prepare(GSource *source, gint *timeout_ms) 39 { 40 GAWatch *watch = (GAWatch *)source; 41 GAChannel *c = (GAChannel *)watch->channel; 42 GAChannelReadState *rs = &c->rstate; 43 DWORD count_read, count_to_read = 0; 44 bool success; 45 GIOCondition new_events = 0; 46 47 g_debug("prepare"); 48 /* go ahead and submit another read if there's room in the buffer 49 * and no previous reads are outstanding 50 */ 51 if (!rs->ov_pending) { 52 if (rs->cur + rs->pending >= rs->buf_size) { 53 if (rs->cur) { 54 memmove(rs->buf, rs->buf + rs->cur, rs->pending); 55 rs->cur = 0; 56 } 57 } 58 count_to_read = rs->buf_size - rs->cur - rs->pending; 59 } 60 61 if (rs->ov_pending || count_to_read <= 0) { 62 goto out; 63 } 64 65 /* submit the read */ 66 success = ReadFile(c->handle, rs->buf + rs->cur + rs->pending, 67 count_to_read, &count_read, &rs->ov); 68 if (success) { 69 rs->pending += count_read; 70 rs->ov_pending = false; 71 } else { 72 if (GetLastError() == ERROR_IO_PENDING) { 73 rs->ov_pending = true; 74 } else { 75 new_events |= G_IO_ERR; 76 } 77 } 78 79 out: 80 /* dont block forever, iterate the main loop every once and a while */ 81 *timeout_ms = 500; 82 /* if there's data in the read buffer, or another event is pending, 83 * skip polling and issue user cb. 84 */ 85 if (rs->pending) { 86 new_events |= G_IO_IN; 87 } 88 c->pending_events |= new_events; 89 return !!c->pending_events; 90 } 91 92 /* 93 * Called by glib after an outstanding read request is completed. 94 */ 95 static gboolean ga_channel_check(GSource *source) 96 { 97 GAWatch *watch = (GAWatch *)source; 98 GAChannel *c = (GAChannel *)watch->channel; 99 GAChannelReadState *rs = &c->rstate; 100 DWORD count_read, error; 101 BOOL success; 102 103 GIOCondition new_events = 0; 104 105 g_debug("check"); 106 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. 113 */ 114 g_assert(rs->ov_pending); 115 116 success = GetOverlappedResult(c->handle, &rs->ov, &count_read, FALSE); 117 if (success) { 118 g_debug("thread: overlapped result, count_read: %d", (int)count_read); 119 rs->pending += count_read; 120 new_events |= G_IO_IN; 121 } else { 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. 133 */ 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; 138 } 139 } 140 141 if (new_events) { 142 rs->ov_pending = 0; 143 } 144 c->pending_events |= new_events; 145 146 return !!c->pending_events; 147 } 148 149 /* 150 * Called by glib after either prepare or check routines signal readiness 151 */ 152 static gboolean ga_channel_dispatch(GSource *source, GSourceFunc unused, 153 gpointer user_data) 154 { 155 GAWatch *watch = (GAWatch *)source; 156 GAChannel *c = (GAChannel *)watch->channel; 157 GAChannelReadState *rs = &c->rstate; 158 gboolean success; 159 160 g_debug("dispatch"); 161 success = c->cb(watch->pollfd.revents, c->user_data); 162 163 if (c->pending_events & G_IO_ERR) { 164 g_critical("channel error, removing source"); 165 return false; 166 } 167 168 /* TODO: replace rs->pending with watch->revents */ 169 c->pending_events &= ~G_IO_HUP; 170 if (!rs->pending) { 171 c->pending_events &= ~G_IO_IN; 172 } else { 173 c->pending_events = 0; 174 } 175 return success; 176 } 177 178 static void ga_channel_finalize(GSource *source) 179 { 180 g_debug("finalize"); 181 } 182 183 GSourceFuncs ga_channel_watch_funcs = { 184 ga_channel_prepare, 185 ga_channel_check, 186 ga_channel_dispatch, 187 ga_channel_finalize 188 }; 189 190 static GSource *ga_channel_create_watch(GAChannel *c) 191 { 192 GSource *source = g_source_new(&ga_channel_watch_funcs, sizeof(GAWatch)); 193 GAWatch *watch = (GAWatch *)source; 194 195 watch->channel = c; 196 watch->pollfd.fd = (gintptr) c->rstate.ov.hEvent; 197 g_source_add_poll(source, &watch->pollfd); 198 199 return source; 200 } 201 202 GIOStatus ga_channel_read(GAChannel *c, char *buf, size_t size, gsize *count) 203 { 204 GAChannelReadState *rs = &c->rstate; 205 GIOStatus status; 206 size_t to_read = 0; 207 208 if (c->pending_events & G_IO_ERR) { 209 return G_IO_STATUS_ERROR; 210 } 211 212 *count = to_read = MIN(size, rs->pending); 213 if (to_read) { 214 memcpy(buf, rs->buf + rs->cur, to_read); 215 rs->cur += to_read; 216 rs->pending -= to_read; 217 status = G_IO_STATUS_NORMAL; 218 } else { 219 status = G_IO_STATUS_AGAIN; 220 } 221 222 return status; 223 } 224 225 static GIOStatus ga_channel_write(GAChannel *c, const char *buf, size_t size, 226 size_t *count) 227 { 228 GIOStatus status; 229 OVERLAPPED ov = {0}; 230 BOOL ret; 231 DWORD written; 232 233 ov.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 234 ret = WriteFile(c->handle, buf, size, &written, &ov); 235 if (!ret) { 236 if (GetLastError() == ERROR_IO_PENDING) { 237 /* write is pending */ 238 ret = GetOverlappedResult(c->handle, &ov, &written, TRUE); 239 if (!ret) { 240 if (!GetLastError()) { 241 status = G_IO_STATUS_AGAIN; 242 } else { 243 status = G_IO_STATUS_ERROR; 244 } 245 } else { 246 /* write is complete */ 247 status = G_IO_STATUS_NORMAL; 248 *count = written; 249 } 250 } else { 251 status = G_IO_STATUS_ERROR; 252 } 253 } else { 254 /* write returned immediately */ 255 status = G_IO_STATUS_NORMAL; 256 *count = written; 257 } 258 259 if (ov.hEvent) { 260 CloseHandle(ov.hEvent); 261 ov.hEvent = NULL; 262 } 263 return status; 264 } 265 266 GIOStatus ga_channel_write_all(GAChannel *c, const char *buf, size_t size) 267 { 268 GIOStatus status = G_IO_STATUS_NORMAL; 269 size_t count = 0; 270 271 while (size) { 272 status = ga_channel_write(c, buf, size, &count); 273 if (status == G_IO_STATUS_NORMAL) { 274 size -= count; 275 buf += count; 276 } else if (status != G_IO_STATUS_AGAIN) { 277 break; 278 } 279 } 280 281 return status; 282 } 283 284 static gboolean ga_channel_open(GAChannel *c, GAChannelMethod method, 285 const gchar *path) 286 { 287 COMMTIMEOUTS comTimeOut = {0}; 288 gchar newpath[MAXPATHLEN] = {0}; 289 comTimeOut.ReadIntervalTimeout = 1; 290 291 if (method != GA_CHANNEL_VIRTIO_SERIAL && method != GA_CHANNEL_ISA_SERIAL) { 292 g_critical("unsupported communication method"); 293 return false; 294 } 295 296 if (method == GA_CHANNEL_ISA_SERIAL){ 297 snprintf(newpath, sizeof(newpath), "\\\\.\\%s", path); 298 }else { 299 g_strlcpy(newpath, path, sizeof(newpath)); 300 } 301 302 c->handle = CreateFile(newpath, GENERIC_READ | GENERIC_WRITE, 0, NULL, 303 OPEN_EXISTING, 304 FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL); 305 if (c->handle == INVALID_HANDLE_VALUE) { 306 g_critical("error opening path %s", newpath); 307 return false; 308 } 309 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); 313 return false; 314 } 315 316 return true; 317 } 318 319 GAChannel *ga_channel_new(GAChannelMethod method, const gchar *path, 320 GAChannelCallback cb, gpointer opaque) 321 { 322 GAChannel *c = g_new0(GAChannel, 1); 323 SECURITY_ATTRIBUTES sec_attrs; 324 325 if (!ga_channel_open(c, method, path)) { 326 g_critical("error opening channel"); 327 g_free(c); 328 return NULL; 329 } 330 331 c->cb = cb; 332 c->user_data = opaque; 333 334 sec_attrs.nLength = sizeof(SECURITY_ATTRIBUTES); 335 sec_attrs.lpSecurityDescriptor = NULL; 336 sec_attrs.bInheritHandle = false; 337 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); 341 342 c->source = ga_channel_create_watch(c); 343 g_source_attach(c->source, NULL); 344 return c; 345 } 346 347 void ga_channel_free(GAChannel *c) 348 { 349 if (c->source) { 350 g_source_destroy(c->source); 351 } 352 if (c->rstate.ov.hEvent) { 353 CloseHandle(c->rstate.ov.hEvent); 354 } 355 g_free(c->rstate.buf); 356 g_free(c); 357 } 358