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