racer 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (336) hide show
  1. data/LICENSE +22 -0
  2. data/bin/racer +33 -0
  3. data/ext/libuv/AUTHORS +45 -0
  4. data/ext/libuv/LICENSE +42 -0
  5. data/ext/libuv/Makefile +119 -0
  6. data/ext/libuv/README.md +88 -0
  7. data/ext/libuv/build/gcc_version.py +20 -0
  8. data/ext/libuv/common.gypi +176 -0
  9. data/ext/libuv/config-mingw.mk +61 -0
  10. data/ext/libuv/config-unix.mk +171 -0
  11. data/ext/libuv/gyp_uv +64 -0
  12. data/ext/libuv/include/ares.h +591 -0
  13. data/ext/libuv/include/ares_version.h +24 -0
  14. data/ext/libuv/include/uv-private/eio.h +403 -0
  15. data/ext/libuv/include/uv-private/ev.h +838 -0
  16. data/ext/libuv/include/uv-private/ngx-queue.h +108 -0
  17. data/ext/libuv/include/uv-private/tree.h +768 -0
  18. data/ext/libuv/include/uv-private/uv-unix.h +310 -0
  19. data/ext/libuv/include/uv-private/uv-win.h +510 -0
  20. data/ext/libuv/include/uv.h +1796 -0
  21. data/ext/libuv/src/ares/AUTHORS +37 -0
  22. data/ext/libuv/src/ares/CHANGES +1218 -0
  23. data/ext/libuv/src/ares/CMakeLists.txt +22 -0
  24. data/ext/libuv/src/ares/NEWS +21 -0
  25. data/ext/libuv/src/ares/README +60 -0
  26. data/ext/libuv/src/ares/README.cares +13 -0
  27. data/ext/libuv/src/ares/README.msvc +142 -0
  28. data/ext/libuv/src/ares/README.node +21 -0
  29. data/ext/libuv/src/ares/RELEASE-NOTES +26 -0
  30. data/ext/libuv/src/ares/TODO +23 -0
  31. data/ext/libuv/src/ares/ares__close_sockets.c +66 -0
  32. data/ext/libuv/src/ares/ares__get_hostent.c +263 -0
  33. data/ext/libuv/src/ares/ares__read_line.c +71 -0
  34. data/ext/libuv/src/ares/ares__timeval.c +111 -0
  35. data/ext/libuv/src/ares/ares_cancel.c +63 -0
  36. data/ext/libuv/src/ares/ares_data.c +190 -0
  37. data/ext/libuv/src/ares/ares_data.h +65 -0
  38. data/ext/libuv/src/ares/ares_destroy.c +105 -0
  39. data/ext/libuv/src/ares/ares_dns.h +90 -0
  40. data/ext/libuv/src/ares/ares_expand_name.c +200 -0
  41. data/ext/libuv/src/ares/ares_expand_string.c +75 -0
  42. data/ext/libuv/src/ares/ares_fds.c +63 -0
  43. data/ext/libuv/src/ares/ares_free_hostent.c +42 -0
  44. data/ext/libuv/src/ares/ares_free_string.c +25 -0
  45. data/ext/libuv/src/ares/ares_getenv.c +30 -0
  46. data/ext/libuv/src/ares/ares_getenv.h +26 -0
  47. data/ext/libuv/src/ares/ares_gethostbyaddr.c +301 -0
  48. data/ext/libuv/src/ares/ares_gethostbyname.c +523 -0
  49. data/ext/libuv/src/ares/ares_getnameinfo.c +427 -0
  50. data/ext/libuv/src/ares/ares_getopt.c +122 -0
  51. data/ext/libuv/src/ares/ares_getopt.h +53 -0
  52. data/ext/libuv/src/ares/ares_getsock.c +72 -0
  53. data/ext/libuv/src/ares/ares_init.c +1809 -0
  54. data/ext/libuv/src/ares/ares_iphlpapi.h +221 -0
  55. data/ext/libuv/src/ares/ares_ipv6.h +78 -0
  56. data/ext/libuv/src/ares/ares_library_init.c +142 -0
  57. data/ext/libuv/src/ares/ares_library_init.h +42 -0
  58. data/ext/libuv/src/ares/ares_llist.c +86 -0
  59. data/ext/libuv/src/ares/ares_llist.h +42 -0
  60. data/ext/libuv/src/ares/ares_mkquery.c +195 -0
  61. data/ext/libuv/src/ares/ares_nowarn.c +181 -0
  62. data/ext/libuv/src/ares/ares_nowarn.h +55 -0
  63. data/ext/libuv/src/ares/ares_options.c +248 -0
  64. data/ext/libuv/src/ares/ares_parse_a_reply.c +263 -0
  65. data/ext/libuv/src/ares/ares_parse_aaaa_reply.c +259 -0
  66. data/ext/libuv/src/ares/ares_parse_mx_reply.c +170 -0
  67. data/ext/libuv/src/ares/ares_parse_ns_reply.c +182 -0
  68. data/ext/libuv/src/ares/ares_parse_ptr_reply.c +217 -0
  69. data/ext/libuv/src/ares/ares_parse_srv_reply.c +179 -0
  70. data/ext/libuv/src/ares/ares_parse_txt_reply.c +201 -0
  71. data/ext/libuv/src/ares/ares_platform.c +11035 -0
  72. data/ext/libuv/src/ares/ares_platform.h +43 -0
  73. data/ext/libuv/src/ares/ares_private.h +355 -0
  74. data/ext/libuv/src/ares/ares_process.c +1295 -0
  75. data/ext/libuv/src/ares/ares_query.c +183 -0
  76. data/ext/libuv/src/ares/ares_rules.h +144 -0
  77. data/ext/libuv/src/ares/ares_search.c +321 -0
  78. data/ext/libuv/src/ares/ares_send.c +134 -0
  79. data/ext/libuv/src/ares/ares_setup.h +199 -0
  80. data/ext/libuv/src/ares/ares_strcasecmp.c +66 -0
  81. data/ext/libuv/src/ares/ares_strcasecmp.h +30 -0
  82. data/ext/libuv/src/ares/ares_strdup.c +42 -0
  83. data/ext/libuv/src/ares/ares_strdup.h +26 -0
  84. data/ext/libuv/src/ares/ares_strerror.c +56 -0
  85. data/ext/libuv/src/ares/ares_timeout.c +80 -0
  86. data/ext/libuv/src/ares/ares_version.c +11 -0
  87. data/ext/libuv/src/ares/ares_writev.c +79 -0
  88. data/ext/libuv/src/ares/ares_writev.h +36 -0
  89. data/ext/libuv/src/ares/bitncmp.c +59 -0
  90. data/ext/libuv/src/ares/bitncmp.h +26 -0
  91. data/ext/libuv/src/ares/config_cygwin/ares_config.h +512 -0
  92. data/ext/libuv/src/ares/config_darwin/ares_config.h +512 -0
  93. data/ext/libuv/src/ares/config_freebsd/ares_config.h +512 -0
  94. data/ext/libuv/src/ares/config_linux/ares_config.h +512 -0
  95. data/ext/libuv/src/ares/config_netbsd/ares_config.h +512 -0
  96. data/ext/libuv/src/ares/config_openbsd/ares_config.h +512 -0
  97. data/ext/libuv/src/ares/config_sunos/ares_config.h +512 -0
  98. data/ext/libuv/src/ares/config_win32/ares_config.h +369 -0
  99. data/ext/libuv/src/ares/get_ver.awk +35 -0
  100. data/ext/libuv/src/ares/inet_net_pton.c +451 -0
  101. data/ext/libuv/src/ares/inet_net_pton.h +31 -0
  102. data/ext/libuv/src/ares/inet_ntop.c +208 -0
  103. data/ext/libuv/src/ares/inet_ntop.h +26 -0
  104. data/ext/libuv/src/ares/nameser.h +203 -0
  105. data/ext/libuv/src/ares/setup_once.h +504 -0
  106. data/ext/libuv/src/ares/windows_port.c +22 -0
  107. data/ext/libuv/src/cares.c +225 -0
  108. data/ext/libuv/src/fs-poll.c +237 -0
  109. data/ext/libuv/src/unix/async.c +119 -0
  110. data/ext/libuv/src/unix/core.c +647 -0
  111. data/ext/libuv/src/unix/cygwin.c +84 -0
  112. data/ext/libuv/src/unix/darwin.c +341 -0
  113. data/ext/libuv/src/unix/dl.c +83 -0
  114. data/ext/libuv/src/unix/eio/Changes +63 -0
  115. data/ext/libuv/src/unix/eio/LICENSE +36 -0
  116. data/ext/libuv/src/unix/eio/Makefile.am +15 -0
  117. data/ext/libuv/src/unix/eio/aclocal.m4 +8957 -0
  118. data/ext/libuv/src/unix/eio/autogen.sh +3 -0
  119. data/ext/libuv/src/unix/eio/config.h.in +86 -0
  120. data/ext/libuv/src/unix/eio/config_cygwin.h +80 -0
  121. data/ext/libuv/src/unix/eio/config_darwin.h +141 -0
  122. data/ext/libuv/src/unix/eio/config_freebsd.h +81 -0
  123. data/ext/libuv/src/unix/eio/config_linux.h +94 -0
  124. data/ext/libuv/src/unix/eio/config_netbsd.h +81 -0
  125. data/ext/libuv/src/unix/eio/config_openbsd.h +137 -0
  126. data/ext/libuv/src/unix/eio/config_sunos.h +84 -0
  127. data/ext/libuv/src/unix/eio/configure.ac +22 -0
  128. data/ext/libuv/src/unix/eio/demo.c +194 -0
  129. data/ext/libuv/src/unix/eio/ecb.h +370 -0
  130. data/ext/libuv/src/unix/eio/eio.3 +3428 -0
  131. data/ext/libuv/src/unix/eio/eio.c +2593 -0
  132. data/ext/libuv/src/unix/eio/eio.pod +969 -0
  133. data/ext/libuv/src/unix/eio/libeio.m4 +195 -0
  134. data/ext/libuv/src/unix/eio/xthread.h +164 -0
  135. data/ext/libuv/src/unix/error.c +104 -0
  136. data/ext/libuv/src/unix/ev/Changes +388 -0
  137. data/ext/libuv/src/unix/ev/LICENSE +36 -0
  138. data/ext/libuv/src/unix/ev/Makefile.am +18 -0
  139. data/ext/libuv/src/unix/ev/Makefile.in +771 -0
  140. data/ext/libuv/src/unix/ev/README +58 -0
  141. data/ext/libuv/src/unix/ev/aclocal.m4 +8957 -0
  142. data/ext/libuv/src/unix/ev/autogen.sh +6 -0
  143. data/ext/libuv/src/unix/ev/config.guess +1526 -0
  144. data/ext/libuv/src/unix/ev/config.h.in +125 -0
  145. data/ext/libuv/src/unix/ev/config.sub +1658 -0
  146. data/ext/libuv/src/unix/ev/config_cygwin.h +123 -0
  147. data/ext/libuv/src/unix/ev/config_darwin.h +122 -0
  148. data/ext/libuv/src/unix/ev/config_freebsd.h +120 -0
  149. data/ext/libuv/src/unix/ev/config_linux.h +141 -0
  150. data/ext/libuv/src/unix/ev/config_netbsd.h +120 -0
  151. data/ext/libuv/src/unix/ev/config_openbsd.h +126 -0
  152. data/ext/libuv/src/unix/ev/config_sunos.h +122 -0
  153. data/ext/libuv/src/unix/ev/configure +13037 -0
  154. data/ext/libuv/src/unix/ev/configure.ac +18 -0
  155. data/ext/libuv/src/unix/ev/depcomp +630 -0
  156. data/ext/libuv/src/unix/ev/ev++.h +816 -0
  157. data/ext/libuv/src/unix/ev/ev.3 +5311 -0
  158. data/ext/libuv/src/unix/ev/ev.c +3925 -0
  159. data/ext/libuv/src/unix/ev/ev.pod +5243 -0
  160. data/ext/libuv/src/unix/ev/ev_epoll.c +266 -0
  161. data/ext/libuv/src/unix/ev/ev_kqueue.c +235 -0
  162. data/ext/libuv/src/unix/ev/ev_poll.c +148 -0
  163. data/ext/libuv/src/unix/ev/ev_port.c +179 -0
  164. data/ext/libuv/src/unix/ev/ev_select.c +310 -0
  165. data/ext/libuv/src/unix/ev/ev_vars.h +203 -0
  166. data/ext/libuv/src/unix/ev/ev_win32.c +153 -0
  167. data/ext/libuv/src/unix/ev/ev_wrap.h +196 -0
  168. data/ext/libuv/src/unix/ev/event.c +402 -0
  169. data/ext/libuv/src/unix/ev/event.h +170 -0
  170. data/ext/libuv/src/unix/ev/install-sh +294 -0
  171. data/ext/libuv/src/unix/ev/libev.m4 +39 -0
  172. data/ext/libuv/src/unix/ev/ltmain.sh +8413 -0
  173. data/ext/libuv/src/unix/ev/missing +336 -0
  174. data/ext/libuv/src/unix/ev/mkinstalldirs +111 -0
  175. data/ext/libuv/src/unix/freebsd.c +312 -0
  176. data/ext/libuv/src/unix/fs.c +699 -0
  177. data/ext/libuv/src/unix/internal.h +180 -0
  178. data/ext/libuv/src/unix/kqueue.c +122 -0
  179. data/ext/libuv/src/unix/linux/core.c +474 -0
  180. data/ext/libuv/src/unix/linux/inotify.c +209 -0
  181. data/ext/libuv/src/unix/linux/syscalls.c +268 -0
  182. data/ext/libuv/src/unix/linux/syscalls.h +93 -0
  183. data/ext/libuv/src/unix/loop-watcher.c +63 -0
  184. data/ext/libuv/src/unix/loop.c +81 -0
  185. data/ext/libuv/src/unix/netbsd.c +108 -0
  186. data/ext/libuv/src/unix/openbsd.c +295 -0
  187. data/ext/libuv/src/unix/pipe.c +261 -0
  188. data/ext/libuv/src/unix/poll.c +116 -0
  189. data/ext/libuv/src/unix/process.c +447 -0
  190. data/ext/libuv/src/unix/stream.c +1026 -0
  191. data/ext/libuv/src/unix/sunos.c +483 -0
  192. data/ext/libuv/src/unix/tcp.c +328 -0
  193. data/ext/libuv/src/unix/thread.c +211 -0
  194. data/ext/libuv/src/unix/timer.c +138 -0
  195. data/ext/libuv/src/unix/tty.c +146 -0
  196. data/ext/libuv/src/unix/udp.c +661 -0
  197. data/ext/libuv/src/unix/uv-eio.c +107 -0
  198. data/ext/libuv/src/unix/uv-eio.h +13 -0
  199. data/ext/libuv/src/uv-common.c +384 -0
  200. data/ext/libuv/src/uv-common.h +171 -0
  201. data/ext/libuv/src/win/async.c +130 -0
  202. data/ext/libuv/src/win/core.c +283 -0
  203. data/ext/libuv/src/win/dl.c +86 -0
  204. data/ext/libuv/src/win/error.c +150 -0
  205. data/ext/libuv/src/win/fs-event.c +512 -0
  206. data/ext/libuv/src/win/fs.c +1856 -0
  207. data/ext/libuv/src/win/getaddrinfo.c +365 -0
  208. data/ext/libuv/src/win/handle-inl.h +145 -0
  209. data/ext/libuv/src/win/handle.c +150 -0
  210. data/ext/libuv/src/win/internal.h +337 -0
  211. data/ext/libuv/src/win/loop-watcher.c +123 -0
  212. data/ext/libuv/src/win/pipe.c +1675 -0
  213. data/ext/libuv/src/win/poll.c +618 -0
  214. data/ext/libuv/src/win/process-stdio.c +479 -0
  215. data/ext/libuv/src/win/process.c +1013 -0
  216. data/ext/libuv/src/win/req-inl.h +225 -0
  217. data/ext/libuv/src/win/req.c +25 -0
  218. data/ext/libuv/src/win/stream-inl.h +69 -0
  219. data/ext/libuv/src/win/stream.c +167 -0
  220. data/ext/libuv/src/win/tcp.c +1400 -0
  221. data/ext/libuv/src/win/thread.c +372 -0
  222. data/ext/libuv/src/win/threadpool.c +74 -0
  223. data/ext/libuv/src/win/timer.c +226 -0
  224. data/ext/libuv/src/win/tty.c +1801 -0
  225. data/ext/libuv/src/win/udp.c +718 -0
  226. data/ext/libuv/src/win/util.c +864 -0
  227. data/ext/libuv/src/win/winapi.c +132 -0
  228. data/ext/libuv/src/win/winapi.h +4443 -0
  229. data/ext/libuv/src/win/winsock.c +557 -0
  230. data/ext/libuv/src/win/winsock.h +171 -0
  231. data/ext/libuv/test/benchmark-ares.c +117 -0
  232. data/ext/libuv/test/benchmark-fs-stat.c +164 -0
  233. data/ext/libuv/test/benchmark-getaddrinfo.c +94 -0
  234. data/ext/libuv/test/benchmark-list.h +114 -0
  235. data/ext/libuv/test/benchmark-loop-count.c +88 -0
  236. data/ext/libuv/test/benchmark-million-timers.c +65 -0
  237. data/ext/libuv/test/benchmark-ping-pongs.c +213 -0
  238. data/ext/libuv/test/benchmark-pound.c +324 -0
  239. data/ext/libuv/test/benchmark-pump.c +462 -0
  240. data/ext/libuv/test/benchmark-sizes.c +42 -0
  241. data/ext/libuv/test/benchmark-spawn.c +162 -0
  242. data/ext/libuv/test/benchmark-tcp-write-batch.c +140 -0
  243. data/ext/libuv/test/benchmark-thread.c +64 -0
  244. data/ext/libuv/test/benchmark-udp-packet-storm.c +247 -0
  245. data/ext/libuv/test/blackhole-server.c +118 -0
  246. data/ext/libuv/test/dns-server.c +321 -0
  247. data/ext/libuv/test/echo-server.c +378 -0
  248. data/ext/libuv/test/fixtures/empty_file +0 -0
  249. data/ext/libuv/test/fixtures/load_error.node +1 -0
  250. data/ext/libuv/test/run-benchmarks.c +64 -0
  251. data/ext/libuv/test/run-tests.c +138 -0
  252. data/ext/libuv/test/runner-unix.c +290 -0
  253. data/ext/libuv/test/runner-unix.h +36 -0
  254. data/ext/libuv/test/runner-win.c +285 -0
  255. data/ext/libuv/test/runner-win.h +42 -0
  256. data/ext/libuv/test/runner.c +326 -0
  257. data/ext/libuv/test/runner.h +159 -0
  258. data/ext/libuv/test/task.h +109 -0
  259. data/ext/libuv/test/test-async.c +118 -0
  260. data/ext/libuv/test/test-callback-order.c +76 -0
  261. data/ext/libuv/test/test-callback-stack.c +203 -0
  262. data/ext/libuv/test/test-connection-fail.c +148 -0
  263. data/ext/libuv/test/test-counters-init.c +215 -0
  264. data/ext/libuv/test/test-cwd-and-chdir.c +64 -0
  265. data/ext/libuv/test/test-delayed-accept.c +197 -0
  266. data/ext/libuv/test/test-dlerror.c +58 -0
  267. data/ext/libuv/test/test-error.c +59 -0
  268. data/ext/libuv/test/test-fail-always.c +29 -0
  269. data/ext/libuv/test/test-fs-event.c +442 -0
  270. data/ext/libuv/test/test-fs-poll.c +146 -0
  271. data/ext/libuv/test/test-fs.c +1843 -0
  272. data/ext/libuv/test/test-get-currentexe.c +63 -0
  273. data/ext/libuv/test/test-get-loadavg.c +36 -0
  274. data/ext/libuv/test/test-get-memory.c +38 -0
  275. data/ext/libuv/test/test-getaddrinfo.c +122 -0
  276. data/ext/libuv/test/test-gethostbyname.c +189 -0
  277. data/ext/libuv/test/test-getsockname.c +342 -0
  278. data/ext/libuv/test/test-hrtime.c +54 -0
  279. data/ext/libuv/test/test-idle.c +81 -0
  280. data/ext/libuv/test/test-ipc-send-recv.c +209 -0
  281. data/ext/libuv/test/test-ipc.c +620 -0
  282. data/ext/libuv/test/test-list.h +421 -0
  283. data/ext/libuv/test/test-loop-handles.c +336 -0
  284. data/ext/libuv/test/test-multiple-listen.c +102 -0
  285. data/ext/libuv/test/test-mutexes.c +63 -0
  286. data/ext/libuv/test/test-pass-always.c +28 -0
  287. data/ext/libuv/test/test-ping-pong.c +253 -0
  288. data/ext/libuv/test/test-pipe-bind-error.c +140 -0
  289. data/ext/libuv/test/test-pipe-connect-error.c +96 -0
  290. data/ext/libuv/test/test-platform-output.c +87 -0
  291. data/ext/libuv/test/test-poll-close.c +77 -0
  292. data/ext/libuv/test/test-poll.c +573 -0
  293. data/ext/libuv/test/test-process-title.c +42 -0
  294. data/ext/libuv/test/test-ref.c +338 -0
  295. data/ext/libuv/test/test-run-once.c +48 -0
  296. data/ext/libuv/test/test-semaphore.c +111 -0
  297. data/ext/libuv/test/test-shutdown-close.c +103 -0
  298. data/ext/libuv/test/test-shutdown-eof.c +183 -0
  299. data/ext/libuv/test/test-spawn.c +847 -0
  300. data/ext/libuv/test/test-stdio-over-pipes.c +246 -0
  301. data/ext/libuv/test/test-tcp-bind-error.c +191 -0
  302. data/ext/libuv/test/test-tcp-bind6-error.c +154 -0
  303. data/ext/libuv/test/test-tcp-close-while-connecting.c +80 -0
  304. data/ext/libuv/test/test-tcp-close.c +129 -0
  305. data/ext/libuv/test/test-tcp-connect-error-after-write.c +95 -0
  306. data/ext/libuv/test/test-tcp-connect-error.c +70 -0
  307. data/ext/libuv/test/test-tcp-connect-timeout.c +85 -0
  308. data/ext/libuv/test/test-tcp-connect6-error.c +68 -0
  309. data/ext/libuv/test/test-tcp-flags.c +51 -0
  310. data/ext/libuv/test/test-tcp-shutdown-after-write.c +131 -0
  311. data/ext/libuv/test/test-tcp-write-error.c +168 -0
  312. data/ext/libuv/test/test-tcp-write-to-half-open-connection.c +135 -0
  313. data/ext/libuv/test/test-tcp-writealot.c +170 -0
  314. data/ext/libuv/test/test-thread.c +183 -0
  315. data/ext/libuv/test/test-threadpool.c +57 -0
  316. data/ext/libuv/test/test-timer-again.c +141 -0
  317. data/ext/libuv/test/test-timer.c +152 -0
  318. data/ext/libuv/test/test-tty.c +110 -0
  319. data/ext/libuv/test/test-udp-dgram-too-big.c +86 -0
  320. data/ext/libuv/test/test-udp-ipv6.c +156 -0
  321. data/ext/libuv/test/test-udp-multicast-join.c +139 -0
  322. data/ext/libuv/test/test-udp-multicast-ttl.c +86 -0
  323. data/ext/libuv/test/test-udp-options.c +86 -0
  324. data/ext/libuv/test/test-udp-send-and-recv.c +208 -0
  325. data/ext/libuv/test/test-util.c +97 -0
  326. data/ext/libuv/test/test-walk-handles.c +77 -0
  327. data/ext/libuv/uv.gyp +452 -0
  328. data/ext/libuv/vcbuild.bat +105 -0
  329. data/ext/racer/extconf.rb +20 -0
  330. data/ext/racer/http_parser.c +2059 -0
  331. data/ext/racer/http_parser.h +318 -0
  332. data/ext/racer/mkmf.log +22 -0
  333. data/ext/racer/racer.c +551 -0
  334. data/lib/racer.rb +2 -0
  335. data/lib/racer/version.rb +3 -0
  336. metadata +382 -0
@@ -0,0 +1,123 @@
1
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2
+ *
3
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ * of this software and associated documentation files (the "Software"), to
5
+ * deal in the Software without restriction, including without limitation the
6
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ * sell copies of the Software, and to permit persons to whom the Software is
8
+ * furnished to do so, subject to the following conditions:
9
+ *
10
+ * The above copyright notice and this permission notice shall be included in
11
+ * all copies or substantial portions of the Software.
12
+ *
13
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19
+ * IN THE SOFTWARE.
20
+ */
21
+
22
+ #include <assert.h>
23
+
24
+ #include "uv.h"
25
+ #include "internal.h"
26
+ #include "handle-inl.h"
27
+
28
+
29
+ void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle) {
30
+ if (handle->flags & UV_HANDLE_CLOSING) {
31
+ assert(!(handle->flags & UV_HANDLE_CLOSED));
32
+ handle->flags |= UV_HANDLE_CLOSED;
33
+ uv__handle_stop(handle);
34
+ uv__handle_close(handle);
35
+ }
36
+ }
37
+
38
+
39
+ #define UV_LOOP_WATCHER_DEFINE(name, NAME) \
40
+ int uv_##name##_init(uv_loop_t* loop, uv_##name##_t* handle) { \
41
+ uv__handle_init(loop, (uv_handle_t*) handle, UV_##NAME); \
42
+ loop->counters.name##_init++; \
43
+ \
44
+ return 0; \
45
+ } \
46
+ \
47
+ \
48
+ int uv_##name##_start(uv_##name##_t* handle, uv_##name##_cb cb) { \
49
+ uv_loop_t* loop = handle->loop; \
50
+ uv_##name##_t* old_head; \
51
+ \
52
+ assert(handle->type == UV_##NAME); \
53
+ \
54
+ if (handle->flags & UV_HANDLE_ACTIVE) \
55
+ return 0; \
56
+ \
57
+ old_head = loop->name##_handles; \
58
+ \
59
+ handle->name##_next = old_head; \
60
+ handle->name##_prev = NULL; \
61
+ \
62
+ if (old_head) { \
63
+ old_head->name##_prev = handle; \
64
+ } \
65
+ \
66
+ loop->name##_handles = handle; \
67
+ \
68
+ handle->name##_cb = cb; \
69
+ handle->flags |= UV_HANDLE_ACTIVE; \
70
+ uv__handle_start(handle); \
71
+ \
72
+ return 0; \
73
+ } \
74
+ \
75
+ \
76
+ int uv_##name##_stop(uv_##name##_t* handle) { \
77
+ uv_loop_t* loop = handle->loop; \
78
+ \
79
+ assert(handle->type == UV_##NAME); \
80
+ \
81
+ if (!(handle->flags & UV_HANDLE_ACTIVE)) \
82
+ return 0; \
83
+ \
84
+ /* Update loop head if needed */ \
85
+ if (loop->name##_handles == handle) { \
86
+ loop->name##_handles = handle->name##_next; \
87
+ } \
88
+ \
89
+ /* Update the iterator-next pointer of needed */ \
90
+ if (loop->next_##name##_handle == handle) { \
91
+ loop->next_##name##_handle = handle->name##_next; \
92
+ } \
93
+ \
94
+ if (handle->name##_prev) { \
95
+ handle->name##_prev->name##_next = handle->name##_next; \
96
+ } \
97
+ if (handle->name##_next) { \
98
+ handle->name##_next->name##_prev = handle->name##_prev; \
99
+ } \
100
+ \
101
+ handle->flags &= ~UV_HANDLE_ACTIVE; \
102
+ uv__handle_stop(handle); \
103
+ \
104
+ return 0; \
105
+ } \
106
+ \
107
+ \
108
+ void uv_##name##_invoke(uv_loop_t* loop) { \
109
+ uv_##name##_t* handle; \
110
+ \
111
+ (loop)->next_##name##_handle = (loop)->name##_handles; \
112
+ \
113
+ while ((loop)->next_##name##_handle != NULL) { \
114
+ handle = (loop)->next_##name##_handle; \
115
+ (loop)->next_##name##_handle = handle->name##_next; \
116
+ \
117
+ handle->name##_cb(handle, 0); \
118
+ } \
119
+ }
120
+
121
+ UV_LOOP_WATCHER_DEFINE(prepare, PREPARE)
122
+ UV_LOOP_WATCHER_DEFINE(check, CHECK)
123
+ UV_LOOP_WATCHER_DEFINE(idle, IDLE)
@@ -0,0 +1,1675 @@
1
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2
+ *
3
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ * of this software and associated documentation files (the "Software"), to
5
+ * deal in the Software without restriction, including without limitation the
6
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ * sell copies of the Software, and to permit persons to whom the Software is
8
+ * furnished to do so, subject to the following conditions:
9
+ *
10
+ * The above copyright notice and this permission notice shall be included in
11
+ * all copies or substantial portions of the Software.
12
+ *
13
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19
+ * IN THE SOFTWARE.
20
+ */
21
+
22
+ #include <assert.h>
23
+ #include <io.h>
24
+ #include <string.h>
25
+ #include <stdio.h>
26
+
27
+ #include "uv.h"
28
+ #include "internal.h"
29
+ #include "handle-inl.h"
30
+ #include "stream-inl.h"
31
+ #include "req-inl.h"
32
+
33
+
34
+ /* A zero-size buffer for use by uv_pipe_read */
35
+ static char uv_zero_[] = "";
36
+
37
+ /* Null uv_buf_t */
38
+ static const uv_buf_t uv_null_buf_ = { 0, NULL };
39
+
40
+ /* The timeout that the pipe will wait for the remote end to write data */
41
+ /* when the local ends wants to shut it down. */
42
+ static const int64_t eof_timeout = 50; /* ms */
43
+
44
+ static const int default_pending_pipe_instances = 4;
45
+
46
+ /* IPC protocol flags. */
47
+ #define UV_IPC_RAW_DATA 0x0001
48
+ #define UV_IPC_TCP_SERVER 0x0002
49
+ #define UV_IPC_TCP_CONNECTION 0x0004
50
+
51
+ /* IPC frame header. */
52
+ typedef struct {
53
+ int flags;
54
+ uint64_t raw_data_length;
55
+ } uv_ipc_frame_header_t;
56
+
57
+ /* IPC frame, which contains an imported TCP socket stream. */
58
+ typedef struct {
59
+ uv_ipc_frame_header_t header;
60
+ WSAPROTOCOL_INFOW socket_info;
61
+ } uv_ipc_frame_uv_stream;
62
+
63
+ static void eof_timer_init(uv_pipe_t* pipe);
64
+ static void eof_timer_start(uv_pipe_t* pipe);
65
+ static void eof_timer_stop(uv_pipe_t* pipe);
66
+ static void eof_timer_cb(uv_timer_t* timer, int status);
67
+ static void eof_timer_destroy(uv_pipe_t* pipe);
68
+ static void eof_timer_close_cb(uv_handle_t* handle);
69
+
70
+
71
+ static void uv_unique_pipe_name(char* ptr, char* name, size_t size) {
72
+ _snprintf(name, size, "\\\\.\\pipe\\uv\\%p-%d", ptr, GetCurrentProcessId());
73
+ }
74
+
75
+
76
+ int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) {
77
+ uv_stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE);
78
+
79
+ handle->reqs_pending = 0;
80
+ handle->handle = INVALID_HANDLE_VALUE;
81
+ handle->name = NULL;
82
+ handle->ipc_pid = 0;
83
+ handle->remaining_ipc_rawdata_bytes = 0;
84
+ handle->pending_ipc_info.socket_info = NULL;
85
+ handle->pending_ipc_info.tcp_connection = 0;
86
+ handle->ipc = ipc;
87
+ handle->non_overlapped_writes_tail = NULL;
88
+
89
+ uv_req_init(loop, (uv_req_t*) &handle->ipc_header_write_req);
90
+
91
+ loop->counters.pipe_init++;
92
+
93
+ return 0;
94
+ }
95
+
96
+
97
+ static void uv_pipe_connection_init(uv_pipe_t* handle) {
98
+ uv_connection_init((uv_stream_t*) handle);
99
+ handle->read_req.data = handle;
100
+ handle->eof_timer = NULL;
101
+ }
102
+
103
+
104
+ static HANDLE open_named_pipe(WCHAR* name, DWORD* duplex_flags) {
105
+ HANDLE pipeHandle;
106
+
107
+ /*
108
+ * Assume that we have a duplex pipe first, so attempt to
109
+ * connect with GENERIC_READ | GENERIC_WRITE.
110
+ */
111
+ pipeHandle = CreateFileW(name,
112
+ GENERIC_READ | GENERIC_WRITE,
113
+ 0,
114
+ NULL,
115
+ OPEN_EXISTING,
116
+ FILE_FLAG_OVERLAPPED,
117
+ NULL);
118
+ if (pipeHandle != INVALID_HANDLE_VALUE) {
119
+ *duplex_flags = 0;
120
+ return pipeHandle;
121
+ }
122
+
123
+ /*
124
+ * If the pipe is not duplex CreateFileW fails with
125
+ * ERROR_ACCESS_DENIED. In that case try to connect
126
+ * as a read-only or write-only.
127
+ */
128
+ if (GetLastError() == ERROR_ACCESS_DENIED) {
129
+ pipeHandle = CreateFileW(name,
130
+ GENERIC_READ | FILE_WRITE_ATTRIBUTES,
131
+ 0,
132
+ NULL,
133
+ OPEN_EXISTING,
134
+ FILE_FLAG_OVERLAPPED,
135
+ NULL);
136
+
137
+ if (pipeHandle != INVALID_HANDLE_VALUE) {
138
+ *duplex_flags = UV_HANDLE_SHUTTING;
139
+ return pipeHandle;
140
+ }
141
+ }
142
+
143
+ if (GetLastError() == ERROR_ACCESS_DENIED) {
144
+ pipeHandle = CreateFileW(name,
145
+ GENERIC_WRITE | FILE_READ_ATTRIBUTES,
146
+ 0,
147
+ NULL,
148
+ OPEN_EXISTING,
149
+ FILE_FLAG_OVERLAPPED,
150
+ NULL);
151
+
152
+ if (pipeHandle != INVALID_HANDLE_VALUE) {
153
+ *duplex_flags = UV_HANDLE_EOF;
154
+ return pipeHandle;
155
+ }
156
+ }
157
+
158
+ return INVALID_HANDLE_VALUE;
159
+ }
160
+
161
+
162
+ int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access,
163
+ char* name, size_t nameSize) {
164
+ HANDLE pipeHandle;
165
+ int errorno;
166
+ int err;
167
+ char* ptr = (char*)handle;
168
+
169
+ for (;;) {
170
+ uv_unique_pipe_name(ptr, name, nameSize);
171
+
172
+ pipeHandle = CreateNamedPipeA(name,
173
+ access | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE,
174
+ PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 65536, 65536, 0,
175
+ NULL);
176
+
177
+ if (pipeHandle != INVALID_HANDLE_VALUE) {
178
+ /* No name collisions. We're done. */
179
+ break;
180
+ }
181
+
182
+ errorno = GetLastError();
183
+ if (errorno != ERROR_PIPE_BUSY && errorno != ERROR_ACCESS_DENIED) {
184
+ uv__set_sys_error(loop, errorno);
185
+ err = -1;
186
+ goto done;
187
+ }
188
+
189
+ /* Pipe name collision. Increment the pointer and try again. */
190
+ ptr++;
191
+ }
192
+
193
+ if (CreateIoCompletionPort(pipeHandle,
194
+ loop->iocp,
195
+ (ULONG_PTR)handle,
196
+ 0) == NULL) {
197
+ uv__set_sys_error(loop, GetLastError());
198
+ err = -1;
199
+ goto done;
200
+ }
201
+
202
+ uv_pipe_connection_init(handle);
203
+ handle->handle = pipeHandle;
204
+ err = 0;
205
+
206
+ done:
207
+ if (err && pipeHandle != INVALID_HANDLE_VALUE) {
208
+ CloseHandle(pipeHandle);
209
+ }
210
+
211
+ return err;
212
+ }
213
+
214
+
215
+ static int uv_set_pipe_handle(uv_loop_t* loop, uv_pipe_t* handle,
216
+ HANDLE pipeHandle, DWORD duplex_flags) {
217
+ NTSTATUS nt_status;
218
+ IO_STATUS_BLOCK io_status;
219
+ FILE_MODE_INFORMATION mode_info;
220
+ DWORD mode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT;
221
+
222
+ if (!SetNamedPipeHandleState(pipeHandle, &mode, NULL, NULL)) {
223
+ /* If this returns ERROR_INVALID_PARAMETER we probably opened something */
224
+ /* that is not a pipe. */
225
+ if (GetLastError() == ERROR_INVALID_PARAMETER) {
226
+ SetLastError(WSAENOTSOCK);
227
+ }
228
+ return -1;
229
+ }
230
+
231
+ /* Check if the pipe was created with FILE_FLAG_OVERLAPPED. */
232
+ nt_status = pNtQueryInformationFile(pipeHandle,
233
+ &io_status,
234
+ &mode_info,
235
+ sizeof(mode_info),
236
+ FileModeInformation);
237
+ if (nt_status != STATUS_SUCCESS) {
238
+ return -1;
239
+ }
240
+
241
+ if (mode_info.Mode & FILE_SYNCHRONOUS_IO_ALERT ||
242
+ mode_info.Mode & FILE_SYNCHRONOUS_IO_NONALERT) {
243
+ /* Non-overlapped pipe. */
244
+ handle->flags |= UV_HANDLE_NON_OVERLAPPED_PIPE;
245
+ } else {
246
+ /* Overlapped pipe. Try to associate with IOCP. */
247
+ if (CreateIoCompletionPort(pipeHandle,
248
+ loop->iocp,
249
+ (ULONG_PTR)handle,
250
+ 0) == NULL) {
251
+ handle->flags |= UV_HANDLE_EMULATE_IOCP;
252
+ }
253
+ }
254
+
255
+ handle->handle = pipeHandle;
256
+ handle->flags |= duplex_flags;
257
+
258
+ return 0;
259
+ }
260
+
261
+
262
+ static DWORD WINAPI pipe_shutdown_thread_proc(void* parameter) {
263
+ uv_loop_t* loop;
264
+ uv_pipe_t* handle;
265
+ uv_shutdown_t* req;
266
+
267
+ req = (uv_shutdown_t*) parameter;
268
+ assert(req);
269
+ handle = (uv_pipe_t*) req->handle;
270
+ assert(handle);
271
+ loop = handle->loop;
272
+ assert(loop);
273
+
274
+ FlushFileBuffers(handle->handle);
275
+
276
+ /* Post completed */
277
+ POST_COMPLETION_FOR_REQ(loop, req);
278
+
279
+ return 0;
280
+ }
281
+
282
+
283
+ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
284
+ DWORD result;
285
+ uv_shutdown_t* req;
286
+ NTSTATUS nt_status;
287
+ IO_STATUS_BLOCK io_status;
288
+ FILE_PIPE_LOCAL_INFORMATION pipe_info;
289
+
290
+ if ((handle->flags & UV_HANDLE_CONNECTION) &&
291
+ handle->shutdown_req != NULL &&
292
+ handle->write_reqs_pending == 0) {
293
+ req = handle->shutdown_req;
294
+
295
+ /* Clear the shutdown_req field so we don't go here again. */
296
+ handle->shutdown_req = NULL;
297
+
298
+ if (handle->flags & UV_HANDLE_CLOSING) {
299
+ UNREGISTER_HANDLE_REQ(loop, handle, req);
300
+
301
+ /* Already closing. Cancel the shutdown. */
302
+ if (req->cb) {
303
+ uv__set_sys_error(loop, WSAEINTR);
304
+ req->cb(req, -1);
305
+ }
306
+
307
+ DECREASE_PENDING_REQ_COUNT(handle);
308
+ return;
309
+ }
310
+
311
+ /* Try to avoid flushing the pipe buffer in the thread pool. */
312
+ nt_status = pNtQueryInformationFile(handle->handle,
313
+ &io_status,
314
+ &pipe_info,
315
+ sizeof pipe_info,
316
+ FilePipeLocalInformation);
317
+
318
+ if (nt_status != STATUS_SUCCESS) {
319
+ /* Failure */
320
+ UNREGISTER_HANDLE_REQ(loop, handle, req);
321
+
322
+ handle->flags &= ~UV_HANDLE_SHUTTING;
323
+ if (req->cb) {
324
+ uv__set_sys_error(loop, pRtlNtStatusToDosError(nt_status));
325
+ req->cb(req, -1);
326
+ }
327
+
328
+ DECREASE_PENDING_REQ_COUNT(handle);
329
+ return;
330
+ }
331
+
332
+ if (pipe_info.OutboundQuota == pipe_info.WriteQuotaAvailable) {
333
+ /* Short-circuit, no need to call FlushFileBuffers. */
334
+ uv_insert_pending_req(loop, (uv_req_t*) req);
335
+ return;
336
+ }
337
+
338
+ /* Run FlushFileBuffers in the thread pool. */
339
+ result = QueueUserWorkItem(pipe_shutdown_thread_proc,
340
+ req,
341
+ WT_EXECUTELONGFUNCTION);
342
+ if (result) {
343
+ return;
344
+
345
+ } else {
346
+ /* Failure. */
347
+ UNREGISTER_HANDLE_REQ(loop, handle, req);
348
+
349
+ handle->flags &= ~UV_HANDLE_SHUTTING;
350
+ if (req->cb) {
351
+ uv__set_sys_error(loop, GetLastError());
352
+ req->cb(req, -1);
353
+ }
354
+
355
+ DECREASE_PENDING_REQ_COUNT(handle);
356
+ return;
357
+ }
358
+ }
359
+
360
+ if (handle->flags & UV_HANDLE_CLOSING &&
361
+ handle->reqs_pending == 0) {
362
+ assert(!(handle->flags & UV_HANDLE_CLOSED));
363
+ uv__handle_stop(handle);
364
+
365
+ if (handle->flags & UV_HANDLE_CONNECTION) {
366
+ if (handle->pending_ipc_info.socket_info) {
367
+ free(handle->pending_ipc_info.socket_info);
368
+ handle->pending_ipc_info.socket_info = NULL;
369
+ }
370
+
371
+ if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
372
+ if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) {
373
+ UnregisterWait(handle->read_req.wait_handle);
374
+ handle->read_req.wait_handle = INVALID_HANDLE_VALUE;
375
+ }
376
+ if (handle->read_req.event_handle) {
377
+ CloseHandle(handle->read_req.event_handle);
378
+ handle->read_req.event_handle = NULL;
379
+ }
380
+ }
381
+ }
382
+
383
+ if (handle->flags & UV_HANDLE_PIPESERVER) {
384
+ assert(handle->accept_reqs);
385
+ free(handle->accept_reqs);
386
+ handle->accept_reqs = NULL;
387
+ }
388
+
389
+ uv__handle_close(handle);
390
+ }
391
+ }
392
+
393
+
394
+ void uv_pipe_pending_instances(uv_pipe_t* handle, int count) {
395
+ handle->pending_instances = count;
396
+ handle->flags |= UV_HANDLE_PIPESERVER;
397
+ }
398
+
399
+
400
+ /* Creates a pipe server. */
401
+ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
402
+ uv_loop_t* loop = handle->loop;
403
+ int i, errorno, nameSize;
404
+ uv_pipe_accept_t* req;
405
+
406
+ if (handle->flags & UV_HANDLE_BOUND) {
407
+ uv__set_sys_error(loop, WSAEINVAL);
408
+ return -1;
409
+ }
410
+
411
+ if (!name) {
412
+ uv__set_sys_error(loop, WSAEINVAL);
413
+ return -1;
414
+ }
415
+
416
+ if (!(handle->flags & UV_HANDLE_PIPESERVER)) {
417
+ handle->pending_instances = default_pending_pipe_instances;
418
+ }
419
+
420
+ handle->accept_reqs = (uv_pipe_accept_t*)
421
+ malloc(sizeof(uv_pipe_accept_t) * handle->pending_instances);
422
+ if (!handle->accept_reqs) {
423
+ uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
424
+ }
425
+
426
+ for (i = 0; i < handle->pending_instances; i++) {
427
+ req = &handle->accept_reqs[i];
428
+ uv_req_init(loop, (uv_req_t*) req);
429
+ req->type = UV_ACCEPT;
430
+ req->data = handle;
431
+ req->pipeHandle = INVALID_HANDLE_VALUE;
432
+ req->next_pending = NULL;
433
+ }
434
+
435
+ /* Convert name to UTF16. */
436
+ nameSize = uv_utf8_to_utf16(name, NULL, 0) * sizeof(wchar_t);
437
+ handle->name = (wchar_t*)malloc(nameSize);
438
+ if (!handle->name) {
439
+ uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
440
+ }
441
+
442
+ if (!uv_utf8_to_utf16(name, handle->name, nameSize / sizeof(wchar_t))) {
443
+ uv__set_sys_error(loop, GetLastError());
444
+ return -1;
445
+ }
446
+
447
+ /*
448
+ * Attempt to create the first pipe with FILE_FLAG_FIRST_PIPE_INSTANCE.
449
+ * If this fails then there's already a pipe server for the given pipe name.
450
+ */
451
+ handle->accept_reqs[0].pipeHandle = CreateNamedPipeW(handle->name,
452
+ PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED |
453
+ FILE_FLAG_FIRST_PIPE_INSTANCE,
454
+ PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
455
+ PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL);
456
+
457
+ if (handle->accept_reqs[0].pipeHandle == INVALID_HANDLE_VALUE) {
458
+ errorno = GetLastError();
459
+ if (errorno == ERROR_ACCESS_DENIED) {
460
+ uv__set_error(loop, UV_EADDRINUSE, errorno);
461
+ } else if (errorno == ERROR_PATH_NOT_FOUND || errorno == ERROR_INVALID_NAME) {
462
+ uv__set_error(loop, UV_EACCES, errorno);
463
+ } else {
464
+ uv__set_sys_error(loop, errorno);
465
+ }
466
+ goto error;
467
+ }
468
+
469
+ if (uv_set_pipe_handle(loop, handle, handle->accept_reqs[0].pipeHandle, 0)) {
470
+ uv__set_sys_error(loop, GetLastError());
471
+ goto error;
472
+ }
473
+
474
+ handle->pending_accepts = NULL;
475
+ handle->flags |= UV_HANDLE_PIPESERVER;
476
+ handle->flags |= UV_HANDLE_BOUND;
477
+
478
+ return 0;
479
+
480
+ error:
481
+ if (handle->name) {
482
+ free(handle->name);
483
+ handle->name = NULL;
484
+ }
485
+
486
+ if (handle->accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE) {
487
+ CloseHandle(handle->accept_reqs[0].pipeHandle);
488
+ handle->accept_reqs[0].pipeHandle = INVALID_HANDLE_VALUE;
489
+ }
490
+
491
+ return -1;
492
+ }
493
+
494
+
495
+ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) {
496
+ uv_loop_t* loop;
497
+ uv_pipe_t* handle;
498
+ uv_connect_t* req;
499
+ HANDLE pipeHandle = INVALID_HANDLE_VALUE;
500
+ DWORD duplex_flags;
501
+
502
+ req = (uv_connect_t*) parameter;
503
+ assert(req);
504
+ handle = (uv_pipe_t*) req->handle;
505
+ assert(handle);
506
+ loop = handle->loop;
507
+ assert(loop);
508
+
509
+ /* We're here because CreateFile on a pipe returned ERROR_PIPE_BUSY. */
510
+ /* We wait for the pipe to become available with WaitNamedPipe. */
511
+ while (WaitNamedPipeW(handle->name, 30000)) {
512
+ /* The pipe is now available, try to connect. */
513
+ pipeHandle = open_named_pipe(handle->name, &duplex_flags);
514
+ if (pipeHandle != INVALID_HANDLE_VALUE) {
515
+ break;
516
+ }
517
+
518
+ SwitchToThread();
519
+ }
520
+
521
+ if (pipeHandle != INVALID_HANDLE_VALUE &&
522
+ !uv_set_pipe_handle(loop, handle, pipeHandle, duplex_flags)) {
523
+ SET_REQ_SUCCESS(req);
524
+ } else {
525
+ SET_REQ_ERROR(req, GetLastError());
526
+ }
527
+
528
+ /* Post completed */
529
+ POST_COMPLETION_FOR_REQ(loop, req);
530
+
531
+ return 0;
532
+ }
533
+
534
+
535
+ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
536
+ const char* name, uv_connect_cb cb) {
537
+ uv_loop_t* loop = handle->loop;
538
+ int errorno, nameSize;
539
+ HANDLE pipeHandle = INVALID_HANDLE_VALUE;
540
+ DWORD duplex_flags;
541
+
542
+ uv_req_init(loop, (uv_req_t*) req);
543
+ req->type = UV_CONNECT;
544
+ req->handle = (uv_stream_t*) handle;
545
+ req->cb = cb;
546
+
547
+ /* Convert name to UTF16. */
548
+ nameSize = uv_utf8_to_utf16(name, NULL, 0) * sizeof(wchar_t);
549
+ handle->name = (wchar_t*)malloc(nameSize);
550
+ if (!handle->name) {
551
+ uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
552
+ }
553
+
554
+ if (!uv_utf8_to_utf16(name, handle->name, nameSize / sizeof(wchar_t))) {
555
+ errorno = GetLastError();
556
+ goto error;
557
+ }
558
+
559
+ pipeHandle = open_named_pipe(handle->name, &duplex_flags);
560
+ if (pipeHandle == INVALID_HANDLE_VALUE) {
561
+ if (GetLastError() == ERROR_PIPE_BUSY) {
562
+ /* Wait for the server to make a pipe instance available. */
563
+ if (!QueueUserWorkItem(&pipe_connect_thread_proc,
564
+ req,
565
+ WT_EXECUTELONGFUNCTION)) {
566
+ errorno = GetLastError();
567
+ goto error;
568
+ }
569
+
570
+ REGISTER_HANDLE_REQ(loop, handle, req);
571
+ handle->reqs_pending++;
572
+
573
+ return;
574
+ }
575
+
576
+ errorno = GetLastError();
577
+ goto error;
578
+ }
579
+
580
+ assert(pipeHandle != INVALID_HANDLE_VALUE);
581
+
582
+ if (uv_set_pipe_handle(loop,
583
+ (uv_pipe_t*) req->handle,
584
+ pipeHandle,
585
+ duplex_flags)) {
586
+ errorno = GetLastError();
587
+ goto error;
588
+ }
589
+
590
+ SET_REQ_SUCCESS(req);
591
+ uv_insert_pending_req(loop, (uv_req_t*) req);
592
+ handle->reqs_pending++;
593
+ REGISTER_HANDLE_REQ(loop, handle, req);
594
+ return;
595
+
596
+ error:
597
+ if (handle->name) {
598
+ free(handle->name);
599
+ handle->name = NULL;
600
+ }
601
+
602
+ if (pipeHandle != INVALID_HANDLE_VALUE) {
603
+ CloseHandle(pipeHandle);
604
+ }
605
+
606
+ /* Make this req pending reporting an error. */
607
+ SET_REQ_ERROR(req, errorno);
608
+ uv_insert_pending_req(loop, (uv_req_t*) req);
609
+ handle->reqs_pending++;
610
+ REGISTER_HANDLE_REQ(loop, handle, req);
611
+ return;
612
+ }
613
+
614
+
615
+ /* Cleans up uv_pipe_t (server or connection) and all resources associated */
616
+ /* with it. */
617
+ void uv_pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle) {
618
+ int i;
619
+ HANDLE pipeHandle;
620
+
621
+ if (handle->name) {
622
+ free(handle->name);
623
+ handle->name = NULL;
624
+ }
625
+
626
+ if (handle->flags & UV_HANDLE_PIPESERVER) {
627
+ for (i = 0; i < handle->pending_instances; i++) {
628
+ pipeHandle = handle->accept_reqs[i].pipeHandle;
629
+ if (pipeHandle != INVALID_HANDLE_VALUE) {
630
+ CloseHandle(pipeHandle);
631
+ handle->accept_reqs[i].pipeHandle = INVALID_HANDLE_VALUE;
632
+ }
633
+ }
634
+ }
635
+
636
+ if (handle->flags & UV_HANDLE_CONNECTION) {
637
+ handle->flags |= UV_HANDLE_SHUTTING;
638
+ eof_timer_destroy(handle);
639
+ }
640
+
641
+ if ((handle->flags & UV_HANDLE_CONNECTION)
642
+ && handle->handle != INVALID_HANDLE_VALUE) {
643
+ CloseHandle(handle->handle);
644
+ handle->handle = INVALID_HANDLE_VALUE;
645
+ }
646
+ }
647
+
648
+
649
+ void uv_pipe_close(uv_loop_t* loop, uv_pipe_t* handle) {
650
+ if (handle->flags & UV_HANDLE_READING) {
651
+ handle->flags &= ~UV_HANDLE_READING;
652
+ DECREASE_ACTIVE_COUNT(loop, handle);
653
+ }
654
+
655
+ if (handle->flags & UV_HANDLE_LISTENING) {
656
+ handle->flags &= ~UV_HANDLE_LISTENING;
657
+ DECREASE_ACTIVE_COUNT(loop, handle);
658
+ }
659
+
660
+ uv_pipe_cleanup(loop, handle);
661
+
662
+ if (handle->reqs_pending == 0) {
663
+ uv_want_endgame(loop, (uv_handle_t*) handle);
664
+ }
665
+
666
+ uv__handle_start(handle);
667
+ }
668
+
669
+
670
+ static void uv_pipe_queue_accept(uv_loop_t* loop, uv_pipe_t* handle,
671
+ uv_pipe_accept_t* req, BOOL firstInstance) {
672
+ assert(handle->flags & UV_HANDLE_LISTENING);
673
+
674
+ if (!firstInstance) {
675
+ assert(req->pipeHandle == INVALID_HANDLE_VALUE);
676
+
677
+ req->pipeHandle = CreateNamedPipeW(handle->name,
678
+ PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
679
+ PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
680
+ PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL);
681
+
682
+ if (req->pipeHandle == INVALID_HANDLE_VALUE) {
683
+ SET_REQ_ERROR(req, GetLastError());
684
+ uv_insert_pending_req(loop, (uv_req_t*) req);
685
+ handle->reqs_pending++;
686
+ return;
687
+ }
688
+
689
+ if (uv_set_pipe_handle(loop, handle, req->pipeHandle, 0)) {
690
+ CloseHandle(req->pipeHandle);
691
+ req->pipeHandle = INVALID_HANDLE_VALUE;
692
+ SET_REQ_ERROR(req, GetLastError());
693
+ uv_insert_pending_req(loop, (uv_req_t*) req);
694
+ handle->reqs_pending++;
695
+ return;
696
+ }
697
+ }
698
+
699
+ assert(req->pipeHandle != INVALID_HANDLE_VALUE);
700
+
701
+ /* Prepare the overlapped structure. */
702
+ memset(&(req->overlapped), 0, sizeof(req->overlapped));
703
+
704
+ if (!ConnectNamedPipe(req->pipeHandle, &req->overlapped) &&
705
+ GetLastError() != ERROR_IO_PENDING) {
706
+ if (GetLastError() == ERROR_PIPE_CONNECTED) {
707
+ SET_REQ_SUCCESS(req);
708
+ } else {
709
+ CloseHandle(req->pipeHandle);
710
+ req->pipeHandle = INVALID_HANDLE_VALUE;
711
+ /* Make this req pending reporting an error. */
712
+ SET_REQ_ERROR(req, GetLastError());
713
+ }
714
+ uv_insert_pending_req(loop, (uv_req_t*) req);
715
+ handle->reqs_pending++;
716
+ return;
717
+ }
718
+
719
+ handle->reqs_pending++;
720
+ }
721
+
722
+
723
+ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) {
724
+ uv_loop_t* loop = server->loop;
725
+ uv_pipe_t* pipe_client;
726
+ uv_pipe_accept_t* req;
727
+
728
+ if (server->ipc) {
729
+ if (!server->pending_ipc_info.socket_info) {
730
+ /* No valid pending sockets. */
731
+ uv__set_sys_error(loop, WSAEWOULDBLOCK);
732
+ return -1;
733
+ }
734
+
735
+ return uv_tcp_import((uv_tcp_t*)client, server->pending_ipc_info.socket_info,
736
+ server->pending_ipc_info.tcp_connection);
737
+ } else {
738
+ pipe_client = (uv_pipe_t*)client;
739
+
740
+ /* Find a connection instance that has been connected, but not yet */
741
+ /* accepted. */
742
+ req = server->pending_accepts;
743
+
744
+ if (!req) {
745
+ /* No valid connections found, so we error out. */
746
+ uv__set_sys_error(loop, WSAEWOULDBLOCK);
747
+ return -1;
748
+ }
749
+
750
+ /* Initialize the client handle and copy the pipeHandle to the client */
751
+ uv_pipe_connection_init(pipe_client);
752
+ pipe_client->handle = req->pipeHandle;
753
+
754
+ /* Prepare the req to pick up a new connection */
755
+ server->pending_accepts = req->next_pending;
756
+ req->next_pending = NULL;
757
+ req->pipeHandle = INVALID_HANDLE_VALUE;
758
+
759
+ if (!(server->flags & UV_HANDLE_CLOSING)) {
760
+ uv_pipe_queue_accept(loop, server, req, FALSE);
761
+ }
762
+ }
763
+
764
+ return 0;
765
+ }
766
+
767
+
768
+ /* Starts listening for connections for the given pipe. */
769
+ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
770
+ uv_loop_t* loop = handle->loop;
771
+ int i;
772
+
773
+ if (handle->flags & UV_HANDLE_LISTENING) {
774
+ handle->connection_cb = cb;
775
+ }
776
+
777
+ if (!(handle->flags & UV_HANDLE_BOUND)) {
778
+ uv__set_artificial_error(loop, UV_EINVAL);
779
+ return -1;
780
+ }
781
+
782
+ if (handle->flags & UV_HANDLE_READING) {
783
+ uv__set_artificial_error(loop, UV_EISCONN);
784
+ return -1;
785
+ }
786
+
787
+ if (!(handle->flags & UV_HANDLE_PIPESERVER)) {
788
+ uv__set_artificial_error(loop, UV_ENOTSUP);
789
+ return -1;
790
+ }
791
+
792
+ handle->flags |= UV_HANDLE_LISTENING;
793
+ INCREASE_ACTIVE_COUNT(loop, handle);
794
+ handle->connection_cb = cb;
795
+
796
+ /* First pipe handle should have already been created in uv_pipe_bind */
797
+ assert(handle->accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE);
798
+
799
+ for (i = 0; i < handle->pending_instances; i++) {
800
+ uv_pipe_queue_accept(loop, handle, &handle->accept_reqs[i], i == 0);
801
+ }
802
+
803
+ return 0;
804
+ }
805
+
806
+
807
+ static DWORD WINAPI uv_pipe_zero_readfile_thread_proc(void* parameter) {
808
+ int result;
809
+ DWORD bytes;
810
+ uv_read_t* req = (uv_read_t*) parameter;
811
+ uv_pipe_t* handle = (uv_pipe_t*) req->data;
812
+ uv_loop_t* loop = handle->loop;
813
+
814
+ assert(req != NULL);
815
+ assert(req->type == UV_READ);
816
+ assert(handle->type == UV_NAMED_PIPE);
817
+
818
+ result = ReadFile(handle->handle,
819
+ &uv_zero_,
820
+ 0,
821
+ &bytes,
822
+ NULL);
823
+
824
+ if (!result) {
825
+ SET_REQ_ERROR(req, GetLastError());
826
+ }
827
+
828
+ POST_COMPLETION_FOR_REQ(loop, req);
829
+ return 0;
830
+ }
831
+
832
+
833
+ static DWORD WINAPI uv_pipe_writefile_thread_proc(void* parameter) {
834
+ int result;
835
+ DWORD bytes;
836
+ uv_write_t* req = (uv_write_t*) parameter;
837
+ uv_pipe_t* handle = (uv_pipe_t*) req->handle;
838
+ uv_loop_t* loop = handle->loop;
839
+
840
+ assert(req != NULL);
841
+ assert(req->type == UV_WRITE);
842
+ assert(handle->type == UV_NAMED_PIPE);
843
+ assert(req->write_buffer.base);
844
+
845
+ result = WriteFile(handle->handle,
846
+ req->write_buffer.base,
847
+ req->write_buffer.len,
848
+ &bytes,
849
+ NULL);
850
+
851
+ if (!result) {
852
+ SET_REQ_ERROR(req, GetLastError());
853
+ }
854
+
855
+ POST_COMPLETION_FOR_REQ(loop, req);
856
+ return 0;
857
+ }
858
+
859
+
860
+ static void CALLBACK post_completion_read_wait(void* context, BOOLEAN timed_out) {
861
+ uv_read_t* req;
862
+ uv_tcp_t* handle;
863
+
864
+ req = (uv_read_t*) context;
865
+ assert(req != NULL);
866
+ handle = (uv_tcp_t*)req->data;
867
+ assert(handle != NULL);
868
+ assert(!timed_out);
869
+
870
+ if (!PostQueuedCompletionStatus(handle->loop->iocp,
871
+ req->overlapped.InternalHigh,
872
+ 0,
873
+ &req->overlapped)) {
874
+ uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");
875
+ }
876
+ }
877
+
878
+
879
+ static void CALLBACK post_completion_write_wait(void* context, BOOLEAN timed_out) {
880
+ uv_write_t* req;
881
+ uv_tcp_t* handle;
882
+
883
+ req = (uv_write_t*) context;
884
+ assert(req != NULL);
885
+ handle = (uv_tcp_t*)req->handle;
886
+ assert(handle != NULL);
887
+ assert(!timed_out);
888
+
889
+ if (!PostQueuedCompletionStatus(handle->loop->iocp,
890
+ req->overlapped.InternalHigh,
891
+ 0,
892
+ &req->overlapped)) {
893
+ uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");
894
+ }
895
+ }
896
+
897
+
898
+ static void uv_pipe_queue_read(uv_loop_t* loop, uv_pipe_t* handle) {
899
+ uv_read_t* req;
900
+ int result;
901
+
902
+ assert(handle->flags & UV_HANDLE_READING);
903
+ assert(!(handle->flags & UV_HANDLE_READ_PENDING));
904
+
905
+ assert(handle->handle != INVALID_HANDLE_VALUE);
906
+
907
+ req = &handle->read_req;
908
+
909
+ if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
910
+ if (!QueueUserWorkItem(&uv_pipe_zero_readfile_thread_proc,
911
+ req,
912
+ WT_EXECUTELONGFUNCTION)) {
913
+ /* Make this req pending reporting an error. */
914
+ SET_REQ_ERROR(req, GetLastError());
915
+ goto error;
916
+ }
917
+ } else {
918
+ memset(&req->overlapped, 0, sizeof(req->overlapped));
919
+ if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
920
+ req->overlapped.hEvent = (HANDLE) ((DWORD) req->event_handle | 1);
921
+ }
922
+
923
+ /* Do 0-read */
924
+ result = ReadFile(handle->handle,
925
+ &uv_zero_,
926
+ 0,
927
+ NULL,
928
+ &req->overlapped);
929
+
930
+ if (!result && GetLastError() != ERROR_IO_PENDING) {
931
+ /* Make this req pending reporting an error. */
932
+ SET_REQ_ERROR(req, GetLastError());
933
+ goto error;
934
+ }
935
+
936
+ if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
937
+ if (!req->event_handle) {
938
+ req->event_handle = CreateEvent(NULL, 0, 0, NULL);
939
+ if (!req->event_handle) {
940
+ uv_fatal_error(GetLastError(), "CreateEvent");
941
+ }
942
+ }
943
+ if (req->wait_handle == INVALID_HANDLE_VALUE) {
944
+ if (!RegisterWaitForSingleObject(&req->wait_handle,
945
+ req->overlapped.hEvent, post_completion_read_wait, (void*) req,
946
+ INFINITE, WT_EXECUTEINWAITTHREAD)) {
947
+ SET_REQ_ERROR(req, GetLastError());
948
+ goto error;
949
+ }
950
+ }
951
+ }
952
+ }
953
+
954
+ /* Start the eof timer if there is one */
955
+ eof_timer_start(handle);
956
+ handle->flags |= UV_HANDLE_READ_PENDING;
957
+ handle->reqs_pending++;
958
+ return;
959
+
960
+ error:
961
+ uv_insert_pending_req(loop, (uv_req_t*)req);
962
+ handle->flags |= UV_HANDLE_READ_PENDING;
963
+ handle->reqs_pending++;
964
+ }
965
+
966
+
967
+ static int uv_pipe_read_start_impl(uv_pipe_t* handle, uv_alloc_cb alloc_cb,
968
+ uv_read_cb read_cb, uv_read2_cb read2_cb) {
969
+ uv_loop_t* loop = handle->loop;
970
+
971
+ if (!(handle->flags & UV_HANDLE_CONNECTION)) {
972
+ uv__set_artificial_error(loop, UV_EINVAL);
973
+ return -1;
974
+ }
975
+
976
+ if (handle->flags & UV_HANDLE_EOF) {
977
+ uv__set_artificial_error(loop, UV_EOF);
978
+ return -1;
979
+ }
980
+
981
+ handle->flags |= UV_HANDLE_READING;
982
+ INCREASE_ACTIVE_COUNT(loop, handle);
983
+ handle->read_cb = read_cb;
984
+ handle->read2_cb = read2_cb;
985
+ handle->alloc_cb = alloc_cb;
986
+
987
+ /* If reading was stopped and then started again, there could still be a */
988
+ /* read request pending. */
989
+ if (!(handle->flags & UV_HANDLE_READ_PENDING))
990
+ uv_pipe_queue_read(loop, handle);
991
+
992
+ return 0;
993
+ }
994
+
995
+
996
+ int uv_pipe_read_start(uv_pipe_t* handle, uv_alloc_cb alloc_cb,
997
+ uv_read_cb read_cb) {
998
+ return uv_pipe_read_start_impl(handle, alloc_cb, read_cb, NULL);
999
+ }
1000
+
1001
+
1002
+ int uv_pipe_read2_start(uv_pipe_t* handle, uv_alloc_cb alloc_cb,
1003
+ uv_read2_cb read_cb) {
1004
+ return uv_pipe_read_start_impl(handle, alloc_cb, NULL, read_cb);
1005
+ }
1006
+
1007
+
1008
+ static void uv_insert_non_overlapped_write_req(uv_pipe_t* handle,
1009
+ uv_write_t* req) {
1010
+ req->next_req = NULL;
1011
+ if (handle->non_overlapped_writes_tail) {
1012
+ req->next_req =
1013
+ handle->non_overlapped_writes_tail->next_req;
1014
+ handle->non_overlapped_writes_tail->next_req = (uv_req_t*)req;
1015
+ handle->non_overlapped_writes_tail = req;
1016
+ } else {
1017
+ req->next_req = (uv_req_t*)req;
1018
+ handle->non_overlapped_writes_tail = req;
1019
+ }
1020
+ }
1021
+
1022
+
1023
+ static uv_write_t* uv_remove_non_overlapped_write_req(uv_pipe_t* handle) {
1024
+ uv_write_t* req;
1025
+
1026
+ if (handle->non_overlapped_writes_tail) {
1027
+ req = (uv_write_t*)handle->non_overlapped_writes_tail->next_req;
1028
+
1029
+ if (req == handle->non_overlapped_writes_tail) {
1030
+ handle->non_overlapped_writes_tail = NULL;
1031
+ } else {
1032
+ handle->non_overlapped_writes_tail->next_req =
1033
+ req->next_req;
1034
+ }
1035
+
1036
+ return req;
1037
+ } else {
1038
+ /* queue empty */
1039
+ return NULL;
1040
+ }
1041
+ }
1042
+
1043
+
1044
+ static void uv_queue_non_overlapped_write(uv_pipe_t* handle) {
1045
+ uv_write_t* req = uv_remove_non_overlapped_write_req(handle);
1046
+ if (req) {
1047
+ if (!QueueUserWorkItem(&uv_pipe_writefile_thread_proc,
1048
+ req,
1049
+ WT_EXECUTELONGFUNCTION)) {
1050
+ uv_fatal_error(GetLastError(), "QueueUserWorkItem");
1051
+ }
1052
+ }
1053
+ }
1054
+
1055
+
1056
+ static int uv_pipe_write_impl(uv_loop_t* loop, uv_write_t* req,
1057
+ uv_pipe_t* handle, uv_buf_t bufs[], int bufcnt,
1058
+ uv_stream_t* send_handle, uv_write_cb cb) {
1059
+ int result;
1060
+ uv_tcp_t* tcp_send_handle;
1061
+ uv_write_t* ipc_header_req;
1062
+ uv_ipc_frame_uv_stream ipc_frame;
1063
+
1064
+ if (bufcnt != 1 && (bufcnt != 0 || !send_handle)) {
1065
+ uv__set_artificial_error(loop, UV_ENOTSUP);
1066
+ return -1;
1067
+ }
1068
+
1069
+ /* Only TCP handles are supported for sharing. */
1070
+ if (send_handle && ((send_handle->type != UV_TCP) ||
1071
+ (!(send_handle->flags & UV_HANDLE_BOUND) &&
1072
+ !(send_handle->flags & UV_HANDLE_CONNECTION)))) {
1073
+ uv__set_artificial_error(loop, UV_ENOTSUP);
1074
+ return -1;
1075
+ }
1076
+
1077
+ assert(handle->handle != INVALID_HANDLE_VALUE);
1078
+
1079
+ if (!(handle->flags & UV_HANDLE_CONNECTION)) {
1080
+ uv__set_artificial_error(loop, UV_EINVAL);
1081
+ return -1;
1082
+ }
1083
+
1084
+ if (handle->flags & UV_HANDLE_SHUTTING) {
1085
+ uv__set_artificial_error(loop, UV_EOF);
1086
+ return -1;
1087
+ }
1088
+
1089
+ uv_req_init(loop, (uv_req_t*) req);
1090
+ req->type = UV_WRITE;
1091
+ req->handle = (uv_stream_t*) handle;
1092
+ req->cb = cb;
1093
+ req->ipc_header = 0;
1094
+ req->event_handle = NULL;
1095
+ req->wait_handle = INVALID_HANDLE_VALUE;
1096
+ memset(&req->overlapped, 0, sizeof(req->overlapped));
1097
+
1098
+ if (handle->ipc) {
1099
+ assert(!(handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE));
1100
+ ipc_frame.header.flags = 0;
1101
+
1102
+ /* Use the IPC framing protocol. */
1103
+ if (send_handle) {
1104
+ tcp_send_handle = (uv_tcp_t*)send_handle;
1105
+
1106
+ if (uv_tcp_duplicate_socket(tcp_send_handle, handle->ipc_pid,
1107
+ &ipc_frame.socket_info)) {
1108
+ return -1;
1109
+ }
1110
+ ipc_frame.header.flags |= UV_IPC_TCP_SERVER;
1111
+
1112
+ if (tcp_send_handle->flags & UV_HANDLE_CONNECTION) {
1113
+ ipc_frame.header.flags |= UV_IPC_TCP_CONNECTION;
1114
+ }
1115
+ }
1116
+
1117
+ if (bufcnt == 1) {
1118
+ ipc_frame.header.flags |= UV_IPC_RAW_DATA;
1119
+ ipc_frame.header.raw_data_length = bufs[0].len;
1120
+ }
1121
+
1122
+ /*
1123
+ * Use the provided req if we're only doing a single write.
1124
+ * If we're doing multiple writes, use ipc_header_write_req to do
1125
+ * the first write, and then use the provided req for the second write.
1126
+ */
1127
+ if (!(ipc_frame.header.flags & UV_IPC_RAW_DATA)) {
1128
+ ipc_header_req = req;
1129
+ } else {
1130
+ /*
1131
+ * Try to use the preallocated write req if it's available.
1132
+ * Otherwise allocate a new one.
1133
+ */
1134
+ if (handle->ipc_header_write_req.type != UV_WRITE) {
1135
+ ipc_header_req = (uv_write_t*)&handle->ipc_header_write_req;
1136
+ } else {
1137
+ ipc_header_req = (uv_write_t*)malloc(sizeof(uv_write_t));
1138
+ if (!ipc_header_req) {
1139
+ uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
1140
+ }
1141
+ }
1142
+
1143
+ uv_req_init(loop, (uv_req_t*) ipc_header_req);
1144
+ ipc_header_req->type = UV_WRITE;
1145
+ ipc_header_req->handle = (uv_stream_t*) handle;
1146
+ ipc_header_req->cb = NULL;
1147
+ ipc_header_req->ipc_header = 1;
1148
+ }
1149
+
1150
+ /* Write the header or the whole frame. */
1151
+ memset(&ipc_header_req->overlapped, 0, sizeof(ipc_header_req->overlapped));
1152
+
1153
+ result = WriteFile(handle->handle,
1154
+ &ipc_frame,
1155
+ ipc_frame.header.flags & UV_IPC_TCP_SERVER ?
1156
+ sizeof(ipc_frame) : sizeof(ipc_frame.header),
1157
+ NULL,
1158
+ &ipc_header_req->overlapped);
1159
+ if (!result && GetLastError() != ERROR_IO_PENDING) {
1160
+ uv__set_sys_error(loop, GetLastError());
1161
+ return -1;
1162
+ }
1163
+
1164
+ if (result) {
1165
+ /* Request completed immediately. */
1166
+ ipc_header_req->queued_bytes = 0;
1167
+ } else {
1168
+ /* Request queued by the kernel. */
1169
+ ipc_header_req->queued_bytes = ipc_frame.header.flags & UV_IPC_TCP_SERVER ?
1170
+ sizeof(ipc_frame) : sizeof(ipc_frame.header);
1171
+ handle->write_queue_size += ipc_header_req->queued_bytes;
1172
+ }
1173
+
1174
+ REGISTER_HANDLE_REQ(loop, handle, ipc_header_req);
1175
+ handle->reqs_pending++;
1176
+ handle->write_reqs_pending++;
1177
+
1178
+ /* If we don't have any raw data to write - we're done. */
1179
+ if (!(ipc_frame.header.flags & UV_IPC_RAW_DATA)) {
1180
+ return 0;
1181
+ }
1182
+ }
1183
+
1184
+ if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
1185
+ req->write_buffer = bufs[0];
1186
+ uv_insert_non_overlapped_write_req(handle, req);
1187
+ if (handle->write_reqs_pending == 0) {
1188
+ uv_queue_non_overlapped_write(handle);
1189
+ }
1190
+
1191
+ /* Request queued by the kernel. */
1192
+ req->queued_bytes = uv_count_bufs(bufs, bufcnt);
1193
+ handle->write_queue_size += req->queued_bytes;
1194
+ } else {
1195
+ result = WriteFile(handle->handle,
1196
+ bufs[0].base,
1197
+ bufs[0].len,
1198
+ NULL,
1199
+ &req->overlapped);
1200
+
1201
+ if (!result && GetLastError() != ERROR_IO_PENDING) {
1202
+ uv__set_sys_error(loop, GetLastError());
1203
+ return -1;
1204
+ }
1205
+
1206
+ if (result) {
1207
+ /* Request completed immediately. */
1208
+ req->queued_bytes = 0;
1209
+ } else {
1210
+ /* Request queued by the kernel. */
1211
+ req->queued_bytes = uv_count_bufs(bufs, bufcnt);
1212
+ handle->write_queue_size += req->queued_bytes;
1213
+ }
1214
+
1215
+ if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
1216
+ req->event_handle = CreateEvent(NULL, 0, 0, NULL);
1217
+ if (!req->event_handle) {
1218
+ uv_fatal_error(GetLastError(), "CreateEvent");
1219
+ }
1220
+ if (!RegisterWaitForSingleObject(&req->wait_handle,
1221
+ req->overlapped.hEvent, post_completion_write_wait, (void*) req,
1222
+ INFINITE, WT_EXECUTEINWAITTHREAD)) {
1223
+ uv__set_sys_error(loop, GetLastError());
1224
+ return -1;
1225
+ }
1226
+ }
1227
+ }
1228
+
1229
+ REGISTER_HANDLE_REQ(loop, handle, req);
1230
+ handle->reqs_pending++;
1231
+ handle->write_reqs_pending++;
1232
+
1233
+ return 0;
1234
+ }
1235
+
1236
+
1237
+ int uv_pipe_write(uv_loop_t* loop, uv_write_t* req, uv_pipe_t* handle,
1238
+ uv_buf_t bufs[], int bufcnt, uv_write_cb cb) {
1239
+ return uv_pipe_write_impl(loop, req, handle, bufs, bufcnt, NULL, cb);
1240
+ }
1241
+
1242
+
1243
+ int uv_pipe_write2(uv_loop_t* loop, uv_write_t* req, uv_pipe_t* handle,
1244
+ uv_buf_t bufs[], int bufcnt, uv_stream_t* send_handle, uv_write_cb cb) {
1245
+ if (!handle->ipc) {
1246
+ uv__set_artificial_error(loop, UV_EINVAL);
1247
+ return -1;
1248
+ }
1249
+
1250
+ return uv_pipe_write_impl(loop, req, handle, bufs, bufcnt, send_handle, cb);
1251
+ }
1252
+
1253
+
1254
+ static void uv_pipe_read_eof(uv_loop_t* loop, uv_pipe_t* handle,
1255
+ uv_buf_t buf) {
1256
+ /* If there is an eof timer running, we don't need it any more, */
1257
+ /* so discard it. */
1258
+ eof_timer_destroy(handle);
1259
+
1260
+ handle->flags |= UV_HANDLE_EOF;
1261
+ uv_read_stop((uv_stream_t*) handle);
1262
+
1263
+ uv__set_artificial_error(loop, UV_EOF);
1264
+ if (handle->read2_cb) {
1265
+ handle->read2_cb(handle, -1, uv_null_buf_, UV_UNKNOWN_HANDLE);
1266
+ } else {
1267
+ handle->read_cb((uv_stream_t*) handle, -1, uv_null_buf_);
1268
+ }
1269
+ }
1270
+
1271
+
1272
+ static void uv_pipe_read_error(uv_loop_t* loop, uv_pipe_t* handle, int error,
1273
+ uv_buf_t buf) {
1274
+ /* If there is an eof timer running, we don't need it any more, */
1275
+ /* so discard it. */
1276
+ eof_timer_destroy(handle);
1277
+
1278
+ uv_read_stop((uv_stream_t*) handle);
1279
+
1280
+ uv__set_sys_error(loop, error);
1281
+ if (handle->read2_cb) {
1282
+ handle->read2_cb(handle, -1, buf, UV_UNKNOWN_HANDLE);
1283
+ } else {
1284
+ handle->read_cb((uv_stream_t*)handle, -1, buf);
1285
+ }
1286
+ }
1287
+
1288
+
1289
+ static void uv_pipe_read_error_or_eof(uv_loop_t* loop, uv_pipe_t* handle,
1290
+ int error, uv_buf_t buf) {
1291
+ if (error == ERROR_BROKEN_PIPE) {
1292
+ uv_pipe_read_eof(loop, handle, buf);
1293
+ } else {
1294
+ uv_pipe_read_error(loop, handle, error, buf);
1295
+ }
1296
+ }
1297
+
1298
+
1299
+ void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle,
1300
+ uv_req_t* req) {
1301
+ DWORD bytes, avail;
1302
+ uv_buf_t buf;
1303
+ uv_ipc_frame_uv_stream ipc_frame;
1304
+
1305
+ assert(handle->type == UV_NAMED_PIPE);
1306
+
1307
+ handle->flags &= ~UV_HANDLE_READ_PENDING;
1308
+ eof_timer_stop(handle);
1309
+
1310
+ if (!REQ_SUCCESS(req)) {
1311
+ /* An error occurred doing the 0-read. */
1312
+ if (handle->flags & UV_HANDLE_READING) {
1313
+ uv_pipe_read_error_or_eof(loop,
1314
+ handle,
1315
+ GET_REQ_ERROR(req),
1316
+ uv_null_buf_);
1317
+ }
1318
+ } else {
1319
+ /* Do non-blocking reads until the buffer is empty */
1320
+ while (handle->flags & UV_HANDLE_READING) {
1321
+ if (!PeekNamedPipe(handle->handle,
1322
+ NULL,
1323
+ 0,
1324
+ NULL,
1325
+ &avail,
1326
+ NULL)) {
1327
+ uv_pipe_read_error_or_eof(loop, handle, GetLastError(), uv_null_buf_);
1328
+ break;
1329
+ }
1330
+
1331
+ if (avail == 0) {
1332
+ /* There is nothing to read after all. */
1333
+ break;
1334
+ }
1335
+
1336
+ if (handle->ipc) {
1337
+ /* Use the IPC framing protocol to read the incoming data. */
1338
+ if (handle->remaining_ipc_rawdata_bytes == 0) {
1339
+ /* We're reading a new frame. First, read the header. */
1340
+ assert(avail >= sizeof(ipc_frame.header));
1341
+
1342
+ if (!ReadFile(handle->handle,
1343
+ &ipc_frame.header,
1344
+ sizeof(ipc_frame.header),
1345
+ &bytes,
1346
+ NULL)) {
1347
+ uv_pipe_read_error_or_eof(loop, handle, GetLastError(),
1348
+ uv_null_buf_);
1349
+ break;
1350
+ }
1351
+
1352
+ assert(bytes == sizeof(ipc_frame.header));
1353
+ assert(ipc_frame.header.flags <= (UV_IPC_TCP_SERVER | UV_IPC_RAW_DATA |
1354
+ UV_IPC_TCP_CONNECTION));
1355
+
1356
+ if (ipc_frame.header.flags & UV_IPC_TCP_SERVER) {
1357
+ assert(avail - sizeof(ipc_frame.header) >=
1358
+ sizeof(ipc_frame.socket_info));
1359
+
1360
+ /* Read the TCP socket info. */
1361
+ if (!ReadFile(handle->handle,
1362
+ &ipc_frame.socket_info,
1363
+ sizeof(ipc_frame) - sizeof(ipc_frame.header),
1364
+ &bytes,
1365
+ NULL)) {
1366
+ uv_pipe_read_error_or_eof(loop, handle, GetLastError(),
1367
+ uv_null_buf_);
1368
+ break;
1369
+ }
1370
+
1371
+ assert(bytes == sizeof(ipc_frame) - sizeof(ipc_frame.header));
1372
+
1373
+ /* Store the pending socket info. */
1374
+ assert(!handle->pending_ipc_info.socket_info);
1375
+ handle->pending_ipc_info.socket_info =
1376
+ (WSAPROTOCOL_INFOW*)malloc(sizeof(*(handle->pending_ipc_info.socket_info)));
1377
+ if (!handle->pending_ipc_info.socket_info) {
1378
+ uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
1379
+ }
1380
+
1381
+ *(handle->pending_ipc_info.socket_info) = ipc_frame.socket_info;
1382
+ handle->pending_ipc_info.tcp_connection =
1383
+ ipc_frame.header.flags & UV_IPC_TCP_CONNECTION;
1384
+ }
1385
+
1386
+ if (ipc_frame.header.flags & UV_IPC_RAW_DATA) {
1387
+ handle->remaining_ipc_rawdata_bytes =
1388
+ ipc_frame.header.raw_data_length;
1389
+ continue;
1390
+ }
1391
+ } else {
1392
+ avail = min(avail, (DWORD)handle->remaining_ipc_rawdata_bytes);
1393
+ }
1394
+ }
1395
+
1396
+ buf = handle->alloc_cb((uv_handle_t*) handle, avail);
1397
+ assert(buf.len > 0);
1398
+
1399
+ if (ReadFile(handle->handle,
1400
+ buf.base,
1401
+ buf.len,
1402
+ &bytes,
1403
+ NULL)) {
1404
+ /* Successful read */
1405
+ if (handle->ipc) {
1406
+ assert(handle->remaining_ipc_rawdata_bytes >= bytes);
1407
+ handle->remaining_ipc_rawdata_bytes =
1408
+ handle->remaining_ipc_rawdata_bytes - bytes;
1409
+ if (handle->read2_cb) {
1410
+ handle->read2_cb(handle, bytes, buf,
1411
+ handle->pending_ipc_info.socket_info ? UV_TCP : UV_UNKNOWN_HANDLE);
1412
+ } else if (handle->read_cb) {
1413
+ handle->read_cb((uv_stream_t*)handle, bytes, buf);
1414
+ }
1415
+
1416
+ if (handle->pending_ipc_info.socket_info) {
1417
+ free(handle->pending_ipc_info.socket_info);
1418
+ handle->pending_ipc_info.socket_info = NULL;
1419
+ }
1420
+ } else {
1421
+ handle->read_cb((uv_stream_t*)handle, bytes, buf);
1422
+ }
1423
+
1424
+ /* Read again only if bytes == buf.len */
1425
+ if (bytes <= buf.len) {
1426
+ break;
1427
+ }
1428
+ } else {
1429
+ uv_pipe_read_error_or_eof(loop, handle, GetLastError(), uv_null_buf_);
1430
+ break;
1431
+ }
1432
+ }
1433
+
1434
+ /* Post another 0-read if still reading and not closing. */
1435
+ if ((handle->flags & UV_HANDLE_READING) &&
1436
+ !(handle->flags & UV_HANDLE_READ_PENDING)) {
1437
+ uv_pipe_queue_read(loop, handle);
1438
+ }
1439
+ }
1440
+
1441
+ DECREASE_PENDING_REQ_COUNT(handle);
1442
+ }
1443
+
1444
+
1445
+ void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle,
1446
+ uv_write_t* req) {
1447
+ assert(handle->type == UV_NAMED_PIPE);
1448
+
1449
+ assert(handle->write_queue_size >= req->queued_bytes);
1450
+ handle->write_queue_size -= req->queued_bytes;
1451
+
1452
+ UNREGISTER_HANDLE_REQ(loop, handle, req);
1453
+
1454
+ if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
1455
+ if (req->wait_handle != INVALID_HANDLE_VALUE) {
1456
+ UnregisterWait(req->wait_handle);
1457
+ req->wait_handle = INVALID_HANDLE_VALUE;
1458
+ }
1459
+ if (req->event_handle) {
1460
+ CloseHandle(req->event_handle);
1461
+ req->event_handle = NULL;
1462
+ }
1463
+ }
1464
+
1465
+ if (req->ipc_header) {
1466
+ if (req == &handle->ipc_header_write_req) {
1467
+ req->type = UV_UNKNOWN_REQ;
1468
+ } else {
1469
+ free(req);
1470
+ }
1471
+ } else {
1472
+ if (req->cb) {
1473
+ if (!REQ_SUCCESS(req)) {
1474
+ uv__set_sys_error(loop, GET_REQ_ERROR(req));
1475
+ ((uv_write_cb)req->cb)(req, -1);
1476
+ } else {
1477
+ ((uv_write_cb)req->cb)(req, 0);
1478
+ }
1479
+ }
1480
+ }
1481
+
1482
+ handle->write_reqs_pending--;
1483
+
1484
+ if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE &&
1485
+ handle->non_overlapped_writes_tail) {
1486
+ assert(handle->write_reqs_pending > 0);
1487
+ uv_queue_non_overlapped_write(handle);
1488
+ }
1489
+
1490
+ if (handle->write_reqs_pending == 0 &&
1491
+ handle->flags & UV_HANDLE_SHUTTING) {
1492
+ uv_want_endgame(loop, (uv_handle_t*)handle);
1493
+ }
1494
+
1495
+ DECREASE_PENDING_REQ_COUNT(handle);
1496
+ }
1497
+
1498
+
1499
+ void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle,
1500
+ uv_req_t* raw_req) {
1501
+ uv_pipe_accept_t* req = (uv_pipe_accept_t*) raw_req;
1502
+
1503
+ assert(handle->type == UV_NAMED_PIPE);
1504
+
1505
+ if (REQ_SUCCESS(req)) {
1506
+ assert(req->pipeHandle != INVALID_HANDLE_VALUE);
1507
+ req->next_pending = handle->pending_accepts;
1508
+ handle->pending_accepts = req;
1509
+
1510
+ if (handle->connection_cb) {
1511
+ handle->connection_cb((uv_stream_t*)handle, 0);
1512
+ }
1513
+ } else {
1514
+ if (req->pipeHandle != INVALID_HANDLE_VALUE) {
1515
+ CloseHandle(req->pipeHandle);
1516
+ req->pipeHandle = INVALID_HANDLE_VALUE;
1517
+ }
1518
+ if (!(handle->flags & UV_HANDLE_CLOSING)) {
1519
+ uv_pipe_queue_accept(loop, handle, req, FALSE);
1520
+ }
1521
+ }
1522
+
1523
+ DECREASE_PENDING_REQ_COUNT(handle);
1524
+ }
1525
+
1526
+
1527
+ void uv_process_pipe_connect_req(uv_loop_t* loop, uv_pipe_t* handle,
1528
+ uv_connect_t* req) {
1529
+ assert(handle->type == UV_NAMED_PIPE);
1530
+
1531
+ UNREGISTER_HANDLE_REQ(loop, handle, req);
1532
+
1533
+ if (req->cb) {
1534
+ if (REQ_SUCCESS(req)) {
1535
+ uv_pipe_connection_init(handle);
1536
+ ((uv_connect_cb)req->cb)(req, 0);
1537
+ } else {
1538
+ uv__set_sys_error(loop, GET_REQ_ERROR(req));
1539
+ ((uv_connect_cb)req->cb)(req, -1);
1540
+ }
1541
+ }
1542
+
1543
+ DECREASE_PENDING_REQ_COUNT(handle);
1544
+ }
1545
+
1546
+
1547
+ void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle,
1548
+ uv_shutdown_t* req) {
1549
+ assert(handle->type == UV_NAMED_PIPE);
1550
+
1551
+ UNREGISTER_HANDLE_REQ(loop, handle, req);
1552
+
1553
+ /* Initialize and optionally start the eof timer. */
1554
+ /* This makes no sense if we've already seen EOF. */
1555
+ if (!(handle->flags & UV_HANDLE_EOF)) {
1556
+ eof_timer_init(handle);
1557
+
1558
+ /* If reading start the timer right now. */
1559
+ /* Otherwise uv_pipe_queue_read will start it. */
1560
+ if (handle->flags & UV_HANDLE_READ_PENDING) {
1561
+ eof_timer_start(handle);
1562
+ }
1563
+ }
1564
+
1565
+ if (req->cb) {
1566
+ req->cb(req, 0);
1567
+ }
1568
+
1569
+ DECREASE_PENDING_REQ_COUNT(handle);
1570
+ }
1571
+
1572
+
1573
+ static void eof_timer_init(uv_pipe_t* pipe) {
1574
+ int r;
1575
+
1576
+ assert(pipe->eof_timer == NULL);
1577
+ assert(pipe->flags & UV_HANDLE_CONNECTION);
1578
+
1579
+ pipe->eof_timer = (uv_timer_t*) malloc(sizeof *pipe->eof_timer);
1580
+
1581
+ r = uv_timer_init(pipe->loop, pipe->eof_timer);
1582
+ assert(r == 0); /* timers can't fail */
1583
+ pipe->eof_timer->data = pipe;
1584
+ uv_unref((uv_handle_t*) pipe->eof_timer);
1585
+ }
1586
+
1587
+
1588
+ static void eof_timer_start(uv_pipe_t* pipe) {
1589
+ assert(pipe->flags & UV_HANDLE_CONNECTION);
1590
+
1591
+ if (pipe->eof_timer != NULL) {
1592
+ uv_timer_start(pipe->eof_timer, eof_timer_cb, eof_timeout, 0);
1593
+ }
1594
+ }
1595
+
1596
+
1597
+ static void eof_timer_stop(uv_pipe_t* pipe) {
1598
+ assert(pipe->flags & UV_HANDLE_CONNECTION);
1599
+
1600
+ if (pipe->eof_timer != NULL) {
1601
+ uv_timer_stop(pipe->eof_timer);
1602
+ }
1603
+ }
1604
+
1605
+
1606
+ static void eof_timer_cb(uv_timer_t* timer, int status) {
1607
+ uv_pipe_t* pipe = (uv_pipe_t*) timer->data;
1608
+ uv_loop_t* loop = timer->loop;
1609
+
1610
+ assert(status == 0); /* timers can't fail */
1611
+ assert(pipe->type == UV_NAMED_PIPE);
1612
+
1613
+ /* This should always be true, since we start the timer only */
1614
+ /* in uv_pipe_queue_read after successfully calling ReadFile, */
1615
+ /* or in uv_process_pipe_shutdown_req if a read is pending, */
1616
+ /* and we always immediately stop the timer in */
1617
+ /* uv_process_pipe_read_req. */
1618
+ assert(pipe->flags & UV_HANDLE_READ_PENDING);
1619
+
1620
+ /* If there are many packets coming off the iocp then the timer callback */
1621
+ /* may be called before the read request is coming off the queue. */
1622
+ /* Therefore we check here if the read request has completed but will */
1623
+ /* be processed later. */
1624
+ if ((pipe->flags & UV_HANDLE_READ_PENDING) &&
1625
+ HasOverlappedIoCompleted(&pipe->read_req.overlapped)) {
1626
+ return;
1627
+ }
1628
+
1629
+ /* Force both ends off the pipe. */
1630
+ CloseHandle(pipe->handle);
1631
+ pipe->handle = INVALID_HANDLE_VALUE;
1632
+
1633
+ /* Stop reading, so the pending read that is going to fail will */
1634
+ /* not be reported to the user. */
1635
+ uv_read_stop((uv_stream_t*) pipe);
1636
+
1637
+ /* Report the eof and update flags. This will get reported even if the */
1638
+ /* user stopped reading in the meantime. TODO: is that okay? */
1639
+ uv_pipe_read_eof(loop, pipe, uv_null_buf_);
1640
+ }
1641
+
1642
+
1643
+ static void eof_timer_destroy(uv_pipe_t* pipe) {
1644
+ assert(pipe->flags && UV_HANDLE_CONNECTION);
1645
+
1646
+ if (pipe->eof_timer) {
1647
+ uv_close((uv_handle_t*) pipe->eof_timer, eof_timer_close_cb);
1648
+ pipe->eof_timer = NULL;
1649
+ }
1650
+ }
1651
+
1652
+
1653
+ static void eof_timer_close_cb(uv_handle_t* handle) {
1654
+ assert(handle->type == UV_TIMER);
1655
+ free(handle);
1656
+ }
1657
+
1658
+
1659
+ void uv_pipe_open(uv_pipe_t* pipe, uv_file file) {
1660
+ HANDLE os_handle = (HANDLE)_get_osfhandle(file);
1661
+
1662
+ if (os_handle == INVALID_HANDLE_VALUE ||
1663
+ uv_set_pipe_handle(pipe->loop, pipe, os_handle, 0) == -1) {
1664
+ return;
1665
+ }
1666
+
1667
+ uv_pipe_connection_init(pipe);
1668
+ pipe->handle = os_handle;
1669
+
1670
+ if (pipe->ipc) {
1671
+ assert(!(pipe->flags & UV_HANDLE_NON_OVERLAPPED_PIPE));
1672
+ pipe->ipc_pid = uv_parent_pid();
1673
+ assert(pipe->ipc_pid != -1);
1674
+ }
1675
+ }