2
0

channel-win32.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. #include "qemu/osdep.h"
  2. #include <windows.h>
  3. #include <io.h>
  4. #include "guest-agent-core.h"
  5. #include "channel.h"
  6. typedef struct GAChannelReadState {
  7. guint thread_id;
  8. uint8_t *buf;
  9. size_t buf_size;
  10. size_t cur; /* current buffer start */
  11. size_t pending; /* pending buffered bytes to read */
  12. OVERLAPPED ov;
  13. bool ov_pending; /* whether on async read is outstanding */
  14. } GAChannelReadState;
  15. struct GAChannel {
  16. HANDLE handle;
  17. GAChannelCallback cb;
  18. gpointer user_data;
  19. GAChannelReadState rstate;
  20. GIOCondition pending_events; /* TODO: use GAWatch.pollfd.revents */
  21. GSource *source;
  22. };
  23. typedef struct GAWatch {
  24. GSource source;
  25. GPollFD pollfd;
  26. GAChannel *channel;
  27. GIOCondition events_mask;
  28. } GAWatch;
  29. /*
  30. * Called by glib prior to polling to set up poll events if polling is needed.
  31. *
  32. */
  33. static gboolean ga_channel_prepare(GSource *source, gint *timeout_ms)
  34. {
  35. GAWatch *watch = (GAWatch *)source;
  36. GAChannel *c = (GAChannel *)watch->channel;
  37. GAChannelReadState *rs = &c->rstate;
  38. DWORD count_read, count_to_read = 0;
  39. bool success;
  40. GIOCondition new_events = 0;
  41. g_debug("prepare");
  42. /* go ahead and submit another read if there's room in the buffer
  43. * and no previous reads are outstanding
  44. */
  45. if (!rs->ov_pending) {
  46. if (rs->cur + rs->pending >= rs->buf_size) {
  47. if (rs->cur) {
  48. memmove(rs->buf, rs->buf + rs->cur, rs->pending);
  49. rs->cur = 0;
  50. }
  51. }
  52. count_to_read = rs->buf_size - rs->cur - rs->pending;
  53. }
  54. if (rs->ov_pending || count_to_read <= 0) {
  55. goto out;
  56. }
  57. /* submit the read */
  58. success = ReadFile(c->handle, rs->buf + rs->cur + rs->pending,
  59. count_to_read, &count_read, &rs->ov);
  60. if (success) {
  61. rs->pending += count_read;
  62. rs->ov_pending = false;
  63. } else {
  64. if (GetLastError() == ERROR_IO_PENDING) {
  65. rs->ov_pending = true;
  66. } else {
  67. new_events |= G_IO_ERR;
  68. }
  69. }
  70. out:
  71. /* don't block forever, iterate the main loop every once in a while */
  72. *timeout_ms = 500;
  73. /* if there's data in the read buffer, or another event is pending,
  74. * skip polling and issue user cb.
  75. */
  76. if (rs->pending) {
  77. new_events |= G_IO_IN;
  78. }
  79. c->pending_events |= new_events;
  80. return !!c->pending_events;
  81. }
  82. /*
  83. * Called by glib after an outstanding read request is completed.
  84. */
  85. static gboolean ga_channel_check(GSource *source)
  86. {
  87. GAWatch *watch = (GAWatch *)source;
  88. GAChannel *c = (GAChannel *)watch->channel;
  89. GAChannelReadState *rs = &c->rstate;
  90. DWORD count_read, error;
  91. BOOL success;
  92. GIOCondition new_events = 0;
  93. g_debug("check");
  94. /* failing this implies we issued a read that completed immediately,
  95. * yet no data was placed into the buffer (and thus we did not skip
  96. * polling). but since EOF is not obtainable until we retrieve an
  97. * overlapped result, it must be the case that there was data placed
  98. * into the buffer, or an error was generated by Readfile(). in either
  99. * case, we should've skipped the polling for this round.
  100. */
  101. g_assert(rs->ov_pending);
  102. success = GetOverlappedResult(c->handle, &rs->ov, &count_read, FALSE);
  103. if (success) {
  104. g_debug("thread: overlapped result, count_read: %d", (int)count_read);
  105. rs->pending += count_read;
  106. new_events |= G_IO_IN;
  107. } else {
  108. error = GetLastError();
  109. if (error == 0 || error == ERROR_HANDLE_EOF ||
  110. error == ERROR_NO_SYSTEM_RESOURCES ||
  111. error == ERROR_OPERATION_ABORTED) {
  112. /* note: On WinXP SP3 with rhel6ga virtio-win-1.1.16 vioser drivers,
  113. * ENSR seems to be synonymous with when we'd normally expect
  114. * ERROR_HANDLE_EOF. So treat it as such. Microsoft's
  115. * recommendation for ERROR_NO_SYSTEM_RESOURCES is to
  116. * retry the read, so this happens to work out anyway. On newer
  117. * virtio-win driver, this seems to be replaced with EOA, so
  118. * handle that in the same fashion.
  119. */
  120. new_events |= G_IO_HUP;
  121. } else if (error != ERROR_IO_INCOMPLETE) {
  122. g_critical("error retrieving overlapped result: %d", (int)error);
  123. new_events |= G_IO_ERR;
  124. }
  125. }
  126. if (new_events) {
  127. rs->ov_pending = 0;
  128. }
  129. c->pending_events |= new_events;
  130. return !!c->pending_events;
  131. }
  132. /*
  133. * Called by glib after either prepare or check routines signal readiness
  134. */
  135. static gboolean ga_channel_dispatch(GSource *source, GSourceFunc unused,
  136. gpointer user_data)
  137. {
  138. GAWatch *watch = (GAWatch *)source;
  139. GAChannel *c = (GAChannel *)watch->channel;
  140. GAChannelReadState *rs = &c->rstate;
  141. gboolean success;
  142. g_debug("dispatch");
  143. success = c->cb(watch->pollfd.revents, c->user_data);
  144. if (c->pending_events & G_IO_ERR) {
  145. g_critical("channel error, removing source");
  146. return false;
  147. }
  148. /* TODO: replace rs->pending with watch->revents */
  149. c->pending_events &= ~G_IO_HUP;
  150. if (!rs->pending) {
  151. c->pending_events &= ~G_IO_IN;
  152. } else {
  153. c->pending_events = 0;
  154. }
  155. return success;
  156. }
  157. static void ga_channel_finalize(GSource *source)
  158. {
  159. g_debug("finalize");
  160. }
  161. GSourceFuncs ga_channel_watch_funcs = {
  162. ga_channel_prepare,
  163. ga_channel_check,
  164. ga_channel_dispatch,
  165. ga_channel_finalize
  166. };
  167. static GSource *ga_channel_create_watch(GAChannel *c)
  168. {
  169. GSource *source = g_source_new(&ga_channel_watch_funcs, sizeof(GAWatch));
  170. GAWatch *watch = (GAWatch *)source;
  171. watch->channel = c;
  172. watch->pollfd.fd = (gintptr) c->rstate.ov.hEvent;
  173. g_source_add_poll(source, &watch->pollfd);
  174. return source;
  175. }
  176. GIOStatus ga_channel_read(GAChannel *c, char *buf, size_t size, gsize *count)
  177. {
  178. GAChannelReadState *rs = &c->rstate;
  179. GIOStatus status;
  180. size_t to_read = 0;
  181. if (c->pending_events & G_IO_ERR) {
  182. return G_IO_STATUS_ERROR;
  183. }
  184. *count = to_read = MIN(size, rs->pending);
  185. if (to_read) {
  186. memcpy(buf, rs->buf + rs->cur, to_read);
  187. rs->cur += to_read;
  188. rs->pending -= to_read;
  189. status = G_IO_STATUS_NORMAL;
  190. } else {
  191. status = G_IO_STATUS_AGAIN;
  192. }
  193. return status;
  194. }
  195. static GIOStatus ga_channel_write(GAChannel *c, const char *buf, size_t size,
  196. size_t *count)
  197. {
  198. GIOStatus status;
  199. OVERLAPPED ov = {0};
  200. BOOL ret;
  201. DWORD written;
  202. ov.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  203. ret = WriteFile(c->handle, buf, size, &written, &ov);
  204. if (!ret) {
  205. if (GetLastError() == ERROR_IO_PENDING) {
  206. /* write is pending */
  207. ret = GetOverlappedResult(c->handle, &ov, &written, TRUE);
  208. if (!ret) {
  209. if (!GetLastError()) {
  210. status = G_IO_STATUS_AGAIN;
  211. } else {
  212. status = G_IO_STATUS_ERROR;
  213. }
  214. } else {
  215. /* write is complete */
  216. status = G_IO_STATUS_NORMAL;
  217. *count = written;
  218. }
  219. } else {
  220. status = G_IO_STATUS_ERROR;
  221. }
  222. } else {
  223. /* write returned immediately */
  224. status = G_IO_STATUS_NORMAL;
  225. *count = written;
  226. }
  227. if (ov.hEvent) {
  228. CloseHandle(ov.hEvent);
  229. ov.hEvent = NULL;
  230. }
  231. return status;
  232. }
  233. GIOStatus ga_channel_write_all(GAChannel *c, const char *buf, size_t size)
  234. {
  235. GIOStatus status = G_IO_STATUS_NORMAL;
  236. size_t count = 0;
  237. while (size) {
  238. status = ga_channel_write(c, buf, size, &count);
  239. if (status == G_IO_STATUS_NORMAL) {
  240. size -= count;
  241. buf += count;
  242. } else if (status != G_IO_STATUS_AGAIN) {
  243. break;
  244. }
  245. }
  246. return status;
  247. }
  248. static gboolean ga_channel_open(GAChannel *c, GAChannelMethod method,
  249. const gchar *path)
  250. {
  251. COMMTIMEOUTS comTimeOut = {0};
  252. gchar newpath[MAXPATHLEN] = {0};
  253. comTimeOut.ReadIntervalTimeout = 1;
  254. if (method != GA_CHANNEL_VIRTIO_SERIAL && method != GA_CHANNEL_ISA_SERIAL) {
  255. g_critical("unsupported communication method");
  256. return false;
  257. }
  258. if (method == GA_CHANNEL_ISA_SERIAL) {
  259. snprintf(newpath, sizeof(newpath), "\\\\.\\%s", path);
  260. } else {
  261. g_strlcpy(newpath, path, sizeof(newpath));
  262. }
  263. c->handle = CreateFile(newpath, GENERIC_READ | GENERIC_WRITE, 0, NULL,
  264. OPEN_EXISTING,
  265. FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL);
  266. if (c->handle == INVALID_HANDLE_VALUE) {
  267. g_autofree gchar *emsg = g_win32_error_message(GetLastError());
  268. g_critical("error opening path %s: %s", newpath, emsg);
  269. return false;
  270. }
  271. if (method == GA_CHANNEL_ISA_SERIAL
  272. && !SetCommTimeouts(c->handle, &comTimeOut)) {
  273. g_autofree gchar *emsg = g_win32_error_message(GetLastError());
  274. g_critical("error setting timeout for com port: %s", emsg);
  275. CloseHandle(c->handle);
  276. return false;
  277. }
  278. return true;
  279. }
  280. GAChannel *ga_channel_new(GAChannelMethod method, const gchar *path,
  281. int listen_fd, GAChannelCallback cb, gpointer opaque)
  282. {
  283. GAChannel *c = g_new0(GAChannel, 1);
  284. SECURITY_ATTRIBUTES sec_attrs;
  285. if (!ga_channel_open(c, method, path)) {
  286. g_critical("error opening channel");
  287. g_free(c);
  288. return NULL;
  289. }
  290. c->cb = cb;
  291. c->user_data = opaque;
  292. sec_attrs.nLength = sizeof(SECURITY_ATTRIBUTES);
  293. sec_attrs.lpSecurityDescriptor = NULL;
  294. sec_attrs.bInheritHandle = false;
  295. c->rstate.buf_size = QGA_READ_COUNT_DEFAULT;
  296. c->rstate.buf = g_malloc(QGA_READ_COUNT_DEFAULT);
  297. c->rstate.ov.hEvent = CreateEvent(&sec_attrs, FALSE, FALSE, NULL);
  298. c->source = ga_channel_create_watch(c);
  299. g_source_attach(c->source, NULL);
  300. return c;
  301. }
  302. void ga_channel_free(GAChannel *c)
  303. {
  304. if (c->source) {
  305. g_source_destroy(c->source);
  306. }
  307. if (c->rstate.ov.hEvent) {
  308. CloseHandle(c->rstate.ov.hEvent);
  309. }
  310. g_free(c->rstate.buf);
  311. g_free(c);
  312. }