foolio 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +22 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +29 -0
- data/Rakefile +21 -0
- data/examples/timer.rb +20 -0
- data/ext/foolio/extconf.rb +34 -0
- data/ext/foolio/foolio_ext.c +921 -0
- data/ext/foolio/gen.rb +50 -0
- data/ext/foolio/make_table.rb +12 -0
- data/ext/foolio/templ +243 -0
- data/ext/libuv/.gitignore +33 -0
- data/ext/libuv/.mailmap +13 -0
- data/ext/libuv/.travis.yml +9 -0
- data/ext/libuv/AUTHORS +61 -0
- data/ext/libuv/LICENSE +44 -0
- data/ext/libuv/Makefile +71 -0
- data/ext/libuv/README.md +90 -0
- data/ext/libuv/common.gypi +178 -0
- data/ext/libuv/gyp_uv +73 -0
- data/ext/libuv/include/uv-private/eio.h +403 -0
- data/ext/libuv/include/uv-private/ev.h +838 -0
- data/ext/libuv/include/uv-private/ngx-queue.h +108 -0
- data/ext/libuv/include/uv-private/tree.h +768 -0
- data/ext/libuv/include/uv-private/uv-unix.h +324 -0
- data/ext/libuv/include/uv-private/uv-win.h +517 -0
- data/ext/libuv/include/uv.h +1838 -0
- data/ext/libuv/src/fs-poll.c +235 -0
- data/ext/libuv/src/inet.c +293 -0
- data/ext/libuv/src/unix/async.c +148 -0
- data/ext/libuv/src/unix/core.c +696 -0
- data/ext/libuv/src/unix/cygwin.c +83 -0
- data/ext/libuv/src/unix/darwin.c +342 -0
- data/ext/libuv/src/unix/dl.c +83 -0
- data/ext/libuv/src/unix/eio/Changes +63 -0
- data/ext/libuv/src/unix/eio/LICENSE +36 -0
- data/ext/libuv/src/unix/eio/Makefile.am +15 -0
- data/ext/libuv/src/unix/eio/aclocal.m4 +8957 -0
- data/ext/libuv/src/unix/eio/autogen.sh +3 -0
- data/ext/libuv/src/unix/eio/config.h.in +86 -0
- data/ext/libuv/src/unix/eio/config_cygwin.h +80 -0
- data/ext/libuv/src/unix/eio/config_darwin.h +141 -0
- data/ext/libuv/src/unix/eio/config_freebsd.h +81 -0
- data/ext/libuv/src/unix/eio/config_linux.h +94 -0
- data/ext/libuv/src/unix/eio/config_netbsd.h +81 -0
- data/ext/libuv/src/unix/eio/config_openbsd.h +137 -0
- data/ext/libuv/src/unix/eio/config_sunos.h +84 -0
- data/ext/libuv/src/unix/eio/configure.ac +22 -0
- data/ext/libuv/src/unix/eio/demo.c +194 -0
- data/ext/libuv/src/unix/eio/ecb.h +370 -0
- data/ext/libuv/src/unix/eio/eio.3 +3428 -0
- data/ext/libuv/src/unix/eio/eio.c +2593 -0
- data/ext/libuv/src/unix/eio/eio.pod +969 -0
- data/ext/libuv/src/unix/eio/libeio.m4 +195 -0
- data/ext/libuv/src/unix/eio/xthread.h +164 -0
- data/ext/libuv/src/unix/error.c +105 -0
- data/ext/libuv/src/unix/ev/Changes +388 -0
- data/ext/libuv/src/unix/ev/LICENSE +36 -0
- data/ext/libuv/src/unix/ev/Makefile.am +18 -0
- data/ext/libuv/src/unix/ev/Makefile.in +771 -0
- data/ext/libuv/src/unix/ev/README +58 -0
- data/ext/libuv/src/unix/ev/aclocal.m4 +8957 -0
- data/ext/libuv/src/unix/ev/autogen.sh +6 -0
- data/ext/libuv/src/unix/ev/config.guess +1526 -0
- data/ext/libuv/src/unix/ev/config.h.in +125 -0
- data/ext/libuv/src/unix/ev/config.sub +1658 -0
- data/ext/libuv/src/unix/ev/config_cygwin.h +123 -0
- data/ext/libuv/src/unix/ev/config_darwin.h +122 -0
- data/ext/libuv/src/unix/ev/config_freebsd.h +120 -0
- data/ext/libuv/src/unix/ev/config_linux.h +141 -0
- data/ext/libuv/src/unix/ev/config_netbsd.h +120 -0
- data/ext/libuv/src/unix/ev/config_openbsd.h +126 -0
- data/ext/libuv/src/unix/ev/config_sunos.h +122 -0
- data/ext/libuv/src/unix/ev/configure +13037 -0
- data/ext/libuv/src/unix/ev/configure.ac +18 -0
- data/ext/libuv/src/unix/ev/depcomp +630 -0
- data/ext/libuv/src/unix/ev/ev++.h +816 -0
- data/ext/libuv/src/unix/ev/ev.3 +5311 -0
- data/ext/libuv/src/unix/ev/ev.c +3925 -0
- data/ext/libuv/src/unix/ev/ev.pod +5243 -0
- data/ext/libuv/src/unix/ev/ev_epoll.c +266 -0
- data/ext/libuv/src/unix/ev/ev_kqueue.c +235 -0
- data/ext/libuv/src/unix/ev/ev_poll.c +148 -0
- data/ext/libuv/src/unix/ev/ev_port.c +179 -0
- data/ext/libuv/src/unix/ev/ev_select.c +310 -0
- data/ext/libuv/src/unix/ev/ev_vars.h +203 -0
- data/ext/libuv/src/unix/ev/ev_win32.c +153 -0
- data/ext/libuv/src/unix/ev/ev_wrap.h +196 -0
- data/ext/libuv/src/unix/ev/event.c +402 -0
- data/ext/libuv/src/unix/ev/event.h +170 -0
- data/ext/libuv/src/unix/ev/install-sh +294 -0
- data/ext/libuv/src/unix/ev/libev.m4 +39 -0
- data/ext/libuv/src/unix/ev/ltmain.sh +8413 -0
- data/ext/libuv/src/unix/ev/missing +336 -0
- data/ext/libuv/src/unix/ev/mkinstalldirs +111 -0
- data/ext/libuv/src/unix/freebsd.c +326 -0
- data/ext/libuv/src/unix/fs.c +739 -0
- data/ext/libuv/src/unix/internal.h +188 -0
- data/ext/libuv/src/unix/kqueue.c +120 -0
- data/ext/libuv/src/unix/linux/inotify.c +239 -0
- data/ext/libuv/src/unix/linux/linux-core.c +557 -0
- data/ext/libuv/src/unix/linux/syscalls.c +388 -0
- data/ext/libuv/src/unix/linux/syscalls.h +124 -0
- data/ext/libuv/src/unix/loop-watcher.c +62 -0
- data/ext/libuv/src/unix/loop.c +94 -0
- data/ext/libuv/src/unix/netbsd.c +108 -0
- data/ext/libuv/src/unix/openbsd.c +295 -0
- data/ext/libuv/src/unix/pipe.c +259 -0
- data/ext/libuv/src/unix/poll.c +114 -0
- data/ext/libuv/src/unix/process.c +495 -0
- data/ext/libuv/src/unix/signal.c +269 -0
- data/ext/libuv/src/unix/stream.c +990 -0
- data/ext/libuv/src/unix/sunos.c +481 -0
- data/ext/libuv/src/unix/tcp.c +393 -0
- data/ext/libuv/src/unix/thread.c +251 -0
- data/ext/libuv/src/unix/timer.c +136 -0
- data/ext/libuv/src/unix/tty.c +145 -0
- data/ext/libuv/src/unix/udp.c +659 -0
- data/ext/libuv/src/unix/uv-eio.c +107 -0
- data/ext/libuv/src/unix/uv-eio.h +13 -0
- data/ext/libuv/src/uv-common.c +380 -0
- data/ext/libuv/src/uv-common.h +170 -0
- data/ext/libuv/src/win/async.c +100 -0
- data/ext/libuv/src/win/atomicops-inl.h +56 -0
- data/ext/libuv/src/win/core.c +278 -0
- data/ext/libuv/src/win/dl.c +86 -0
- data/ext/libuv/src/win/error.c +155 -0
- data/ext/libuv/src/win/fs-event.c +510 -0
- data/ext/libuv/src/win/fs.c +1948 -0
- data/ext/libuv/src/win/getaddrinfo.c +365 -0
- data/ext/libuv/src/win/handle-inl.h +149 -0
- data/ext/libuv/src/win/handle.c +154 -0
- data/ext/libuv/src/win/internal.h +343 -0
- data/ext/libuv/src/win/loop-watcher.c +122 -0
- data/ext/libuv/src/win/pipe.c +1672 -0
- data/ext/libuv/src/win/poll.c +616 -0
- data/ext/libuv/src/win/process-stdio.c +500 -0
- data/ext/libuv/src/win/process.c +1013 -0
- data/ext/libuv/src/win/req-inl.h +220 -0
- data/ext/libuv/src/win/req.c +25 -0
- data/ext/libuv/src/win/signal.c +57 -0
- data/ext/libuv/src/win/stream-inl.h +67 -0
- data/ext/libuv/src/win/stream.c +167 -0
- data/ext/libuv/src/win/tcp.c +1394 -0
- data/ext/libuv/src/win/thread.c +372 -0
- data/ext/libuv/src/win/threadpool.c +74 -0
- data/ext/libuv/src/win/timer.c +224 -0
- data/ext/libuv/src/win/tty.c +1799 -0
- data/ext/libuv/src/win/udp.c +716 -0
- data/ext/libuv/src/win/util.c +864 -0
- data/ext/libuv/src/win/winapi.c +132 -0
- data/ext/libuv/src/win/winapi.h +4452 -0
- data/ext/libuv/src/win/winsock.c +557 -0
- data/ext/libuv/src/win/winsock.h +171 -0
- data/ext/libuv/test/benchmark-async-pummel.c +97 -0
- data/ext/libuv/test/benchmark-async.c +137 -0
- data/ext/libuv/test/benchmark-fs-stat.c +135 -0
- data/ext/libuv/test/benchmark-getaddrinfo.c +94 -0
- data/ext/libuv/test/benchmark-list.h +127 -0
- data/ext/libuv/test/benchmark-loop-count.c +88 -0
- data/ext/libuv/test/benchmark-million-timers.c +65 -0
- data/ext/libuv/test/benchmark-ping-pongs.c +213 -0
- data/ext/libuv/test/benchmark-pound.c +324 -0
- data/ext/libuv/test/benchmark-pump.c +462 -0
- data/ext/libuv/test/benchmark-sizes.c +44 -0
- data/ext/libuv/test/benchmark-spawn.c +162 -0
- data/ext/libuv/test/benchmark-tcp-write-batch.c +140 -0
- data/ext/libuv/test/benchmark-thread.c +64 -0
- data/ext/libuv/test/benchmark-udp-packet-storm.c +247 -0
- data/ext/libuv/test/blackhole-server.c +118 -0
- data/ext/libuv/test/dns-server.c +321 -0
- data/ext/libuv/test/echo-server.c +378 -0
- data/ext/libuv/test/fixtures/empty_file +0 -0
- data/ext/libuv/test/fixtures/load_error.node +1 -0
- data/ext/libuv/test/run-benchmarks.c +64 -0
- data/ext/libuv/test/run-tests.c +138 -0
- data/ext/libuv/test/runner-unix.c +295 -0
- data/ext/libuv/test/runner-unix.h +36 -0
- data/ext/libuv/test/runner-win.c +285 -0
- data/ext/libuv/test/runner-win.h +42 -0
- data/ext/libuv/test/runner.c +355 -0
- data/ext/libuv/test/runner.h +159 -0
- data/ext/libuv/test/task.h +112 -0
- data/ext/libuv/test/test-async.c +118 -0
- data/ext/libuv/test/test-callback-order.c +76 -0
- data/ext/libuv/test/test-callback-stack.c +203 -0
- data/ext/libuv/test/test-connection-fail.c +148 -0
- data/ext/libuv/test/test-cwd-and-chdir.c +64 -0
- data/ext/libuv/test/test-delayed-accept.c +188 -0
- data/ext/libuv/test/test-dlerror.c +58 -0
- data/ext/libuv/test/test-error.c +59 -0
- data/ext/libuv/test/test-fail-always.c +29 -0
- data/ext/libuv/test/test-fs-event.c +474 -0
- data/ext/libuv/test/test-fs-poll.c +146 -0
- data/ext/libuv/test/test-fs.c +1843 -0
- data/ext/libuv/test/test-get-currentexe.c +63 -0
- data/ext/libuv/test/test-get-loadavg.c +36 -0
- data/ext/libuv/test/test-get-memory.c +38 -0
- data/ext/libuv/test/test-getaddrinfo.c +122 -0
- data/ext/libuv/test/test-getsockname.c +342 -0
- data/ext/libuv/test/test-hrtime.c +54 -0
- data/ext/libuv/test/test-idle.c +81 -0
- data/ext/libuv/test/test-ipc-send-recv.c +209 -0
- data/ext/libuv/test/test-ipc.c +620 -0
- data/ext/libuv/test/test-list.h +427 -0
- data/ext/libuv/test/test-loop-handles.c +336 -0
- data/ext/libuv/test/test-multiple-listen.c +102 -0
- data/ext/libuv/test/test-mutexes.c +63 -0
- data/ext/libuv/test/test-pass-always.c +28 -0
- data/ext/libuv/test/test-ping-pong.c +253 -0
- data/ext/libuv/test/test-pipe-bind-error.c +140 -0
- data/ext/libuv/test/test-pipe-connect-error.c +96 -0
- data/ext/libuv/test/test-platform-output.c +87 -0
- data/ext/libuv/test/test-poll-close.c +72 -0
- data/ext/libuv/test/test-poll.c +573 -0
- data/ext/libuv/test/test-process-title.c +49 -0
- data/ext/libuv/test/test-ref.c +338 -0
- data/ext/libuv/test/test-run-once.c +48 -0
- data/ext/libuv/test/test-semaphore.c +111 -0
- data/ext/libuv/test/test-shutdown-close.c +103 -0
- data/ext/libuv/test/test-shutdown-eof.c +183 -0
- data/ext/libuv/test/test-signal.c +162 -0
- data/ext/libuv/test/test-spawn.c +863 -0
- data/ext/libuv/test/test-stdio-over-pipes.c +246 -0
- data/ext/libuv/test/test-tcp-bind-error.c +191 -0
- data/ext/libuv/test/test-tcp-bind6-error.c +154 -0
- data/ext/libuv/test/test-tcp-close-while-connecting.c +80 -0
- data/ext/libuv/test/test-tcp-close.c +129 -0
- data/ext/libuv/test/test-tcp-connect-error-after-write.c +95 -0
- data/ext/libuv/test/test-tcp-connect-error.c +70 -0
- data/ext/libuv/test/test-tcp-connect-timeout.c +85 -0
- data/ext/libuv/test/test-tcp-connect6-error.c +68 -0
- data/ext/libuv/test/test-tcp-flags.c +51 -0
- data/ext/libuv/test/test-tcp-shutdown-after-write.c +131 -0
- data/ext/libuv/test/test-tcp-unexpected-read.c +113 -0
- data/ext/libuv/test/test-tcp-write-error.c +168 -0
- data/ext/libuv/test/test-tcp-write-to-half-open-connection.c +135 -0
- data/ext/libuv/test/test-tcp-writealot.c +170 -0
- data/ext/libuv/test/test-thread.c +183 -0
- data/ext/libuv/test/test-threadpool.c +57 -0
- data/ext/libuv/test/test-timer-again.c +141 -0
- data/ext/libuv/test/test-timer.c +152 -0
- data/ext/libuv/test/test-tty.c +110 -0
- data/ext/libuv/test/test-udp-dgram-too-big.c +86 -0
- data/ext/libuv/test/test-udp-ipv6.c +156 -0
- data/ext/libuv/test/test-udp-multicast-join.c +139 -0
- data/ext/libuv/test/test-udp-multicast-ttl.c +86 -0
- data/ext/libuv/test/test-udp-options.c +86 -0
- data/ext/libuv/test/test-udp-send-and-recv.c +208 -0
- data/ext/libuv/test/test-util.c +97 -0
- data/ext/libuv/test/test-walk-handles.c +77 -0
- data/ext/libuv/uv.gyp +375 -0
- data/ext/libuv/vcbuild.bat +105 -0
- data/foolio.gemspec +18 -0
- data/lib/foolio.rb +9 -0
- data/lib/foolio/handle.rb +27 -0
- data/lib/foolio/listener.rb +26 -0
- data/lib/foolio/loop.rb +79 -0
- data/lib/foolio/stream.rb +109 -0
- data/lib/foolio/version.rb +3 -0
- metadata +309 -0
|
@@ -0,0 +1,96 @@
|
|
|
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 "uv.h"
|
|
23
|
+
#include "task.h"
|
|
24
|
+
#include <stdio.h>
|
|
25
|
+
#include <stdlib.h>
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
#ifdef _WIN32
|
|
29
|
+
# define BAD_PIPENAME "bad-pipe"
|
|
30
|
+
#else
|
|
31
|
+
# define BAD_PIPENAME "/path/to/unix/socket/that/really/should/not/be/there"
|
|
32
|
+
#endif
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
static int close_cb_called = 0;
|
|
36
|
+
static int connect_cb_called = 0;
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
static void close_cb(uv_handle_t* handle) {
|
|
40
|
+
ASSERT(handle != NULL);
|
|
41
|
+
close_cb_called++;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
static void connect_cb(uv_connect_t* connect_req, int status) {
|
|
46
|
+
ASSERT(status == -1);
|
|
47
|
+
ASSERT(uv_last_error(uv_default_loop()).code == UV_ENOENT);
|
|
48
|
+
uv_close((uv_handle_t*)connect_req->handle, close_cb);
|
|
49
|
+
connect_cb_called++;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
static void connect_cb_file(uv_connect_t* connect_req, int status) {
|
|
54
|
+
ASSERT(status == -1);
|
|
55
|
+
ASSERT(uv_last_error(uv_default_loop()).code == UV_ENOTSOCK ||
|
|
56
|
+
uv_last_error(uv_default_loop()).code == UV_ECONNREFUSED);
|
|
57
|
+
uv_close((uv_handle_t*)connect_req->handle, close_cb);
|
|
58
|
+
connect_cb_called++;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
TEST_IMPL(pipe_connect_bad_name) {
|
|
63
|
+
uv_pipe_t client;
|
|
64
|
+
uv_connect_t req;
|
|
65
|
+
int r;
|
|
66
|
+
|
|
67
|
+
r = uv_pipe_init(uv_default_loop(), &client, 0);
|
|
68
|
+
ASSERT(r == 0);
|
|
69
|
+
uv_pipe_connect(&req, &client, BAD_PIPENAME, connect_cb);
|
|
70
|
+
|
|
71
|
+
uv_run(uv_default_loop());
|
|
72
|
+
|
|
73
|
+
ASSERT(close_cb_called == 1);
|
|
74
|
+
ASSERT(connect_cb_called == 1);
|
|
75
|
+
|
|
76
|
+
return 0;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
TEST_IMPL(pipe_connect_to_file) {
|
|
81
|
+
const char* path = "test/fixtures/empty_file";
|
|
82
|
+
uv_pipe_t client;
|
|
83
|
+
uv_connect_t req;
|
|
84
|
+
int r;
|
|
85
|
+
|
|
86
|
+
r = uv_pipe_init(uv_default_loop(), &client, 0);
|
|
87
|
+
ASSERT(r == 0);
|
|
88
|
+
uv_pipe_connect(&req, &client, path, connect_cb_file);
|
|
89
|
+
|
|
90
|
+
uv_run(uv_default_loop());
|
|
91
|
+
|
|
92
|
+
ASSERT(close_cb_called == 1);
|
|
93
|
+
ASSERT(connect_cb_called == 1);
|
|
94
|
+
|
|
95
|
+
return 0;
|
|
96
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
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 "uv.h"
|
|
23
|
+
#include "task.h"
|
|
24
|
+
#include <string.h>
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
TEST_IMPL(platform_output) {
|
|
28
|
+
char buffer[512];
|
|
29
|
+
size_t rss;
|
|
30
|
+
double uptime;
|
|
31
|
+
uv_cpu_info_t* cpus;
|
|
32
|
+
uv_interface_address_t* interfaces;
|
|
33
|
+
int count;
|
|
34
|
+
int i;
|
|
35
|
+
uv_err_t err;
|
|
36
|
+
|
|
37
|
+
err = uv_get_process_title(buffer, sizeof(buffer));
|
|
38
|
+
ASSERT(UV_OK == err.code);
|
|
39
|
+
printf("uv_get_process_title: %s\n", buffer);
|
|
40
|
+
|
|
41
|
+
err = uv_resident_set_memory(&rss);
|
|
42
|
+
ASSERT(UV_OK == err.code);
|
|
43
|
+
printf("uv_resident_set_memory: %llu\n", (unsigned long long) rss);
|
|
44
|
+
|
|
45
|
+
err = uv_uptime(&uptime);
|
|
46
|
+
ASSERT(UV_OK == err.code);
|
|
47
|
+
ASSERT(uptime > 0);
|
|
48
|
+
printf("uv_uptime: %f\n", uptime);
|
|
49
|
+
|
|
50
|
+
err = uv_cpu_info(&cpus, &count);
|
|
51
|
+
ASSERT(UV_OK == err.code);
|
|
52
|
+
|
|
53
|
+
printf("uv_cpu_info:\n");
|
|
54
|
+
for (i = 0; i < count; i++) {
|
|
55
|
+
printf(" model: %s\n", cpus[i].model);
|
|
56
|
+
printf(" speed: %d\n", cpus[i].speed);
|
|
57
|
+
printf(" times.sys: %llu\n", (unsigned long long) cpus[i].cpu_times.sys);
|
|
58
|
+
printf(" times.user: %llu\n",
|
|
59
|
+
(unsigned long long) cpus[i].cpu_times.user);
|
|
60
|
+
printf(" times.idle: %llu\n",
|
|
61
|
+
(unsigned long long) cpus[i].cpu_times.idle);
|
|
62
|
+
printf(" times.irq: %llu\n", (unsigned long long) cpus[i].cpu_times.irq);
|
|
63
|
+
printf(" times.nice: %llu\n",
|
|
64
|
+
(unsigned long long) cpus[i].cpu_times.nice);
|
|
65
|
+
}
|
|
66
|
+
uv_free_cpu_info(cpus, count);
|
|
67
|
+
|
|
68
|
+
err = uv_interface_addresses(&interfaces, &count);
|
|
69
|
+
ASSERT(UV_OK == err.code);
|
|
70
|
+
|
|
71
|
+
printf("uv_interface_addresses:\n");
|
|
72
|
+
for (i = 0; i < count; i++) {
|
|
73
|
+
printf(" name: %s\n", interfaces[i].name);
|
|
74
|
+
printf(" internal: %d\n", interfaces[i].is_internal);
|
|
75
|
+
|
|
76
|
+
if (interfaces[i].address.address4.sin_family == AF_INET) {
|
|
77
|
+
uv_ip4_name(&interfaces[i].address.address4, buffer, sizeof(buffer));
|
|
78
|
+
} else if (interfaces[i].address.address4.sin_family == AF_INET6) {
|
|
79
|
+
uv_ip6_name(&interfaces[i].address.address6, buffer, sizeof(buffer));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
printf(" address: %s\n", buffer);
|
|
83
|
+
}
|
|
84
|
+
uv_free_interface_addresses(interfaces, count);
|
|
85
|
+
|
|
86
|
+
return 0;
|
|
87
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
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 <errno.h>
|
|
23
|
+
|
|
24
|
+
#ifndef _WIN32
|
|
25
|
+
# include <fcntl.h>
|
|
26
|
+
# include <sys/socket.h>
|
|
27
|
+
# include <unistd.h>
|
|
28
|
+
#endif
|
|
29
|
+
|
|
30
|
+
#include "uv.h"
|
|
31
|
+
#include "task.h"
|
|
32
|
+
|
|
33
|
+
#define NUM_SOCKETS 64
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
static int close_cb_called = 0;
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
static void close_cb(uv_handle_t* handle) {
|
|
40
|
+
close_cb_called++;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
TEST_IMPL(poll_close) {
|
|
45
|
+
uv_os_sock_t sockets[NUM_SOCKETS];
|
|
46
|
+
uv_poll_t poll_handles[NUM_SOCKETS];
|
|
47
|
+
int i;
|
|
48
|
+
|
|
49
|
+
#ifdef _WIN32
|
|
50
|
+
{
|
|
51
|
+
struct WSAData wsa_data;
|
|
52
|
+
int r = WSAStartup(MAKEWORD(2, 2), &wsa_data);
|
|
53
|
+
ASSERT(r == 0);
|
|
54
|
+
}
|
|
55
|
+
#endif
|
|
56
|
+
|
|
57
|
+
for (i = 0; i < NUM_SOCKETS; i++) {
|
|
58
|
+
sockets[i] = socket(AF_INET, SOCK_STREAM, 0);
|
|
59
|
+
uv_poll_init_socket(uv_default_loop(), &poll_handles[i], sockets[i]);
|
|
60
|
+
uv_poll_start(&poll_handles[i], UV_READABLE | UV_WRITABLE, NULL);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
for (i = 0; i < NUM_SOCKETS; i++) {
|
|
64
|
+
uv_close((uv_handle_t*) &poll_handles[i], close_cb);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
uv_run(uv_default_loop());
|
|
68
|
+
|
|
69
|
+
ASSERT(close_cb_called == NUM_SOCKETS);
|
|
70
|
+
|
|
71
|
+
return 0;
|
|
72
|
+
}
|
|
@@ -0,0 +1,573 @@
|
|
|
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 <errno.h>
|
|
23
|
+
|
|
24
|
+
#ifndef _WIN32
|
|
25
|
+
# include <fcntl.h>
|
|
26
|
+
# include <sys/socket.h>
|
|
27
|
+
# include <unistd.h>
|
|
28
|
+
#endif
|
|
29
|
+
|
|
30
|
+
#include "uv.h"
|
|
31
|
+
#include "task.h"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
#define NUM_CLIENTS 5
|
|
35
|
+
#define TRANSFER_BYTES (1 << 16)
|
|
36
|
+
|
|
37
|
+
#undef MIN
|
|
38
|
+
#define MIN(a, b) (((a) < (b)) ? (a) : (b));
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
typedef enum {
|
|
42
|
+
UNIDIRECTIONAL,
|
|
43
|
+
DUPLEX
|
|
44
|
+
} test_mode_t;
|
|
45
|
+
|
|
46
|
+
typedef struct connection_context_s {
|
|
47
|
+
uv_poll_t poll_handle;
|
|
48
|
+
uv_timer_t timer_handle;
|
|
49
|
+
uv_os_sock_t sock;
|
|
50
|
+
size_t read, sent;
|
|
51
|
+
int is_server_connection;
|
|
52
|
+
int open_handles;
|
|
53
|
+
int got_fin, sent_fin;
|
|
54
|
+
unsigned int events, delayed_events;
|
|
55
|
+
} connection_context_t;
|
|
56
|
+
|
|
57
|
+
typedef struct server_context_s {
|
|
58
|
+
uv_poll_t poll_handle;
|
|
59
|
+
uv_os_sock_t sock;
|
|
60
|
+
int connections;
|
|
61
|
+
} server_context_t;
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
static void delay_timer_cb(uv_timer_t* timer, int status);
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
static test_mode_t test_mode = DUPLEX;
|
|
68
|
+
|
|
69
|
+
static int closed_connections = 0;
|
|
70
|
+
|
|
71
|
+
static int valid_writable_wakeups = 0;
|
|
72
|
+
static int spurious_writable_wakeups = 0;
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
static int got_eagain() {
|
|
76
|
+
#ifdef _WIN32
|
|
77
|
+
return WSAGetLastError() == WSAEWOULDBLOCK;
|
|
78
|
+
#else
|
|
79
|
+
return errno == EAGAIN
|
|
80
|
+
|| errno == EINPROGRESS
|
|
81
|
+
#ifdef EWOULDBLOCK
|
|
82
|
+
|| errno == EWOULDBLOCK;
|
|
83
|
+
#endif
|
|
84
|
+
;
|
|
85
|
+
#endif
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
static void set_nonblocking(uv_os_sock_t sock) {
|
|
90
|
+
int r;
|
|
91
|
+
#ifdef _WIN32
|
|
92
|
+
unsigned long on = 1;
|
|
93
|
+
r = ioctlsocket(sock, FIONBIO, &on);
|
|
94
|
+
ASSERT(r == 0);
|
|
95
|
+
#else
|
|
96
|
+
int flags = fcntl(sock, F_GETFL, 0);
|
|
97
|
+
ASSERT(flags >= 0);
|
|
98
|
+
r = fcntl(sock, F_SETFL, flags | O_NONBLOCK);
|
|
99
|
+
ASSERT(r >= 0);
|
|
100
|
+
#endif
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
static uv_os_sock_t create_nonblocking_bound_socket(
|
|
105
|
+
struct sockaddr_in bind_addr) {
|
|
106
|
+
uv_os_sock_t sock;
|
|
107
|
+
int r;
|
|
108
|
+
|
|
109
|
+
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
|
|
110
|
+
#ifdef _WIN32
|
|
111
|
+
ASSERT(sock != INVALID_SOCKET);
|
|
112
|
+
#else
|
|
113
|
+
ASSERT(sock >= 0);
|
|
114
|
+
#endif
|
|
115
|
+
|
|
116
|
+
set_nonblocking(sock);
|
|
117
|
+
|
|
118
|
+
#ifndef _WIN32
|
|
119
|
+
{
|
|
120
|
+
/* Allow reuse of the port. */
|
|
121
|
+
int yes = 1;
|
|
122
|
+
r = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes);
|
|
123
|
+
ASSERT(r == 0);
|
|
124
|
+
}
|
|
125
|
+
#endif
|
|
126
|
+
|
|
127
|
+
r = bind(sock, (const struct sockaddr*) &bind_addr, sizeof bind_addr);
|
|
128
|
+
ASSERT(r == 0);
|
|
129
|
+
|
|
130
|
+
return sock;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
static void close_socket(uv_os_sock_t sock) {
|
|
135
|
+
int r;
|
|
136
|
+
#ifdef _WIN32
|
|
137
|
+
r = closesocket(sock);
|
|
138
|
+
#else
|
|
139
|
+
r = close(sock);
|
|
140
|
+
#endif
|
|
141
|
+
ASSERT(r == 0);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
static connection_context_t* create_connection_context(
|
|
146
|
+
uv_os_sock_t sock, int is_server_connection) {
|
|
147
|
+
int r;
|
|
148
|
+
connection_context_t* context;
|
|
149
|
+
|
|
150
|
+
context = (connection_context_t*) malloc(sizeof *context);
|
|
151
|
+
ASSERT(context != NULL);
|
|
152
|
+
|
|
153
|
+
context->sock = sock;
|
|
154
|
+
context->is_server_connection = is_server_connection;
|
|
155
|
+
context->read = 0;
|
|
156
|
+
context->sent = 0;
|
|
157
|
+
context->open_handles = 0;
|
|
158
|
+
context->events = 0;
|
|
159
|
+
context->delayed_events = 0;
|
|
160
|
+
context->got_fin = 0;
|
|
161
|
+
context->sent_fin = 0;
|
|
162
|
+
|
|
163
|
+
r = uv_poll_init_socket(uv_default_loop(), &context->poll_handle, sock);
|
|
164
|
+
context->open_handles++;
|
|
165
|
+
context->poll_handle.data = context;
|
|
166
|
+
ASSERT(r == 0);
|
|
167
|
+
|
|
168
|
+
r = uv_timer_init(uv_default_loop(), &context->timer_handle);
|
|
169
|
+
context->open_handles++;
|
|
170
|
+
context->timer_handle.data = context;
|
|
171
|
+
ASSERT(r == 0);
|
|
172
|
+
|
|
173
|
+
return context;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
static void connection_close_cb(uv_handle_t* handle) {
|
|
178
|
+
connection_context_t* context = (connection_context_t*) handle->data;
|
|
179
|
+
|
|
180
|
+
if (--context->open_handles == 0) {
|
|
181
|
+
if (test_mode == DUPLEX || context->is_server_connection) {
|
|
182
|
+
ASSERT(context->read == TRANSFER_BYTES);
|
|
183
|
+
} else {
|
|
184
|
+
ASSERT(context->read == 0);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (test_mode == DUPLEX || !context->is_server_connection) {
|
|
188
|
+
ASSERT(context->sent == TRANSFER_BYTES);
|
|
189
|
+
} else {
|
|
190
|
+
ASSERT(context->sent == 0);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
closed_connections++;
|
|
194
|
+
|
|
195
|
+
free(context);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
static void destroy_connection_context(connection_context_t* context) {
|
|
201
|
+
uv_close((uv_handle_t*) &context->poll_handle, connection_close_cb);
|
|
202
|
+
uv_close((uv_handle_t*) &context->timer_handle, connection_close_cb);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
static void connection_poll_cb(uv_poll_t* handle, int status, int events) {
|
|
207
|
+
connection_context_t* context = (connection_context_t*) handle->data;
|
|
208
|
+
int new_events;
|
|
209
|
+
int r;
|
|
210
|
+
|
|
211
|
+
ASSERT(status == 0);
|
|
212
|
+
ASSERT(events & context->events);
|
|
213
|
+
ASSERT(!(events & ~context->events));
|
|
214
|
+
|
|
215
|
+
new_events = context->events;
|
|
216
|
+
|
|
217
|
+
if (events & UV_READABLE) {
|
|
218
|
+
int action = rand() % 7;
|
|
219
|
+
|
|
220
|
+
switch (action) {
|
|
221
|
+
case 0:
|
|
222
|
+
case 1: {
|
|
223
|
+
/* Read a couple of bytes. */
|
|
224
|
+
static char buffer[74];
|
|
225
|
+
r = recv(context->sock, buffer, sizeof buffer, 0);
|
|
226
|
+
ASSERT(r >= 0);
|
|
227
|
+
|
|
228
|
+
if (r > 0) {
|
|
229
|
+
context->read += r;
|
|
230
|
+
} else {
|
|
231
|
+
/* Got FIN. */
|
|
232
|
+
context->got_fin = 1;
|
|
233
|
+
new_events &= ~UV_READABLE;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
case 2:
|
|
240
|
+
case 3: {
|
|
241
|
+
/* Read until EAGAIN. */
|
|
242
|
+
static char buffer[931];
|
|
243
|
+
r = recv(context->sock, buffer, sizeof buffer, 0);
|
|
244
|
+
ASSERT(r >= 0);
|
|
245
|
+
|
|
246
|
+
while (r > 0) {
|
|
247
|
+
context->read += r;
|
|
248
|
+
r = recv(context->sock, buffer, sizeof buffer, 0);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if (r == 0) {
|
|
252
|
+
/* Got FIN. */
|
|
253
|
+
context->got_fin = 1;
|
|
254
|
+
new_events &= ~UV_READABLE;
|
|
255
|
+
} else {
|
|
256
|
+
ASSERT(got_eagain());
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
break;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
case 4:
|
|
263
|
+
/* Ignore. */
|
|
264
|
+
break;
|
|
265
|
+
|
|
266
|
+
case 5:
|
|
267
|
+
/* Stop reading for a while. Restart in timer callback. */
|
|
268
|
+
new_events &= ~UV_READABLE;
|
|
269
|
+
if (!uv_is_active((uv_handle_t*) &context->timer_handle)) {
|
|
270
|
+
context->delayed_events = UV_READABLE;
|
|
271
|
+
uv_timer_start(&context->timer_handle, delay_timer_cb, 10, 0);
|
|
272
|
+
} else {
|
|
273
|
+
context->delayed_events |= UV_READABLE;
|
|
274
|
+
}
|
|
275
|
+
break;
|
|
276
|
+
|
|
277
|
+
case 6:
|
|
278
|
+
/* Fudge with the event mask. */
|
|
279
|
+
uv_poll_start(&context->poll_handle, UV_WRITABLE, connection_poll_cb);
|
|
280
|
+
uv_poll_start(&context->poll_handle, UV_READABLE, connection_poll_cb);
|
|
281
|
+
context->events = UV_READABLE;
|
|
282
|
+
break;
|
|
283
|
+
|
|
284
|
+
default:
|
|
285
|
+
ASSERT(0);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (events & UV_WRITABLE) {
|
|
290
|
+
if (context->sent < TRANSFER_BYTES &&
|
|
291
|
+
!(test_mode == UNIDIRECTIONAL && context->is_server_connection)) {
|
|
292
|
+
/* We have to send more bytes. */
|
|
293
|
+
int action = rand() % 7;
|
|
294
|
+
|
|
295
|
+
switch (action) {
|
|
296
|
+
case 0:
|
|
297
|
+
case 1: {
|
|
298
|
+
/* Send a couple of bytes. */
|
|
299
|
+
static char buffer[103];
|
|
300
|
+
|
|
301
|
+
int send_bytes = MIN(TRANSFER_BYTES - context->sent, sizeof buffer);
|
|
302
|
+
ASSERT(send_bytes > 0);
|
|
303
|
+
|
|
304
|
+
r = send(context->sock, buffer, send_bytes, 0);
|
|
305
|
+
|
|
306
|
+
if (r < 0) {
|
|
307
|
+
ASSERT(got_eagain());
|
|
308
|
+
spurious_writable_wakeups++;
|
|
309
|
+
break;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
ASSERT(r > 0);
|
|
313
|
+
context->sent += r;
|
|
314
|
+
valid_writable_wakeups++;
|
|
315
|
+
break;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
case 2:
|
|
319
|
+
case 3: {
|
|
320
|
+
/* Send until EAGAIN. */
|
|
321
|
+
static char buffer[1234];
|
|
322
|
+
|
|
323
|
+
int send_bytes = MIN(TRANSFER_BYTES - context->sent, sizeof buffer);
|
|
324
|
+
ASSERT(send_bytes > 0);
|
|
325
|
+
|
|
326
|
+
r = send(context->sock, buffer, send_bytes, 0);
|
|
327
|
+
|
|
328
|
+
if (r < 0) {
|
|
329
|
+
ASSERT(got_eagain());
|
|
330
|
+
spurious_writable_wakeups++;
|
|
331
|
+
break;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
ASSERT(r > 0);
|
|
335
|
+
valid_writable_wakeups++;
|
|
336
|
+
context->sent += r;
|
|
337
|
+
|
|
338
|
+
while (context->sent < TRANSFER_BYTES) {
|
|
339
|
+
send_bytes = MIN(TRANSFER_BYTES - context->sent, sizeof buffer);
|
|
340
|
+
ASSERT(send_bytes > 0);
|
|
341
|
+
|
|
342
|
+
r = send(context->sock, buffer, send_bytes, 0);
|
|
343
|
+
|
|
344
|
+
if (r <= 0) break;
|
|
345
|
+
context->sent += r;
|
|
346
|
+
}
|
|
347
|
+
ASSERT(r > 0 || got_eagain());
|
|
348
|
+
break;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
case 4:
|
|
352
|
+
/* Ignore. */
|
|
353
|
+
break;
|
|
354
|
+
|
|
355
|
+
case 5:
|
|
356
|
+
/* Stop sending for a while. Restart in timer callback. */
|
|
357
|
+
new_events &= ~UV_WRITABLE;
|
|
358
|
+
if (!uv_is_active((uv_handle_t*) &context->timer_handle)) {
|
|
359
|
+
context->delayed_events = UV_WRITABLE;
|
|
360
|
+
uv_timer_start(&context->timer_handle, delay_timer_cb, 100, 0);
|
|
361
|
+
} else {
|
|
362
|
+
context->delayed_events |= UV_WRITABLE;
|
|
363
|
+
}
|
|
364
|
+
break;
|
|
365
|
+
|
|
366
|
+
case 6:
|
|
367
|
+
/* Fudge with the event mask. */
|
|
368
|
+
uv_poll_start(&context->poll_handle,
|
|
369
|
+
UV_READABLE,
|
|
370
|
+
connection_poll_cb);
|
|
371
|
+
uv_poll_start(&context->poll_handle,
|
|
372
|
+
UV_WRITABLE,
|
|
373
|
+
connection_poll_cb);
|
|
374
|
+
context->events = UV_WRITABLE;
|
|
375
|
+
break;
|
|
376
|
+
|
|
377
|
+
default:
|
|
378
|
+
ASSERT(0);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
} else {
|
|
382
|
+
/* Nothing more to write. Send FIN. */
|
|
383
|
+
int r;
|
|
384
|
+
#ifdef _WIN32
|
|
385
|
+
r = shutdown(context->sock, SD_SEND);
|
|
386
|
+
#else
|
|
387
|
+
r = shutdown(context->sock, SHUT_WR);
|
|
388
|
+
#endif
|
|
389
|
+
ASSERT(r == 0);
|
|
390
|
+
context->sent_fin = 1;
|
|
391
|
+
new_events &= ~UV_WRITABLE;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
if (context->got_fin && context->sent_fin) {
|
|
396
|
+
/* Sent and received FIN. Close and destroy context. */
|
|
397
|
+
close_socket(context->sock);
|
|
398
|
+
destroy_connection_context(context);
|
|
399
|
+
context->events = 0;
|
|
400
|
+
|
|
401
|
+
} else if (new_events != context->events) {
|
|
402
|
+
/* Poll mask changed. Call uv_poll_start again. */
|
|
403
|
+
context->events = new_events;
|
|
404
|
+
uv_poll_start(handle, new_events, connection_poll_cb);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/* Assert that uv_is_active works correctly for poll handles. */
|
|
408
|
+
if (context->events != 0) {
|
|
409
|
+
ASSERT(uv_is_active((uv_handle_t*) handle));
|
|
410
|
+
} else {
|
|
411
|
+
ASSERT(!uv_is_active((uv_handle_t*) handle));
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
static void delay_timer_cb(uv_timer_t* timer, int status) {
|
|
417
|
+
connection_context_t* context = (connection_context_t*) timer->data;
|
|
418
|
+
int r;
|
|
419
|
+
|
|
420
|
+
/* Timer should auto stop. */
|
|
421
|
+
ASSERT(!uv_is_active((uv_handle_t*) timer));
|
|
422
|
+
|
|
423
|
+
/* Add the requested events to the poll mask. */
|
|
424
|
+
ASSERT(context->delayed_events != 0);
|
|
425
|
+
context->events |= context->delayed_events;
|
|
426
|
+
context->delayed_events = 0;
|
|
427
|
+
|
|
428
|
+
r = uv_poll_start(&context->poll_handle,
|
|
429
|
+
context->events,
|
|
430
|
+
connection_poll_cb);
|
|
431
|
+
ASSERT(r == 0);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
static server_context_t* create_server_context(
|
|
436
|
+
uv_os_sock_t sock) {
|
|
437
|
+
int r;
|
|
438
|
+
server_context_t* context;
|
|
439
|
+
|
|
440
|
+
context = (server_context_t*) malloc(sizeof *context);
|
|
441
|
+
ASSERT(context != NULL);
|
|
442
|
+
|
|
443
|
+
context->sock = sock;
|
|
444
|
+
context->connections = 0;
|
|
445
|
+
|
|
446
|
+
r = uv_poll_init_socket(uv_default_loop(), &context->poll_handle, sock);
|
|
447
|
+
context->poll_handle.data = context;
|
|
448
|
+
ASSERT(r == 0);
|
|
449
|
+
|
|
450
|
+
return context;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
static void server_close_cb(uv_handle_t* handle) {
|
|
455
|
+
server_context_t* context = (server_context_t*) handle->data;
|
|
456
|
+
free(context);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
static void destroy_server_context(server_context_t* context) {
|
|
461
|
+
uv_close((uv_handle_t*) &context->poll_handle, server_close_cb);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
static void server_poll_cb(uv_poll_t* handle, int status, int events) {
|
|
466
|
+
server_context_t* server_context = (server_context_t*)
|
|
467
|
+
handle->data;
|
|
468
|
+
connection_context_t* connection_context;
|
|
469
|
+
struct sockaddr_in addr;
|
|
470
|
+
socklen_t addr_len;
|
|
471
|
+
uv_os_sock_t sock;
|
|
472
|
+
int r;
|
|
473
|
+
|
|
474
|
+
addr_len = sizeof addr;
|
|
475
|
+
sock = accept(server_context->sock, (struct sockaddr*) &addr, &addr_len);
|
|
476
|
+
#ifdef _WIN32
|
|
477
|
+
ASSERT(sock != INVALID_SOCKET);
|
|
478
|
+
#else
|
|
479
|
+
ASSERT(sock >= 0);
|
|
480
|
+
#endif
|
|
481
|
+
|
|
482
|
+
set_nonblocking(sock);
|
|
483
|
+
|
|
484
|
+
connection_context = create_connection_context(sock, 1);
|
|
485
|
+
connection_context->events = UV_READABLE | UV_WRITABLE;
|
|
486
|
+
r = uv_poll_start(&connection_context->poll_handle,
|
|
487
|
+
UV_READABLE | UV_WRITABLE,
|
|
488
|
+
connection_poll_cb);
|
|
489
|
+
ASSERT(r == 0);
|
|
490
|
+
|
|
491
|
+
if (++server_context->connections == NUM_CLIENTS) {
|
|
492
|
+
close_socket(server_context->sock);
|
|
493
|
+
destroy_server_context(server_context);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
|
|
498
|
+
static void start_server() {
|
|
499
|
+
uv_os_sock_t sock;
|
|
500
|
+
server_context_t* context;
|
|
501
|
+
int r;
|
|
502
|
+
|
|
503
|
+
sock = create_nonblocking_bound_socket(uv_ip4_addr("127.0.0.1", TEST_PORT));
|
|
504
|
+
context = create_server_context(sock);
|
|
505
|
+
|
|
506
|
+
r = listen(sock, 100);
|
|
507
|
+
ASSERT(r == 0);
|
|
508
|
+
|
|
509
|
+
r = uv_poll_start(&context->poll_handle, UV_READABLE, server_poll_cb);
|
|
510
|
+
ASSERT(r == 0);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
static void start_client() {
|
|
515
|
+
uv_os_sock_t sock;
|
|
516
|
+
connection_context_t* context;
|
|
517
|
+
struct sockaddr_in server_addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
|
|
518
|
+
int r;
|
|
519
|
+
|
|
520
|
+
sock = create_nonblocking_bound_socket(uv_ip4_addr("0.0.0.0", 0));
|
|
521
|
+
context = create_connection_context(sock, 0);
|
|
522
|
+
|
|
523
|
+
context->events = UV_READABLE | UV_WRITABLE;
|
|
524
|
+
r = uv_poll_start(&context->poll_handle,
|
|
525
|
+
UV_READABLE | UV_WRITABLE,
|
|
526
|
+
connection_poll_cb);
|
|
527
|
+
ASSERT(r == 0);
|
|
528
|
+
|
|
529
|
+
r = connect(sock, (struct sockaddr*) &server_addr, sizeof server_addr);
|
|
530
|
+
ASSERT(r == 0 || got_eagain());
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
static void start_poll_test() {
|
|
535
|
+
int i, r;
|
|
536
|
+
|
|
537
|
+
#ifdef _WIN32
|
|
538
|
+
{
|
|
539
|
+
struct WSAData wsa_data;
|
|
540
|
+
int r = WSAStartup(MAKEWORD(2, 2), &wsa_data);
|
|
541
|
+
ASSERT(r == 0);
|
|
542
|
+
}
|
|
543
|
+
#endif
|
|
544
|
+
|
|
545
|
+
start_server();
|
|
546
|
+
|
|
547
|
+
for (i = 0; i < NUM_CLIENTS; i++)
|
|
548
|
+
start_client();
|
|
549
|
+
|
|
550
|
+
r = uv_run(uv_default_loop());
|
|
551
|
+
ASSERT(r == 0);
|
|
552
|
+
|
|
553
|
+
/* Assert that at most five percent of the writable wakeups was spurious. */
|
|
554
|
+
ASSERT(spurious_writable_wakeups == 0 ||
|
|
555
|
+
(valid_writable_wakeups + spurious_writable_wakeups) /
|
|
556
|
+
spurious_writable_wakeups > 20);
|
|
557
|
+
|
|
558
|
+
ASSERT(closed_connections == NUM_CLIENTS * 2);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
TEST_IMPL(poll_duplex) {
|
|
563
|
+
test_mode = DUPLEX;
|
|
564
|
+
start_poll_test();
|
|
565
|
+
return 0;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
|
|
569
|
+
TEST_IMPL(poll_unidirectional) {
|
|
570
|
+
test_mode = UNIDIRECTIONAL;
|
|
571
|
+
start_poll_test();
|
|
572
|
+
return 0;
|
|
573
|
+
}
|