asyncengine 0.0.1.testing1 → 0.0.2.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (251) hide show
  1. data/README.markdown +3 -0
  2. data/Rakefile +38 -0
  3. data/asyncengine.gemspec +8 -4
  4. data/ext/asyncengine/ae_call_from_other_thread.c +106 -0
  5. data/ext/asyncengine/ae_call_from_other_thread.h +12 -0
  6. data/ext/asyncengine/ae_handle_common.c +193 -48
  7. data/ext/asyncengine/ae_handle_common.h +40 -13
  8. data/ext/asyncengine/ae_ip_utils.c +246 -0
  9. data/ext/asyncengine/ae_ip_utils.h +25 -0
  10. data/ext/asyncengine/ae_next_tick.c +81 -21
  11. data/ext/asyncengine/ae_next_tick.h +4 -2
  12. data/ext/asyncengine/ae_resolver.c +156 -0
  13. data/ext/asyncengine/ae_resolver.h +10 -0
  14. data/ext/asyncengine/ae_tcp.c +908 -0
  15. data/ext/asyncengine/ae_tcp.h +20 -0
  16. data/ext/asyncengine/ae_timer.c +355 -81
  17. data/ext/asyncengine/ae_timer.h +11 -4
  18. data/ext/asyncengine/ae_udp.c +579 -13
  19. data/ext/asyncengine/ae_udp.h +15 -2
  20. data/ext/asyncengine/ae_utils.c +192 -0
  21. data/ext/asyncengine/ae_utils.h +16 -0
  22. data/ext/asyncengine/asyncengine_ruby.c +469 -26
  23. data/ext/asyncengine/asyncengine_ruby.h +49 -11
  24. data/ext/asyncengine/debug.h +68 -0
  25. data/ext/asyncengine/extconf.rb +26 -2
  26. data/ext/asyncengine/ip_parser.c +5954 -0
  27. data/ext/asyncengine/ip_parser.h +16 -0
  28. data/ext/asyncengine/libuv/AUTHORS +16 -0
  29. data/ext/asyncengine/libuv/common.gypi +4 -4
  30. data/ext/asyncengine/libuv/config-mingw.mk +6 -6
  31. data/ext/asyncengine/libuv/config-unix.mk +13 -13
  32. data/ext/asyncengine/libuv/gyp_uv +5 -1
  33. data/ext/asyncengine/libuv/ibc_tests/exec_test.sh +8 -0
  34. data/ext/asyncengine/libuv/ibc_tests/uv_shutdown_write_issue.c +171 -0
  35. data/ext/asyncengine/libuv/ibc_tests/uv_tcp_close_while_connecting.c +102 -0
  36. data/ext/asyncengine/libuv/include/uv-private/ngx-queue.h +3 -1
  37. data/ext/asyncengine/libuv/include/uv-private/uv-unix.h +103 -50
  38. data/ext/asyncengine/libuv/include/uv-private/uv-win.h +76 -24
  39. data/ext/asyncengine/libuv/include/uv.h +353 -88
  40. data/ext/asyncengine/libuv/src/ares/ares__close_sockets.o +0 -0
  41. data/ext/asyncengine/libuv/src/ares/ares__get_hostent.o +0 -0
  42. data/ext/asyncengine/libuv/src/ares/ares__read_line.o +0 -0
  43. data/ext/asyncengine/libuv/src/ares/ares__timeval.o +0 -0
  44. data/ext/asyncengine/libuv/src/ares/ares_cancel.o +0 -0
  45. data/ext/asyncengine/libuv/src/ares/ares_data.o +0 -0
  46. data/ext/asyncengine/libuv/src/ares/ares_destroy.o +0 -0
  47. data/ext/asyncengine/libuv/src/ares/ares_expand_name.o +0 -0
  48. data/ext/asyncengine/libuv/src/ares/ares_expand_string.o +0 -0
  49. data/ext/asyncengine/libuv/src/ares/ares_fds.o +0 -0
  50. data/ext/asyncengine/libuv/src/ares/ares_free_hostent.o +0 -0
  51. data/ext/asyncengine/libuv/src/ares/ares_free_string.o +0 -0
  52. data/ext/asyncengine/libuv/src/ares/ares_gethostbyaddr.o +0 -0
  53. data/ext/asyncengine/libuv/src/ares/ares_gethostbyname.o +0 -0
  54. data/ext/asyncengine/libuv/src/ares/ares_getnameinfo.o +0 -0
  55. data/ext/asyncengine/libuv/src/ares/ares_getopt.o +0 -0
  56. data/ext/asyncengine/libuv/src/ares/ares_getsock.o +0 -0
  57. data/ext/asyncengine/libuv/src/ares/ares_init.o +0 -0
  58. data/ext/asyncengine/libuv/src/ares/ares_library_init.o +0 -0
  59. data/ext/asyncengine/libuv/src/ares/ares_llist.o +0 -0
  60. data/ext/asyncengine/libuv/src/ares/ares_mkquery.o +0 -0
  61. data/ext/asyncengine/libuv/src/ares/ares_nowarn.o +0 -0
  62. data/ext/asyncengine/libuv/src/ares/ares_options.o +0 -0
  63. data/ext/asyncengine/libuv/src/ares/ares_parse_a_reply.o +0 -0
  64. data/ext/asyncengine/libuv/src/ares/ares_parse_aaaa_reply.o +0 -0
  65. data/ext/asyncengine/libuv/src/ares/ares_parse_mx_reply.o +0 -0
  66. data/ext/asyncengine/libuv/src/ares/ares_parse_ns_reply.o +0 -0
  67. data/ext/asyncengine/libuv/src/ares/ares_parse_ptr_reply.o +0 -0
  68. data/ext/asyncengine/libuv/src/ares/ares_parse_srv_reply.o +0 -0
  69. data/ext/asyncengine/libuv/src/ares/ares_parse_txt_reply.o +0 -0
  70. data/ext/asyncengine/libuv/src/ares/ares_process.o +0 -0
  71. data/ext/asyncengine/libuv/src/ares/ares_query.o +0 -0
  72. data/ext/asyncengine/libuv/src/ares/ares_search.o +0 -0
  73. data/ext/asyncengine/libuv/src/ares/ares_send.o +0 -0
  74. data/ext/asyncengine/libuv/src/ares/ares_strcasecmp.o +0 -0
  75. data/ext/asyncengine/libuv/src/ares/ares_strdup.o +0 -0
  76. data/ext/asyncengine/libuv/src/ares/ares_strerror.o +0 -0
  77. data/ext/asyncengine/libuv/src/ares/ares_timeout.o +0 -0
  78. data/ext/asyncengine/libuv/src/ares/ares_version.o +0 -0
  79. data/ext/asyncengine/libuv/src/ares/ares_writev.o +0 -0
  80. data/ext/asyncengine/libuv/src/ares/bitncmp.o +0 -0
  81. data/ext/asyncengine/libuv/src/ares/inet_net_pton.o +0 -0
  82. data/ext/asyncengine/libuv/src/ares/inet_ntop.o +0 -0
  83. data/ext/asyncengine/libuv/src/cares.c +225 -0
  84. data/ext/asyncengine/libuv/src/cares.o +0 -0
  85. data/ext/asyncengine/libuv/src/fs-poll.c +237 -0
  86. data/ext/asyncengine/libuv/src/fs-poll.o +0 -0
  87. data/ext/asyncengine/libuv/src/unix/async.c +78 -17
  88. data/ext/asyncengine/libuv/src/unix/async.o +0 -0
  89. data/ext/asyncengine/libuv/src/unix/core.c +305 -213
  90. data/ext/asyncengine/libuv/src/unix/core.o +0 -0
  91. data/ext/asyncengine/libuv/src/unix/cygwin.c +1 -1
  92. data/ext/asyncengine/libuv/src/unix/darwin.c +2 -1
  93. data/ext/asyncengine/libuv/src/unix/dl.c +36 -44
  94. data/ext/asyncengine/libuv/src/unix/dl.o +0 -0
  95. data/ext/asyncengine/libuv/src/unix/eio/eio.o +0 -0
  96. data/ext/asyncengine/libuv/src/unix/error.c +6 -0
  97. data/ext/asyncengine/libuv/src/unix/error.o +0 -0
  98. data/ext/asyncengine/libuv/src/unix/ev/ev.c +8 -4
  99. data/ext/asyncengine/libuv/src/unix/ev/ev.o +0 -0
  100. data/ext/asyncengine/libuv/src/unix/freebsd.c +1 -1
  101. data/ext/asyncengine/libuv/src/unix/fs.c +25 -33
  102. data/ext/asyncengine/libuv/src/unix/fs.o +0 -0
  103. data/ext/asyncengine/libuv/src/unix/internal.h +50 -31
  104. data/ext/asyncengine/libuv/src/unix/kqueue.c +2 -7
  105. data/ext/asyncengine/libuv/src/unix/linux/core.o +0 -0
  106. data/ext/asyncengine/libuv/src/unix/linux/inotify.c +12 -14
  107. data/ext/asyncengine/libuv/src/unix/linux/inotify.o +0 -0
  108. data/ext/asyncengine/libuv/src/unix/linux/{core.c → linux-core.c} +1 -1
  109. data/ext/asyncengine/libuv/src/unix/linux/linux-core.o +0 -0
  110. data/ext/asyncengine/libuv/src/unix/linux/syscalls.c +147 -1
  111. data/ext/asyncengine/libuv/src/unix/linux/syscalls.h +39 -2
  112. data/ext/asyncengine/libuv/src/unix/linux/syscalls.o +0 -0
  113. data/ext/asyncengine/libuv/src/unix/loop-watcher.c +63 -0
  114. data/ext/asyncengine/libuv/src/unix/loop-watcher.o +0 -0
  115. data/ext/asyncengine/libuv/src/unix/loop.c +29 -6
  116. data/ext/asyncengine/libuv/src/unix/loop.o +0 -0
  117. data/ext/asyncengine/libuv/src/unix/netbsd.c +1 -1
  118. data/ext/asyncengine/libuv/src/unix/openbsd.c +1 -1
  119. data/ext/asyncengine/libuv/src/unix/pipe.c +31 -36
  120. data/ext/asyncengine/libuv/src/unix/pipe.o +0 -0
  121. data/ext/asyncengine/libuv/src/unix/poll.c +116 -0
  122. data/ext/asyncengine/libuv/src/unix/poll.o +0 -0
  123. data/ext/asyncengine/libuv/src/unix/process.c +193 -115
  124. data/ext/asyncengine/libuv/src/unix/process.o +0 -0
  125. data/ext/asyncengine/libuv/src/unix/stream.c +146 -153
  126. data/ext/asyncengine/libuv/src/unix/stream.o +0 -0
  127. data/ext/asyncengine/libuv/src/unix/sunos.c +45 -36
  128. data/ext/asyncengine/libuv/src/unix/tcp.c +6 -5
  129. data/ext/asyncengine/libuv/src/unix/tcp.o +0 -0
  130. data/ext/asyncengine/libuv/src/unix/thread.c +82 -25
  131. data/ext/asyncengine/libuv/src/unix/thread.o +0 -0
  132. data/ext/asyncengine/libuv/src/unix/timer.c +69 -58
  133. data/ext/asyncengine/libuv/src/unix/timer.o +0 -0
  134. data/ext/asyncengine/libuv/src/unix/tty.c +3 -3
  135. data/ext/asyncengine/libuv/src/unix/tty.o +0 -0
  136. data/ext/asyncengine/libuv/src/unix/udp.c +57 -66
  137. data/ext/asyncengine/libuv/src/unix/udp.o +0 -0
  138. data/ext/asyncengine/libuv/src/unix/uv-eio.c +33 -50
  139. data/ext/asyncengine/libuv/src/unix/uv-eio.o +0 -0
  140. data/ext/asyncengine/libuv/src/uv-common.c +68 -38
  141. data/ext/asyncengine/libuv/src/uv-common.h +104 -20
  142. data/ext/asyncengine/libuv/src/uv-common.o +0 -0
  143. data/ext/asyncengine/libuv/src/win/async.c +20 -17
  144. data/ext/asyncengine/libuv/src/win/core.c +44 -31
  145. data/ext/asyncengine/libuv/src/win/dl.c +40 -36
  146. data/ext/asyncengine/libuv/src/win/error.c +21 -1
  147. data/ext/asyncengine/libuv/src/win/fs-event.c +19 -21
  148. data/ext/asyncengine/libuv/src/win/fs.c +541 -189
  149. data/ext/asyncengine/libuv/src/win/getaddrinfo.c +56 -63
  150. data/ext/asyncengine/libuv/src/win/handle-inl.h +145 -0
  151. data/ext/asyncengine/libuv/src/win/handle.c +26 -101
  152. data/ext/asyncengine/libuv/src/win/internal.h +92 -107
  153. data/ext/asyncengine/libuv/src/win/loop-watcher.c +6 -14
  154. data/ext/asyncengine/libuv/src/win/pipe.c +78 -64
  155. data/ext/asyncengine/libuv/src/win/poll.c +618 -0
  156. data/ext/asyncengine/libuv/src/win/process-stdio.c +479 -0
  157. data/ext/asyncengine/libuv/src/win/process.c +147 -274
  158. data/ext/asyncengine/libuv/src/win/req-inl.h +225 -0
  159. data/ext/asyncengine/libuv/src/win/req.c +0 -149
  160. data/ext/asyncengine/libuv/src/{unix/check.c → win/stream-inl.h} +31 -42
  161. data/ext/asyncengine/libuv/src/win/stream.c +9 -43
  162. data/ext/asyncengine/libuv/src/win/tcp.c +200 -82
  163. data/ext/asyncengine/libuv/src/win/thread.c +42 -2
  164. data/ext/asyncengine/libuv/src/win/threadpool.c +3 -2
  165. data/ext/asyncengine/libuv/src/win/timer.c +13 -63
  166. data/ext/asyncengine/libuv/src/win/tty.c +26 -20
  167. data/ext/asyncengine/libuv/src/win/udp.c +26 -17
  168. data/ext/asyncengine/libuv/src/win/util.c +312 -167
  169. data/ext/asyncengine/libuv/src/win/winapi.c +16 -1
  170. data/ext/asyncengine/libuv/src/win/winapi.h +33 -9
  171. data/ext/asyncengine/libuv/src/win/winsock.c +88 -1
  172. data/ext/asyncengine/libuv/src/win/winsock.h +36 -3
  173. data/ext/asyncengine/libuv/test/benchmark-ares.c +16 -17
  174. data/ext/asyncengine/libuv/test/benchmark-fs-stat.c +164 -0
  175. data/ext/asyncengine/libuv/test/benchmark-list.h +9 -0
  176. data/ext/asyncengine/libuv/{src/unix/prepare.c → test/benchmark-loop-count.c} +42 -33
  177. data/ext/asyncengine/libuv/test/benchmark-million-timers.c +65 -0
  178. data/ext/asyncengine/libuv/test/benchmark-pound.c +1 -1
  179. data/ext/asyncengine/libuv/test/benchmark-sizes.c +2 -0
  180. data/ext/asyncengine/libuv/test/benchmark-spawn.c +7 -1
  181. data/ext/asyncengine/libuv/test/benchmark-udp-packet-storm.c +1 -1
  182. data/ext/asyncengine/libuv/test/echo-server.c +8 -0
  183. data/ext/asyncengine/libuv/test/run-tests.c +30 -0
  184. data/ext/asyncengine/libuv/test/runner-unix.c +6 -26
  185. data/ext/asyncengine/libuv/test/runner-win.c +5 -63
  186. data/ext/asyncengine/libuv/test/runner.c +10 -1
  187. data/ext/asyncengine/libuv/test/task.h +0 -8
  188. data/ext/asyncengine/libuv/test/test-async.c +43 -141
  189. data/ext/asyncengine/libuv/test/test-callback-order.c +76 -0
  190. data/ext/asyncengine/libuv/test/test-counters-init.c +2 -3
  191. data/ext/asyncengine/libuv/test/test-dlerror.c +17 -8
  192. data/ext/asyncengine/libuv/test/test-fs-event.c +31 -39
  193. data/ext/asyncengine/libuv/test/test-fs-poll.c +146 -0
  194. data/ext/asyncengine/libuv/test/test-fs.c +114 -2
  195. data/ext/asyncengine/libuv/test/test-gethostbyname.c +8 -8
  196. data/ext/asyncengine/libuv/test/test-hrtime.c +18 -15
  197. data/ext/asyncengine/libuv/test/test-ipc.c +8 -2
  198. data/ext/asyncengine/libuv/test/test-list.h +59 -9
  199. data/ext/asyncengine/libuv/test/test-loop-handles.c +2 -25
  200. data/ext/asyncengine/libuv/{src/unix/idle.c → test/test-poll-close.c} +37 -39
  201. data/ext/asyncengine/libuv/test/test-poll.c +573 -0
  202. data/ext/asyncengine/libuv/test/test-ref.c +79 -63
  203. data/ext/asyncengine/libuv/test/test-run-once.c +15 -11
  204. data/ext/asyncengine/libuv/test/test-semaphore.c +111 -0
  205. data/ext/asyncengine/libuv/test/test-spawn.c +368 -20
  206. data/ext/asyncengine/libuv/test/test-stdio-over-pipes.c +25 -35
  207. data/ext/asyncengine/libuv/test/test-tcp-close-while-connecting.c +80 -0
  208. data/ext/asyncengine/libuv/test/test-tcp-close.c +1 -1
  209. data/ext/asyncengine/libuv/test/test-tcp-connect-error-after-write.c +95 -0
  210. data/ext/asyncengine/libuv/test/test-tcp-connect-timeout.c +85 -0
  211. data/ext/asyncengine/libuv/test/test-tcp-shutdown-after-write.c +131 -0
  212. data/ext/asyncengine/libuv/test/test-tcp-write-error.c +2 -2
  213. data/ext/asyncengine/libuv/test/test-tcp-writealot.c +29 -54
  214. data/ext/asyncengine/libuv/test/test-timer-again.c +1 -1
  215. data/ext/asyncengine/libuv/test/test-timer.c +23 -1
  216. data/ext/asyncengine/libuv/test/test-udp-options.c +1 -1
  217. data/ext/asyncengine/libuv/test/{test-eio-overflow.c → test-walk-handles.c} +31 -44
  218. data/ext/asyncengine/libuv/uv.gyp +26 -9
  219. data/ext/asyncengine/rb_utilities.c +54 -0
  220. data/ext/asyncengine/rb_utilities.h +63 -0
  221. data/lib/asyncengine.rb +45 -38
  222. data/lib/asyncengine/asyncengine_ext.so +0 -0
  223. data/lib/asyncengine/debug.rb +37 -0
  224. data/lib/asyncengine/handle.rb +9 -0
  225. data/lib/asyncengine/tcp.rb +28 -0
  226. data/lib/asyncengine/timer.rb +18 -28
  227. data/lib/asyncengine/udp.rb +29 -0
  228. data/lib/asyncengine/utils.rb +32 -0
  229. data/lib/asyncengine/uv_error.rb +17 -0
  230. data/lib/asyncengine/version.rb +9 -1
  231. data/test/ae_test_helper.rb +62 -0
  232. data/test/test_basic.rb +169 -0
  233. data/test/test_call_from_other_thread.rb +55 -0
  234. data/test/test_error.rb +92 -0
  235. data/test/test_ip_utils.rb +44 -0
  236. data/test/test_next_tick.rb +37 -0
  237. data/test/test_resolver.rb +51 -0
  238. data/test/test_threads.rb +69 -0
  239. data/test/test_timer.rb +95 -0
  240. data/test/test_udp.rb +216 -0
  241. data/test/test_utils.rb +49 -0
  242. metadata +84 -57
  243. data/ext/asyncengine/libuv/mkmf.log +0 -24
  244. data/ext/asyncengine/libuv/src/unix/cares.c +0 -194
  245. data/ext/asyncengine/libuv/src/unix/cares.o +0 -0
  246. data/ext/asyncengine/libuv/src/unix/check.o +0 -0
  247. data/ext/asyncengine/libuv/src/unix/idle.o +0 -0
  248. data/ext/asyncengine/libuv/src/unix/prepare.o +0 -0
  249. data/ext/asyncengine/libuv/src/win/cares.c +0 -290
  250. data/lib/asyncengine/errors.rb +0 -5
  251. data/lib/asyncengine/next_tick.rb +0 -24
@@ -21,6 +21,7 @@
21
21
 
22
22
  #include <assert.h>
23
23
  #include <direct.h>
24
+ #include <limits.h>
24
25
  #include <malloc.h>
25
26
  #include <stdio.h>
26
27
  #include <string.h>
@@ -29,9 +30,10 @@
29
30
 
30
31
  #include "uv.h"
31
32
  #include "internal.h"
32
- #include "tlhelp32.h"
33
- #include "psapi.h"
34
- #include "iphlpapi.h"
33
+
34
+ #include <iphlpapi.h>
35
+ #include <psapi.h>
36
+ #include <tlhelp32.h>
35
37
 
36
38
 
37
39
  /*
@@ -46,11 +48,32 @@
46
48
  */
47
49
  #define MAX_TITLE_LENGTH 8192
48
50
 
51
+ /* The number of nanoseconds in one second. */
52
+ #undef NANOSEC
53
+ #define NANOSEC 1000000000
54
+
49
55
 
56
+ /* Cached copy of the process title, plus a mutex guarding it. */
50
57
  static char *process_title;
51
- static uv_once_t uv_process_title_init_guard_ = UV_ONCE_INIT;
52
58
  static CRITICAL_SECTION process_title_lock;
53
59
 
60
+ /* The tick frequency of the high-resolution clock. */
61
+ static uint64_t hrtime_frequency_ = 0;
62
+
63
+
64
+ /*
65
+ * One-time intialization code for functionality defined in util.c.
66
+ */
67
+ void uv__util_init() {
68
+ /* Initialize process title access mutex. */
69
+ InitializeCriticalSection(&process_title_lock);
70
+
71
+ /* Retrieve high-resolution timer frequency. */
72
+ if (!QueryPerformanceFrequency((LARGE_INTEGER*) &hrtime_frequency_))
73
+ hrtime_frequency_ = 0;
74
+ }
75
+
76
+
54
77
  int uv_utf16_to_utf8(const wchar_t* utf16Buffer, size_t utf16Size,
55
78
  char* utf8Buffer, size_t utf8Size) {
56
79
  return WideCharToMultiByte(CP_UTF8,
@@ -75,133 +98,182 @@ int uv_utf8_to_utf16(const char* utf8Buffer, wchar_t* utf16Buffer,
75
98
  }
76
99
 
77
100
 
78
- int uv_exepath(char* buffer, size_t* size) {
79
- int retVal;
80
- size_t utf16Size;
81
- wchar_t* utf16Buffer;
101
+ int uv_exepath(char* buffer, size_t* size_ptr) {
102
+ int utf8_len, utf16_buffer_len, utf16_len;
103
+ WCHAR* utf16_buffer;
82
104
 
83
- if (!buffer || !size) {
105
+ if (buffer == NULL || size_ptr == NULL || *size_ptr == 0) {
84
106
  return -1;
85
107
  }
86
108
 
87
- utf16Buffer = (wchar_t*)malloc(sizeof(wchar_t) * *size);
88
- if (!utf16Buffer) {
89
- retVal = -1;
90
- goto done;
109
+ if (*size_ptr > 32768) {
110
+ /* Windows paths can never be longer than this. */
111
+ utf16_buffer_len = 32768;
112
+ } else {
113
+ utf16_buffer_len = (int) *size_ptr;
91
114
  }
92
115
 
93
- /* Get the path as UTF-16 */
94
- utf16Size = GetModuleFileNameW(NULL, utf16Buffer, *size - 1);
95
- if (utf16Size <= 0) {
96
- /* uv__set_sys_error(loop, GetLastError()); */
97
- retVal = -1;
98
- goto done;
116
+ utf16_buffer = (wchar_t*) malloc(sizeof(WCHAR) * utf16_buffer_len);
117
+ if (!utf16_buffer) {
118
+ return -1;
99
119
  }
100
120
 
101
- utf16Buffer[utf16Size] = L'\0';
102
-
103
- /* Convert to UTF-8 */
104
- *size = uv_utf16_to_utf8(utf16Buffer, utf16Size, buffer, *size);
105
- if (!*size) {
106
- /* uv__set_sys_error(loop, GetLastError()); */
107
- retVal = -1;
108
- goto done;
121
+ /* Get the path as UTF-16. */
122
+ utf16_len = GetModuleFileNameW(NULL, utf16_buffer, utf16_buffer_len);
123
+ if (utf16_len <= 0) {
124
+ goto error;
109
125
  }
110
126
 
111
- buffer[*size] = '\0';
112
- retVal = 0;
127
+ /* utf16_len contains the length, *not* including the terminating null. */
128
+ utf16_buffer[utf16_len] = L'\0';
113
129
 
114
- done:
115
- if (utf16Buffer) {
116
- free(utf16Buffer);
117
- }
130
+ /* Convert to UTF-8 */
131
+ utf8_len = WideCharToMultiByte(CP_UTF8,
132
+ 0,
133
+ utf16_buffer,
134
+ -1,
135
+ buffer,
136
+ *size_ptr > INT_MAX ? INT_MAX : (int) *size_ptr,
137
+ NULL,
138
+ NULL);
139
+ if (utf8_len == 0) {
140
+ goto error;
141
+ }
142
+
143
+ free(utf16_buffer);
144
+
145
+ /* utf8_len *does* include the terminating null at this point, but the */
146
+ /* returned size shouldn't. */
147
+ *size_ptr = utf8_len - 1;
148
+ return 0;
118
149
 
119
- return retVal;
150
+ error:
151
+ free(utf16_buffer);
152
+ return -1;
120
153
  }
121
154
 
122
155
 
123
156
  uv_err_t uv_cwd(char* buffer, size_t size) {
124
- uv_err_t err;
125
- size_t utf8Size;
126
- wchar_t* utf16Buffer = NULL;
157
+ DWORD utf16_len;
158
+ WCHAR utf16_buffer[MAX_PATH];
159
+ int r;
127
160
 
128
- if (!buffer || !size) {
129
- err.code = UV_EINVAL;
130
- goto done;
161
+ if (buffer == NULL || size == 0) {
162
+ return uv__new_artificial_error(UV_EINVAL);
131
163
  }
132
164
 
133
- utf16Buffer = (wchar_t*)malloc(sizeof(wchar_t) * size);
134
- if (!utf16Buffer) {
135
- err.code = UV_ENOMEM;
136
- goto done;
137
- }
138
-
139
- if (!_wgetcwd(utf16Buffer, size - 1)) {
140
- err = uv__new_sys_error(_doserrno);
141
- goto done;
165
+ utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer);
166
+ if (utf16_len == 0) {
167
+ return uv__new_sys_error(GetLastError());
168
+ } else if (utf16_len > MAX_PATH) {
169
+ /* This should be impossible; however the CRT has a code path to deal */
170
+ /* with this scenario, so I added a check anyway. */
171
+ return uv__new_artificial_error(UV_EIO);
142
172
  }
143
173
 
144
- utf16Buffer[size - 1] = L'\0';
174
+ /* utf16_len contains the length, *not* including the terminating null. */
175
+ utf16_buffer[utf16_len] = L'\0';
145
176
 
146
- /* Convert to UTF-8 */
147
- utf8Size = uv_utf16_to_utf8(utf16Buffer, -1, buffer, size);
148
- if (utf8Size == 0) {
149
- err = uv__new_sys_error(GetLastError());
150
- goto done;
177
+ /* The returned directory should not have a trailing slash, unless it */
178
+ /* points at a drive root, like c:\. Remove it if needed.*/
179
+ if (utf16_buffer[utf16_len - 1] == L'\\' &&
180
+ !(utf16_len == 3 && utf16_buffer[1] == L':')) {
181
+ utf16_len--;
182
+ utf16_buffer[utf16_len] = L'\0';
151
183
  }
152
184
 
153
- buffer[utf8Size] = '\0';
154
- err = uv_ok_;
155
-
156
- done:
157
- if (utf16Buffer) {
158
- free(utf16Buffer);
185
+ /* Convert to UTF-8 */
186
+ r = WideCharToMultiByte(CP_UTF8,
187
+ 0,
188
+ utf16_buffer,
189
+ -1,
190
+ buffer,
191
+ size > INT_MAX ? INT_MAX : (int) size,
192
+ NULL,
193
+ NULL);
194
+ if (r == 0) {
195
+ return uv__new_sys_error(GetLastError());
159
196
  }
160
197
 
161
- return err;
198
+ return uv_ok_;
162
199
  }
163
200
 
164
201
 
165
202
  uv_err_t uv_chdir(const char* dir) {
166
- uv_err_t err;
167
- wchar_t* utf16Buffer = NULL;
168
- size_t utf16Size;
169
-
170
- if (!dir) {
171
- err.code = UV_EINVAL;
172
- goto done;
173
- }
174
-
175
- utf16Size = uv_utf8_to_utf16(dir, NULL, 0);
176
- if (!utf16Size) {
177
- err = uv__new_sys_error(GetLastError());
178
- goto done;
179
- }
180
-
181
- utf16Buffer = (wchar_t*)malloc(sizeof(wchar_t) * utf16Size);
182
- if (!utf16Buffer) {
183
- err.code = UV_ENOMEM;
184
- goto done;
203
+ WCHAR utf16_buffer[MAX_PATH];
204
+ size_t utf16_len;
205
+ WCHAR drive_letter, env_var[4];
206
+
207
+ if (dir == NULL) {
208
+ return uv__new_artificial_error(UV_EINVAL);
209
+ }
210
+
211
+ if (MultiByteToWideChar(CP_UTF8,
212
+ 0,
213
+ dir,
214
+ -1,
215
+ utf16_buffer,
216
+ MAX_PATH) == 0) {
217
+ DWORD error = GetLastError();
218
+ /* The maximum length of the current working directory is 260 chars, */
219
+ /* including terminating null. If it doesn't fit, the path name must be */
220
+ /* too long. */
221
+ if (error == ERROR_INSUFFICIENT_BUFFER) {
222
+ return uv__new_artificial_error(UV_ENAMETOOLONG);
223
+ } else {
224
+ return uv__new_sys_error(error);
225
+ }
185
226
  }
186
227
 
187
- if (!uv_utf8_to_utf16(dir, utf16Buffer, utf16Size)) {
188
- err = uv__new_sys_error(GetLastError());
189
- goto done;
228
+ if (!SetCurrentDirectoryW(utf16_buffer)) {
229
+ return uv__new_sys_error(GetLastError());
190
230
  }
191
231
 
192
- if (_wchdir(utf16Buffer) == -1) {
193
- err = uv__new_sys_error(_doserrno);
194
- goto done;
232
+ /* Windows stores the drive-local path in an "hidden" environment variable, */
233
+ /* which has the form "=C:=C:\Windows". SetCurrentDirectory does not */
234
+ /* update this, so we'll have to do it. */
235
+ utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer);
236
+ if (utf16_len == 0) {
237
+ return uv__new_sys_error(GetLastError());
238
+ } else if (utf16_len > MAX_PATH) {
239
+ return uv__new_artificial_error(UV_EIO);
240
+ }
241
+
242
+ /* The returned directory should not have a trailing slash, unless it */
243
+ /* points at a drive root, like c:\. Remove it if needed. */
244
+ if (utf16_buffer[utf16_len - 1] == L'\\' &&
245
+ !(utf16_len == 3 && utf16_buffer[1] == L':')) {
246
+ utf16_len--;
247
+ utf16_buffer[utf16_len] = L'\0';
248
+ }
249
+
250
+ if (utf16_len < 2 || utf16_buffer[1] != L':') {
251
+ /* Doesn't look like a drive letter could be there - probably an UNC */
252
+ /* path. TODO: Need to handle win32 namespaces like \\?\C:\ ? */
253
+ drive_letter = 0;
254
+ } else if (utf16_buffer[0] >= L'A' && utf16_buffer[0] <= L'Z') {
255
+ drive_letter = utf16_buffer[0];
256
+ } else if (utf16_buffer[0] >= L'a' && utf16_buffer[0] <= L'z') {
257
+ /* Convert to uppercase. */
258
+ drive_letter = utf16_buffer[0] - L'a' + L'A';
259
+ } else {
260
+ /* Not valid. */
261
+ drive_letter = 0;
195
262
  }
196
263
 
197
- err = uv_ok_;
264
+ if (drive_letter != 0) {
265
+ /* Construct the environment variable name and set it. */
266
+ env_var[0] = L'=';
267
+ env_var[1] = drive_letter;
268
+ env_var[2] = L':';
269
+ env_var[3] = L'\0';
198
270
 
199
- done:
200
- if (utf16Buffer) {
201
- free(utf16Buffer);
271
+ if (!SetEnvironmentVariableW(env_var, utf16_buffer)) {
272
+ return uv__new_sys_error(GetLastError());
273
+ }
202
274
  }
203
275
 
204
- return err;
276
+ return uv_ok_;
205
277
  }
206
278
 
207
279
 
@@ -265,17 +337,12 @@ char** uv_setup_args(int argc, char** argv) {
265
337
  }
266
338
 
267
339
 
268
- static void uv_process_title_init(void) {
269
- InitializeCriticalSection(&process_title_lock);
270
- }
271
-
272
-
273
340
  uv_err_t uv_set_process_title(const char* title) {
274
341
  uv_err_t err;
275
342
  int length;
276
343
  wchar_t* title_w = NULL;
277
344
 
278
- uv_once(&uv_process_title_init_guard_, uv_process_title_init);
345
+ uv__once_init();
279
346
 
280
347
  /* Find out how big the buffer for the wide-char title must be */
281
348
  length = uv_utf8_to_utf16(title, NULL, 0);
@@ -350,7 +417,7 @@ static int uv__get_process_title() {
350
417
 
351
418
 
352
419
  uv_err_t uv_get_process_title(char* buffer, size_t size) {
353
- uv_once(&uv_process_title_init_guard_, uv_process_title_init);
420
+ uv__once_init();
354
421
 
355
422
  EnterCriticalSection(&process_title_lock);
356
423
  /*
@@ -369,6 +436,31 @@ uv_err_t uv_get_process_title(char* buffer, size_t size) {
369
436
  }
370
437
 
371
438
 
439
+ uint64_t uv_hrtime(void) {
440
+ LARGE_INTEGER counter;
441
+
442
+ uv__once_init();
443
+
444
+ /* If the performance frequency is zero, there's no support. */
445
+ if (!hrtime_frequency_) {
446
+ /* uv__set_sys_error(loop, ERROR_NOT_SUPPORTED); */
447
+ return 0;
448
+ }
449
+
450
+ if (!QueryPerformanceCounter(&counter)) {
451
+ /* uv__set_sys_error(loop, GetLastError()); */
452
+ return 0;
453
+ }
454
+
455
+ /* Because we have no guarantee about the order of magnitude of the */
456
+ /* performance counter frequency, and there may not be much headroom to */
457
+ /* multiply by NANOSEC without overflowing, we use 128-bit math instead. */
458
+ return ((uint64_t) counter.LowPart * NANOSEC / hrtime_frequency_) +
459
+ (((uint64_t) counter.HighPart * NANOSEC / hrtime_frequency_)
460
+ << 32);
461
+ }
462
+
463
+
372
464
  uv_err_t uv_resident_set_memory(size_t* rss) {
373
465
  HANDLE current_process;
374
466
  PROCESS_MEMORY_COUNTERS pmc;
@@ -487,81 +579,148 @@ uv_err_t uv_uptime(double* uptime) {
487
579
 
488
580
 
489
581
  uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
490
- uv_err_t err;
491
- char key[128];
492
- HKEY processor_key = NULL;
493
- DWORD cpu_speed = 0;
494
- DWORD cpu_speed_length = sizeof(cpu_speed);
495
- char cpu_brand[256];
496
- DWORD cpu_brand_length = sizeof(cpu_brand);
582
+ SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* sppi;
583
+ DWORD sppi_size;
497
584
  SYSTEM_INFO system_info;
585
+ DWORD cpu_count, i, r;
586
+ ULONG result_size;
587
+ size_t size;
588
+ uv_err_t err;
498
589
  uv_cpu_info_t* cpu_info;
499
- unsigned int i;
500
590
 
501
- GetSystemInfo(&system_info);
591
+ *cpu_infos = NULL;
592
+ *count = 0;
502
593
 
503
- *cpu_infos = (uv_cpu_info_t*)malloc(system_info.dwNumberOfProcessors *
504
- sizeof(uv_cpu_info_t));
505
- if (!(*cpu_infos)) {
506
- uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
507
- }
594
+ uv__once_init();
508
595
 
509
- *count = 0;
596
+ GetSystemInfo(&system_info);
597
+ cpu_count = system_info.dwNumberOfProcessors;
510
598
 
511
- for (i = 0; i < system_info.dwNumberOfProcessors; i++) {
512
- _snprintf(key, sizeof(key), "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\%d", i);
599
+ size = cpu_count * sizeof(uv_cpu_info_t);
600
+ *cpu_infos = (uv_cpu_info_t*) malloc(size);
601
+ if (*cpu_infos == NULL) {
602
+ err = uv__new_artificial_error(UV_ENOMEM);
603
+ goto out;
604
+ }
605
+ memset(*cpu_infos, 0, size);
513
606
 
514
- if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_QUERY_VALUE,
515
- &processor_key) != ERROR_SUCCESS) {
516
- if (i == 0) {
517
- err = uv__new_sys_error(GetLastError());
518
- goto done;
519
- }
607
+ sppi_size = sizeof(*sppi) * cpu_count;
608
+ sppi = (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION*) malloc(sppi_size);
609
+ if (!sppi) {
610
+ uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
611
+ }
520
612
 
521
- continue;
613
+ r = pNtQuerySystemInformation(SystemProcessorPerformanceInformation,
614
+ sppi,
615
+ sppi_size,
616
+ &result_size);
617
+ if (r != ERROR_SUCCESS || result_size != sppi_size) {
618
+ err = uv__new_sys_error(GetLastError());
619
+ goto out;
620
+ }
621
+
622
+ for (i = 0; i < cpu_count; i++) {
623
+ WCHAR key_name[128];
624
+ HKEY processor_key;
625
+ DWORD cpu_speed;
626
+ DWORD cpu_speed_size = sizeof(cpu_speed);
627
+ WCHAR cpu_brand[256];
628
+ DWORD cpu_brand_size = sizeof(cpu_brand);
629
+
630
+ _snwprintf(key_name,
631
+ ARRAY_SIZE(key_name),
632
+ L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\%d",
633
+ i);
634
+
635
+ r = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
636
+ key_name,
637
+ 0,
638
+ KEY_QUERY_VALUE,
639
+ &processor_key);
640
+ if (r != ERROR_SUCCESS) {
641
+ err = uv__new_sys_error(GetLastError());
642
+ goto out;
522
643
  }
523
644
 
524
- if (RegQueryValueEx(processor_key, "~MHz", NULL, NULL,
525
- (LPBYTE)&cpu_speed, &cpu_speed_length)
526
- != ERROR_SUCCESS) {
645
+ if (RegQueryValueExW(processor_key,
646
+ L"~MHz",
647
+ NULL, NULL,
648
+ (BYTE*) &cpu_speed,
649
+ &cpu_speed_size) != ERROR_SUCCESS) {
527
650
  err = uv__new_sys_error(GetLastError());
528
- goto done;
651
+ RegCloseKey(processor_key);
652
+ goto out;
529
653
  }
530
654
 
531
- if (RegQueryValueEx(processor_key, "ProcessorNameString", NULL, NULL,
532
- (LPBYTE)&cpu_brand, &cpu_brand_length)
533
- != ERROR_SUCCESS) {
655
+ if (RegQueryValueExW(processor_key,
656
+ L"ProcessorNameString",
657
+ NULL, NULL,
658
+ (BYTE*) &cpu_brand,
659
+ &cpu_brand_size) != ERROR_SUCCESS) {
534
660
  err = uv__new_sys_error(GetLastError());
535
- goto done;
661
+ RegCloseKey(processor_key);
662
+ goto out;
536
663
  }
537
664
 
538
665
  RegCloseKey(processor_key);
539
- processor_key = NULL;
540
666
 
541
667
  cpu_info = &(*cpu_infos)[i];
542
-
543
- /* $TODO: find times on windows */
544
- cpu_info->cpu_times.user = 0;
668
+ cpu_info->speed = cpu_speed;
669
+ cpu_info->cpu_times.user = sppi[i].UserTime.QuadPart / 10000;
670
+ cpu_info->cpu_times.sys = (sppi[i].KernelTime.QuadPart -
671
+ sppi[i].IdleTime.QuadPart) / 10000;
672
+ cpu_info->cpu_times.idle = sppi[i].IdleTime.QuadPart / 10000;
673
+ cpu_info->cpu_times.irq = sppi[i].InterruptTime.QuadPart / 10000;
545
674
  cpu_info->cpu_times.nice = 0;
546
- cpu_info->cpu_times.sys = 0;
547
- cpu_info->cpu_times.idle = 0;
548
- cpu_info->cpu_times.irq = 0;
549
675
 
550
- cpu_info->model = strdup(cpu_brand);
551
- cpu_info->speed = cpu_speed;
676
+ size = uv_utf16_to_utf8(cpu_brand,
677
+ cpu_brand_size / sizeof(WCHAR),
678
+ NULL,
679
+ 0);
680
+ if (size == 0) {
681
+ err = uv__new_sys_error(GetLastError());
682
+ goto out;
683
+ }
684
+
685
+ /* Allocate 1 extra byte for the null terminator. */
686
+ cpu_info->model = (char*) malloc(size + 1);
687
+ if (cpu_info->model == NULL) {
688
+ err = uv__new_artificial_error(UV_ENOMEM);
689
+ goto out;
690
+ }
691
+
692
+ if (uv_utf16_to_utf8(cpu_brand,
693
+ cpu_brand_size / sizeof(WCHAR),
694
+ cpu_info->model,
695
+ size) == 0) {
696
+ err = uv__new_sys_error(GetLastError());
697
+ goto out;
698
+ }
699
+
700
+ /* Ensure that cpu_info->model is null terminated. */
701
+ cpu_info->model[size] = '\0';
552
702
 
553
703
  (*count)++;
554
704
  }
555
705
 
556
706
  err = uv_ok_;
557
707
 
558
- done:
559
- if (processor_key) {
560
- RegCloseKey(processor_key);
708
+ out:
709
+ if (sppi) {
710
+ free(sppi);
561
711
  }
562
712
 
563
- if (err.code != UV_OK) {
713
+ if (err.code != UV_OK &&
714
+ *cpu_infos != NULL) {
715
+ int i;
716
+
717
+ for (i = 0; i < *count; i++) {
718
+ /* This is safe because the cpu_infos memory area is zeroed out */
719
+ /* immediately after allocating it. */
720
+ free((*cpu_infos)[i].model);
721
+ }
564
722
  free(*cpu_infos);
723
+
565
724
  *cpu_infos = NULL;
566
725
  *count = 0;
567
726
  }
@@ -615,8 +774,13 @@ uv_err_t uv_interface_addresses(uv_interface_address_t** addresses,
615
774
  for (adapter_address = adapter_addresses;
616
775
  adapter_address != NULL;
617
776
  adapter_address = adapter_address->Next) {
777
+
778
+ if (adapter_address->OperStatus != IfOperStatusUp)
779
+ continue;
780
+
618
781
  unicast_address = (IP_ADAPTER_UNICAST_ADDRESS_XP*)
619
782
  adapter_address->FirstUnicastAddress;
783
+
620
784
  while (unicast_address) {
621
785
  (*count)++;
622
786
  unicast_address = unicast_address->Next;
@@ -634,6 +798,10 @@ uv_err_t uv_interface_addresses(uv_interface_address_t** addresses,
634
798
  for (adapter_address = adapter_addresses;
635
799
  adapter_address != NULL;
636
800
  adapter_address = adapter_address->Next) {
801
+
802
+ if (adapter_address->OperStatus != IfOperStatusUp)
803
+ continue;
804
+
637
805
  name = NULL;
638
806
  unicast_address = (IP_ADAPTER_UNICAST_ADDRESS_XP*)
639
807
  adapter_address->FirstUnicastAddress;
@@ -694,26 +862,3 @@ void uv_free_interface_addresses(uv_interface_address_t* addresses,
694
862
 
695
863
  free(addresses);
696
864
  }
697
-
698
-
699
- void uv_filetime_to_time_t(FILETIME* file_time, time_t* stat_time) {
700
- FILETIME local_time;
701
- SYSTEMTIME system_time;
702
- struct tm time;
703
-
704
- if ((file_time->dwLowDateTime || file_time->dwHighDateTime) &&
705
- FileTimeToLocalFileTime(file_time, &local_time) &&
706
- FileTimeToSystemTime(&local_time, &system_time)) {
707
- time.tm_year = system_time.wYear - 1900;
708
- time.tm_mon = system_time.wMonth - 1;
709
- time.tm_mday = system_time.wDay;
710
- time.tm_hour = system_time.wHour;
711
- time.tm_min = system_time.wMinute;
712
- time.tm_sec = system_time.wSecond;
713
- time.tm_isdst = -1;
714
-
715
- *stat_time = mktime(&time);
716
- } else {
717
- *stat_time = 0;
718
- }
719
- }