diff --git a/README.md b/README.md index c2abb91..74ad135 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ uvbook ====== -An Introduction to libuv +An Introduction to libuv: + +Now maintained at . diff --git a/libuv/.gitignore b/libuv/.gitignore deleted file mode 100644 index 1eaaca8..0000000 --- a/libuv/.gitignore +++ /dev/null @@ -1,72 +0,0 @@ -*.swp -*.[oa] -*.l[oa] -*.opensdf -*.orig -*.pyc -*.sdf -*.suo -core -vgcore.* -.buildstamp -.dirstamp -.deps/ -/.libs/ -/aclocal.m4 -/ar-lib -/autom4te.cache/ -/compile -/config.guess -/config.log -/config.status -/config.sub -/configure -/depcomp -/install-sh -/libtool -/libuv.a -/libuv.dylib -/libuv.pc -/libuv.so -/ltmain.sh -/missing -/test-driver -Makefile -Makefile.in - -# Generated by gyp for android -*.target.mk - -/out/ -/build/gyp - -/test/.libs/ -/test/run-tests -/test/run-tests.exe -/test/run-tests.dSYM -/test/run-benchmarks -/test/run-benchmarks.exe -/test/run-benchmarks.dSYM - -*.sln -*.sln.cache -*.ncb -*.vcproj -*.vcproj*.user -*.vcxproj -*.vcxproj.filters -*.vcxproj.user -_UpgradeReport_Files/ -UpgradeLog*.XML -Debug -Release -ipch - -# sphinx generated files -/docs/build/ - -*.xcodeproj -*.xcworkspace - -# make dist output -libuv-*.tar.* diff --git a/libuv/.mailmap b/libuv/.mailmap deleted file mode 100644 index 3a350a4..0000000 --- a/libuv/.mailmap +++ /dev/null @@ -1,32 +0,0 @@ -Aaron Bieber -Alan Gutierrez -Andrius Bentkus -Bert Belder -Bert Belder -Brandon Philips -Brian White -Brian White -Caleb James DeLisle -Christoph Iserlohn -Fedor Indutny -Frank Denis -Isaac Z. Schlueter -Justin Venus -Keno Fischer -Keno Fischer -Leonard Hecker -Maciej Małecki -Marc Schlaich -Rasmus Christian Pedersen -Rasmus Christian Pedersen -Robert Mustacchi -Ryan Dahl -Ryan Emery -Sam Roberts -San-Tai Hsu -Saúl Ibarra Corretgé -Shigeki Ohtsu -Timothy J. Fontaine -Yasuhiro Matsumoto -Yazhong Liu -Yuki Okumura diff --git a/libuv/AUTHORS b/libuv/AUTHORS deleted file mode 100644 index ee6595d..0000000 --- a/libuv/AUTHORS +++ /dev/null @@ -1,182 +0,0 @@ -# Authors ordered by first contribution. -Ryan Dahl -Bert Belder -Josh Roesslein -Alan Gutierrez -Joshua Peek -Igor Zinkovsky -San-Tai Hsu -Ben Noordhuis -Henry Rawas -Robert Mustacchi -Matt Stevens -Paul Querna -Shigeki Ohtsu -Tom Hughes -Peter Bright -Jeroen Janssen -Andrea Lattuada -Augusto Henrique Hentz -Clifford Heath -Jorge Chamorro Bieling -Luis Lavena -Matthew Sporleder -Erick Tryzelaar -Isaac Z. Schlueter -Pieter Noordhuis -Marek Jelen -Fedor Indutny -Saúl Ibarra Corretgé -Felix Geisendörfer -Yuki Okumura -Roman Shtylman -Frank Denis -Carter Allen -Tj Holowaychuk -Shimon Doodkin -Ryan Emery -Bruce Mitchener -Maciej Małecki -Yasuhiro Matsumoto -Daisuke Murase -Paddy Byers -Dan VerWeire -Brandon Benvie -Brandon Philips -Nathan Rajlich -Charlie McConnell -Vladimir Dronnikov -Aaron Bieber -Bulat Shakirzyanov -Brian White -Erik Dubbelboer -Keno Fischer -Ira Cooper -Andrius Bentkus -Iñaki Baz Castillo -Mark Cavage -George Yohng -Xidorn Quan -Roman Neuhauser -Shuhei Tanuma -Bryan Cantrill -Trond Norbye -Tim Holy -Prancesco Pertugio -Leonard Hecker -Andrew Paprocki -Luigi Grilli -Shannen Saez -Artur Adib -Hiroaki Nakamura -Ting-Yu Lin -Stephen Gallagher -Shane Holloway -Andrew Shaffer -Vlad Tudose -Ben Leslie -Tim Bradshaw -Timothy J. Fontaine -Marc Schlaich -Brian Mazza -Elliot Saba -Ben Kelly -Nils Maier -Nicholas Vavilov -Miroslav Bajtoš -Sean Silva -Wynn Wilkes -Andrei Sedoi -Alex Crichton -Brent Cook -Brian Kaisner -Luca Bruno -Reini Urban -Maks Naumov -Sean Farrell -Chris Bank -Geert Jansen -Christoph Iserlohn -Steven Kabbes -Alex Gaynor -huxingyi -Tenor Biel -Andrej Manduch -Joshua Neuheisel -Alexis Campailla -Yazhong Liu -Sam Roberts -River Tarnell -Nathan Sweet -Trevor Norris -Oguz Bastemur -Dylan Cali -Austin Foxley -Benjamin Saunders -Geoffry Song -Rasmus Christian Pedersen -William Light -Oleg Efimov -Lars Gierth -Rasmus Christian Pedersen -Justin Venus -Kristian Evensen -Linus Mårtensson -Navaneeth Kedaram Nambiathan -Yorkie -StarWing -thierry-FreeBSD -Isaiah Norton -Raul Martins -David Capello -Paul Tan -Javier Hernández -Tonis Tiigi -Norio Kobota -李港平 -Chernyshev Viacheslav -Stephen von Takach -JD Ballard -Luka Perkov -Ryan Cole -HungMingWu -Jay Satiro -Leith Bade -Peter Atashian -Tim Cooper -Caleb James DeLisle -Jameson Nash -Graham Lee -Andrew Low -Pavel Platto -Tony Kelman -John Firebaugh -lilohuang -Paul Goldsmith -Julien Gilli -Michael Hudson-Doyle -Recep ASLANTAS -Rob Adams -Zachary Newman -Robin Hahling -Jeff Widman -cjihrig -Tomasz Kołodziejski -Unknown W. Brackets -Emmanuel Odeke -Mikhail Mukovnikov -Thorsten Lorenz -Yuri D'Elia -Manos Nikolaidis -Elijah Andrews -Michael Ira Krufky -Helge Deller -Joey Geralnik -Tim Caswell -Logan Rosen -Kenneth Perry -John Marino -Alexey Melnichuk -Johan Bergström -Alex Mo -Luis Martinez de Bartolome diff --git a/libuv/CONTRIBUTING.md b/libuv/CONTRIBUTING.md deleted file mode 100644 index 332ed11..0000000 --- a/libuv/CONTRIBUTING.md +++ /dev/null @@ -1,166 +0,0 @@ -# CONTRIBUTING - -The libuv project welcomes new contributors. This document will guide you -through the process. - - -### FORK - -Fork the project [on GitHub](https://github.com/libuv/libuv) and check out -your copy. - -``` -$ git clone https://github.com/username/libuv.git -$ cd libuv -$ git remote add upstream https://github.com/libuv/libuv.git -``` - -Now decide if you want your feature or bug fix to go into the master branch -or the stable branch. As a rule of thumb, bug fixes go into the stable branch -while new features go into the master branch. - -The stable branch is effectively frozen; patches that change the libuv -API/ABI or affect the run-time behavior of applications get rejected. - -In case of doubt, open an issue in the [issue tracker][], post your question -to the [libuv mailing list], or contact one of project maintainers -(@bnoordhuis, @piscisaureus, @indutny or @saghul) on [IRC][]. - -Especially do so if you plan to work on something big. Nothing is more -frustrating than seeing your hard work go to waste because your vision -does not align with that of a project maintainers. - - -### BRANCH - -Okay, so you have decided on the proper branch. Create a feature branch -and start hacking: - -``` -$ git checkout -b my-feature-branch -t origin/v1.x -``` - -(Where v1.x is the latest stable branch as of this writing.) - -### CODE - -Please adhere to libuv's code style. In general it follows the conventions from -the [Google C/C++ style guide]. Some of the key points, as well as some -additional guidelines, are enumerated below. - -* Code that is specific to unix-y platforms should be placed in `src/unix`, and - declarations go into `src/uv-unix.h`. - -* Source code that is Windows-specific goes into `src/win`, and related - publicly exported types, functions and macro declarations should generally - be declared in `include/uv-win.h`. - -* Names should be descriptive and concise. - -* All the symbols and types that libuv makes available publicly should be - prefixed with `uv_` (or `UV_` in case of macros). - -* Internal, non-static functions should be prefixed with `uv__`. - -* Use two spaces and no tabs. - -* Lines should be wrapped at 80 characters. - -* Ensure that lines have no trailing whitespace, and use unix-style (LF) line - endings. - -* Use C89-compliant syntax. In other words, variables can only be declared at - the top of a scope (function, if/for/while-block). - -* When writing comments, use properly constructed sentences, including - punctuation. - -* When documenting APIs and/or source code, don't make assumptions or make - implications about race, gender, religion, political orientation or anything - else that isn't relevant to the project. - -* Remember that source code usually gets written once and read often: ensure - the reader doesn't have to make guesses. Make sure that the purpose and inner - logic are either obvious to a reasonably skilled professional, or add a - comment that explains it. - - -### COMMIT - -Make sure git knows your name and email address: - -``` -$ git config --global user.name "J. Random User" -$ git config --global user.email "j.random.user@example.com" -``` - -Writing good commit logs is important. A commit log should describe what -changed and why. Follow these guidelines when writing one: - -1. The first line should be 50 characters or less and contain a short - description of the change prefixed with the name of the changed - subsystem (e.g. "net: add localAddress and localPort to Socket"). -2. Keep the second line blank. -3. Wrap all other lines at 72 columns. - -A good commit log looks like this: - -``` -subsystem: explaining the commit in one line - -Body of commit message is a few lines of text, explaining things -in more detail, possibly giving some background about the issue -being fixed, etc etc. - -The body of the commit message can be several paragraphs, and -please do proper word-wrap and keep columns shorter than about -72 characters or so. That way `git log` will show things -nicely even when it is indented. -``` - -The header line should be meaningful; it is what other people see when they -run `git shortlog` or `git log --oneline`. - -Check the output of `git log --oneline files_that_you_changed` to find out -what subsystem (or subsystems) your changes touch. - - -### REBASE - -Use `git rebase` (not `git merge`) to sync your work from time to time. - -``` -$ git fetch upstream -$ git rebase upstream/v1.x # or upstream/master -``` - - -### TEST - -Bug fixes and features should come with tests. Add your tests in the -`test/` directory. Tests also need to be registered in `test/test-list.h`. -Look at other tests to see how they should be structured (license boilerplate, -the way entry points are declared, etc.). - -Check README.md file to find out how to run the test suite and make sure that -there are no test regressions. - -### PUSH - -``` -$ git push origin my-feature-branch -``` - -Go to https://github.com/username/libuv and select your feature branch. Click -the 'Pull Request' button and fill out the form. - -Pull requests are usually reviewed within a few days. If there are comments -to address, apply your changes in a separate commit and push that to your -feature branch. Post a comment in the pull request afterwards; GitHub does -not send out notifications when you add commits. - - -[issue tracker]: https://github.com/libuv/libuv/issues -[libuv mailing list]: http://groups.google.com/group/libuv -[IRC]: http://webchat.freelibuv.net/?channels=libuv -[Google C/C++ style guide]: http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml diff --git a/libuv/ChangeLog b/libuv/ChangeLog deleted file mode 100644 index 33478b7..0000000 --- a/libuv/ChangeLog +++ /dev/null @@ -1,1880 +0,0 @@ -2015.01.29, Version 1.3.0 (Stable) - -Changes since version 1.2.1: - -* unix, windows: set non-block mode in uv_poll_init (Saúl Ibarra Corretgé) - -* doc: clarify which flags are supported in uv_fs_event_start (Saúl Ibarra - Corretgé) - -* win,unix: move loop functions which have identical implementations (Andrius - Bentkus) - -* doc: explain how the threadpool is allocated (Alex Mo) - -* doc: clarify uv_default_loop (Saúl Ibarra Corretgé) - -* unix: fix implicit declaration compiler warning (Ben Noordhuis) - -* unix: fix long line introduced in commit 94e628fa (Ben Noordhuis) - -* unix, win: add synchronous uv_get{addr,name}info (Saúl Ibarra Corretgé) - -* linux: fix epoll_pwait() regression with < 2.6.19 (Ben Noordhuis) - -* build: compile -D_GNU_SOURCE on linux (Ben Noordhuis) - -* build: use -fvisibility=hidden in autotools build (Ben Noordhuis) - -* fs, pipe: no trailing terminator in exact sized buffers (Andrius Bentkus) - -* style: rename buf to buffer and len to size for consistency (Andrius Bentkus) - -* test: fix test-spawn on MinGW32 (Luis Martinez de Bartolome) - -* win, pipe: fix assertion when destroying timer (Andrius Bentkus) - -* win, unix: add pipe_peername implementation (Andrius Bentkus) - - -2015.01.29, Version 0.10.33 (Stable), 7a2253d33ad8215a26c1b34f1952aee7242dd687 - -Changes since version 0.10.32: - -* linux: fix epoll_pwait() regression with < 2.6.19 (Ben Noordhuis) - -* test: back-port uv_loop_configure() test (Ben Noordhuis) - - -2015.01.15, Version 1.2.1 (Stable), 4ca78e989062a1099dc4b9ad182a98e8374134b1 - -Changes since version 1.2.0: - -* unix: remove unused dtrace file (Saúl Ibarra Corretgé) - -* test: skip TTY select test if /dev/tty can't be opened (Saúl Ibarra Corretgé) - -* doc: clarify the behavior of uv_tty_init (Saúl Ibarra Corretgé) - -* doc: clarify how uv_async_send behaves (Saúl Ibarra Corretgé) - -* build: make dist now generates a full tarball (Johan Bergström) - -* freebsd: make uv_exepath more resilient (Saúl Ibarra Corretgé) - -* unix: make setting the tty mode to the same value a no-op (Saúl Ibarra - Corretgé) - -* win,tcp: support uv_try_write (Bert Belder) - -* test: enable test-tcp-try-write on windows (Bert Belder) - -* win,tty: support uv_try_write (Bert Belder) - -* unix: set non-block mode in uv_{pipe,tcp,udp}_open (Ben Noordhuis) - - -2015.01.06, Version 1.2.0 (Stable), 09f25b13cd149c7981108fc1a75611daf1277f83 - -Changes since version 1.1.0: - -* linux: fix epoll_pwait() sigmask size calculation (Ben Noordhuis) - -* tty: implement binary I/O terminal mode (Yuri D'Elia) - -* test: fix spawn test with autotools build (Ben Noordhuis) - -* test: skip ipv6 tests when ipv6 is not supported (Ben Noordhuis) - -* common: move STATIC_ASSERT to uv-common.h (Alexey Melnichuk) - -* win/thread: store thread handle in a TLS slot (Alexey Melnichuk) - -* unix: fix ttl, multicast ttl and loop options on IPv6 (Saúl Ibarra Corretgé) - -* linux: fix support for preadv/pwritev-less kernels (Ben Noordhuis) - -* unix: make uv_exepath(size=0) return UV_EINVAL (Ben Noordhuis) - -* darwin: fix uv_exepath(smallbuf) UV_EPERM error (Ben Noordhuis) - -* openbsd: fix uv_exepath(smallbuf) UV_EINVAL error (Ben Noordhuis) - -* linux: fix uv_exepath(size=1) UV_EINVAL error (Ben Noordhuis) - -* sunos: preemptively fix uv_exepath(size=1) (Ben Noordhuis) - -* win: fix and clarify comments in winapi.h (Bert Belder) - -* win: make available NtQueryDirectoryFile (Bert Belder) - -* win: add definitions for directory information types (Bert Belder) - -* win: use NtQueryDirectoryFile to implement uv_fs_scandir (Bert Belder) - -* unix: don't unlink unix socket on bind error (Ben Noordhuis) - -* build: fix bad comment in autogen.sh (Ben Noordhuis) - -* build: add AC_PROG_LIBTOOL to configure.ac (Ben Noordhuis) - -* test: skip udp_options6 if there no IPv6 support (Saúl Ibarra Corretgé) - -* win: add definitions for MUI errors mingw lacks (Bert Belder) - -* build: enable warnings in autotools build (Ben Noordhuis) - -* build: remove -Wno-dollar-in-identifier-extension (Ben Noordhuis) - -* build: move flags from Makefile.am to configure.ac (Ben Noordhuis) - - -2015.01.06, Version 0.10.32 (Stable), 378de30c59aef5fdb6d130fa5cfcb0a68fce571c - -Changes since version 0.10.31: - -* linux: fix epoll_pwait() sigmask size calculation (Ben Noordhuis) - - -2014.12.25, Version 1.1.0 (Stable), 9572f3e74a167f59a8017e57ca3ebe91ffd88e18 - -Changes since version 1.0.2: - -* test: test that closing a poll handle doesn't corrupt the stack (Bert Belder) - -* win: fix compilation of tests (Marc Schlaich) - -* Revert "win: keep a reference to AFD_POLL_INFO in cancel poll" (Bert Belder) - -* win: avoid stack corruption when closing a poll handle (Bert Belder) - -* test: fix test-fs-file-loop on Windows (Bert Belder) - -* test: fix test-cwd-and-chdir (Bert Belder) - -* doc: indicate what version uv_loop_configure was added on (Saúl Ibarra - Corretgé) - -* doc: fix sphinx warning (Saúl Ibarra Corretgé) - -* test: skip spawn_setuid_setgid if we get EACCES (Saúl Ibarra Corretgé) - -* test: silence some Clang warnings (Saúl Ibarra Corretgé) - -* test: relax osx_select_many_fds (Saúl Ibarra Corretgé) - -* test: fix compilation warnings when building with Clang (Saúl Ibarra - Corretgé) - -* win: fix autotools build of tests (Luis Lavena) - -* gitignore: ignore Visual Studio files (Marc Schlaich) - -* win: set fallback message if FormatMessage fails (Marc Schlaich) - -* win: fall back to default language in uv_dlerror (Marc Schlaich) - -* test: improve compatibility for dlerror test (Marc Schlaich) - -* test: check dlerror is "no error" in no error case (Marc Schlaich) - -* unix: change uv_cwd not to return a trailing slash (Saúl Ibarra Corretgé) - -* test: fix cwd_and_chdir test on Unix (Saúl Ibarra Corretgé) - -* test: add uv_cwd output to platform_output test (Saúl Ibarra Corretgé) - -* build: fix dragonflybsd autotools build (John Marino) - -* win: scandir use 'ls' for formatting long strings (Kenneth Perry) - -* build: remove clang and gcc_version gyp defines (Ben Noordhuis) - -* unix, windows: don't treat uv_run_mode as a bitmask (Saúl Ibarra Corretgé) - -* unix, windows: fix UV_RUN_ONCE mode if progress was made (Saúl Ibarra - Corretgé) - - -2014.12.25, Version 0.10.31 (Stable), 4dbd27e2219069a6daa769fb37f98673b77b4261 - -Changes since version 0.10.30: - -* test: test that closing a poll handle doesn't corrupt the stack (Bert Belder) - -* win: fix compilation of tests (Marc Schlaich) - -* Revert "win: keep a reference to AFD_POLL_INFO in cancel poll" (Bert Belder) - -* win: avoid stack corruption when closing a poll handle (Bert Belder) - -* gitignore: ignore Visual Studio files (Marc Schlaich) - -* win: set fallback message if FormatMessage fails (Marc Schlaich) - -* win: fall back to default language in uv_dlerror (Marc Schlaich) - -* test: improve compatibility for dlerror test (Marc Schlaich) - -* test: check dlerror is "no error" in no error case (Marc Schlaich) - -* build: link against -pthread (Logan Rosen) - -* win: scandir use 'ls' for formatting long strings (Kenneth Perry) - - -2014.12.10, Version 1.0.2 (Stable), eec671f0059953505f9a3c9aeb7f9f31466dd7cd - -Changes since version 1.0.1: - -* linux: fix sigmask size arg in epoll_pwait() call (Ben Noordhuis) - -* linux: handle O_NONBLOCK != SOCK_NONBLOCK case (Helge Deller) - -* doc: fix spelling (Joey Geralnik) - -* unix, windows: fix typos in comments (Joey Geralnik) - -* test: canonicalize test runner path (Ben Noordhuis) - -* test: fix compilation warnings (Saúl Ibarra Corretgé) - -* test: skip tty test if detected width and height are 0 (Saúl Ibarra Corretgé) - -* doc: update README with IRC channel (Saúl Ibarra Corretgé) - -* Revert "unix: use cfmakeraw() for setting raw TTY mode" (Ben Noordhuis) - -* doc: document how to get result of uv_fs_mkdtemp (Tim Caswell) - -* unix: add flag for blocking SIGPROF during poll (Ben Noordhuis) - -* unix, windows: add uv_loop_configure() function (Ben Noordhuis) - -* win: keep a reference to AFD_POLL_INFO in cancel poll (Marc Schlaich) - -* test: raise fd limit for OSX select test (Saúl Ibarra Corretgé) - -* unix: remove overzealous assert in uv_read_stop (Saúl Ibarra Corretgé) - -* unix: reset the reading flag when a stream gets EOF (Saúl Ibarra Corretgé) - -* unix: stop reading if an error is produced (Saúl Ibarra Corretgé) - -* cleanup: remove all dead assignments (Maciej Małecki) - -* linux: return early if we have no interfaces (Maciej Małecki) - -* cleanup: remove a dead increment (Maciej Małecki) - - -2014.12.10, Version 0.10.30 (Stable), 5a63f5e9546dca482eeebc3054139b21f509f21f - -Changes since version 0.10.29: - -* linux: fix sigmask size arg in epoll_pwait() call (Ben Noordhuis) - -* linux: handle O_NONBLOCK != SOCK_NONBLOCK case (Helge Deller) - -* doc: update project links (Ben Noordhuis) - -* windows: fix compilation of tests (Marc Schlaich) - -* unix: add flag for blocking SIGPROF during poll (Ben Noordhuis) - -* unix, windows: add uv_loop_configure() function (Ben Noordhuis) - -* win: keep a reference to AFD_POLL_INFO in cancel poll (Marc Schlaich) - - -2014.11.27, Version 1.0.1 (Stable), 0a8e81374e861d425b56c45c8599595d848911d2 - -Changes since version 1.0.0: - -* readme: remove Rust from users (Elijah Andrews) - -* doc,build,include: update project links (Ben Noordhuis) - -* doc: fix typo: Strcutures -> Structures (Michael Ira Krufky) - -* unix: fix processing process handles queue (Saúl Ibarra Corretgé) - -* win: replace non-ansi characters in source file (Bert Belder) - - -2014.11.21, Version 1.0.0 (Stable), feb2a9e6947d892f449b2770c4090f7d8c88381b - -Changes since version 1.0.0-rc2: - -* doc: fix git/svn url for gyp repo in README (Emmanuel Odeke) - -* windows: fix fs_read with nbufs > 1 and offset (Unknown W. Brackets) - -* win: add missing IP_ADAPTER_UNICAST_ADDRESS_LH definition for MinGW - (huxingyi) - -* doc: mention homebrew in README (Mikhail Mukovnikov) - -* doc: add learnuv workshop to README (Thorsten Lorenz) - -* doc: fix parameter name in uv_fs_access (Saúl Ibarra Corretgé) - -* unix: use cfmakeraw() for setting raw TTY mode (Yuri D'Elia) - -* win: fix uv_thread_self() (Alexis Campailla) - -* build: add x32 support to gyp build (Ben Noordhuis) - -* build: remove dtrace probes (Ben Noordhuis) - -* doc: fix link in misc.rst (Manos Nikolaidis) - -* mailmap: remove duplicated entries (Saúl Ibarra Corretgé) - -* gyp: fix comment regarding version info location (Saúl Ibarra Corretgé) - - -2014.10.21, Version 1.0.0-rc2 (Pre-release) - -Changes since version 1.0.0-rc1: - -* build: add missing fixtures to distribution tarball (Rob Adams) - -* doc: update references to current stable branch (Zachary Newman) - -* fs: fix readdir on empty directory (Fedor Indutny) - -* fs: rename uv_fs_readdir to uv_fs_scandir (Saúl Ibarra Corretgé) - -* doc: document uv_alloc_cb (Saúl Ibarra Corretgé) - -* doc: add migration guide from version 0.10 (Saúl Ibarra Corretgé) - -* build: add DragonFly BSD support in autotools (Robin Hahling) - -* doc: document missing stream related structures (Saúl Ibarra Corretgé) - -* doc: clarify uv_loop_t.data field lifetime (Saúl Ibarra Corretgé) - -* doc: add documentation for missing functions and structures (Saúl Ibarra - Corretgé) - -* doc: fix punctuation and grammar in README (Jeff Widman) - -* windows: return libuv error codes in uv_poll_init() (cjihrig) - -* unix, windows: add uv_fs_access() (cjihrig) - -* windows: fix netmask detection (Alexis Campailla) - -* unix, windows: don't include null byte in uv_cwd size (Saúl Ibarra Corretgé) - -* unix, windows: add uv_thread_equal (Tomasz Kołodziejski) - -* windows: fix fs_write with nbufs > 1 and offset (Unknown W. Brackets) - - -2014.10.21, Version 0.10.29 (Stable), 2d728542d3790183417f8f122a110693cd85db14 - -Changes since version 0.10.28: - -* darwin: allocate enough space for select() hack (Fedor Indutny) - -* linux: try epoll_pwait if epoll_wait is missing (Michael Hudson-Doyle) - -* windows: map ERROR_INVALID_DRIVE to UV_ENOENT (Saúl Ibarra Corretgé) - - -2014.09.18, Version 1.0.0-rc1 (Unstable), 0c28bbf7b42882853d1799ab96ff68b07f7f8d49 - -Changes since version 0.11.29: - -* windows: improve timer precision (Alexis Campailla) - -* build, gyp: set xcode flags (Recep ASLANTAS) - -* ignore: include m4 files which are created manually (Recep ASLANTAS) - -* build: add m4 for feature/flag-testing (Recep ASLANTAS) - -* ignore: ignore Xcode project and workspace files (Recep ASLANTAS) - -* unix: fix warnings about dollar symbol usage in identifiers (Recep ASLANTAS) - -* unix: fix warnings when loading functions with dlsym (Recep ASLANTAS) - -* linux: try epoll_pwait if epoll_wait is missing (Michael Hudson-Doyle) - -* test: add test for closing and recreating default loop (Saúl Ibarra Corretgé) - -* windows: properly close the default loop (Saúl Ibarra Corretgé) - -* version: add ability to specify a version suffix (Saúl Ibarra Corretgé) - -* doc: add API documentation (Saúl Ibarra Corretgé) - -* test: don't close connection on write error (Trevor Norris) - -* windows: further simplify the code for timers (Saúl Ibarra Corretgé) - -* gyp: remove UNLIMITED_SELECT from dependent define (Fedor Indutny) - -* darwin: allocate enough space for select() hack (Fedor Indutny) - -* unix, windows: don't allow a NULL callback on timers (Saúl Ibarra Corretgé) - -* windows: simplify code in uv_timer_again (Saúl Ibarra Corretgé) - -* test: use less requests on tcp-write-queue-order (Saúl Ibarra Corretgé) - -* unix: stop child process watcher after last one exits (Saúl Ibarra Corretgé) - -* unix: simplify how process handle queue is managed (Saúl Ibarra Corretgé) - -* windows: remove duplicated field (mattn) - -* core: add a reserved field to uv_handle_t and uv_req_t (Saúl Ibarra Corretgé) - -* windows: fix buffer leak after failed udp send (Bert Belder) - -* windows: make sure sockets and handles are reset on close (Saúl Ibarra Corretgé) - -* unix, windows: add uv_fileno (Saúl Ibarra Corretgé) - -* build: use same CFLAGS in autotools build as in gyp (Saúl Ibarra Corretgé) - -* build: remove unneeded define in uv.gyp (Saúl Ibarra Corretgé) - -* test: fix watcher_cross_stop on Windows (Saúl Ibarra Corretgé) - -* unix, windows: move includes for EAI constants (Saúl Ibarra Corretgé) - -* unix: fix exposing EAI_* glibc-isms (Saúl Ibarra Corretgé) - -* unix: fix tcp write after bad connect freezing (Andrius Bentkus) - - -2014.08.20, Version 0.11.29 (Unstable), 35451fed830807095bbae8ef981af004a4b9259e - -Changes since version 0.11.28: - -* windows: make uv_read_stop immediately stop reading (Jameson Nash) - -* windows: fix uv__getaddrinfo_translate_error (Alexis Campailla) - -* netbsd: fix build (Saúl Ibarra Corretgé) - -* unix, windows: add uv_recv_buffer_size and uv_send_buffer_size (Andrius - Bentkus) - -* windows: add support for UNC paths on uv_spawn (Paul Goldsmith) - -* windows: replace use of inet_addr with uv_inet_pton (Saúl Ibarra Corretgé) - -* unix: replace some asserts with returning errors (Andrius Bentkus) - -* windows: use OpenBSD implementation for uv_fs_mkdtemp (Pavel Platto) - -* windows: fix GetNameInfoW error handling (Alexis Campailla) - -* fs: introduce uv_readdir_next() and report types (Fedor Indutny) - -* fs: extend reported types in uv_fs_readdir_next (Saúl Ibarra Corretgé) - -* unix: read on stream even when UV__POLLHUP set. (Julien Gilli) - - -2014.08.08, Version 0.11.28 (Unstable), fc9e2a0bc487b299c0cd3b2c9a23aeb554b5d8d1 - -Changes since version 0.11.27: - -* unix, windows: const-ify handle in uv_udp_getsockname (Rasmus Pedersen) - -* windows: use UV_ECANCELED for aborted TCP writes (Saúl Ibarra Corretgé) - -* windows: add more required environment variables (Jameson Nash) - -* windows: sort environment variables before calling CreateProcess (Jameson - Nash) - -* unix, windows: move uv_loop_close out of assert (John Firebaugh) - -* windows: fix buffer overflow on uv__getnameinfo_work() (lilohuang) - -* windows: add uv_backend_timeout (Jameson Nash) - -* test: disable tcp_close_accept on Windows (Saúl Ibarra Corretgé) - -* windows: read the PATH env var of the child (Alex Crichton) - -* include: avoid using C++ 'template' reserved word (Iñaki Baz Castillo) - -* include: fix version number (Saúl Ibarra Corretgé) - - -2014.07.32, Version 0.11.27 (Unstable), ffe24f955032d060968ea0289af365006afed55e - -Changes since version 0.11.26: - -* unix, windows: use the same threadpool implementation (Saúl Ibarra Corretgé) - -* unix: use struct sockaddr_storage for target UDP addr (Saúl Ibarra Corretgé) - -* doc: add documentation to uv_udp_start_recv (Andrius Bentkus) - -* common: use common uv__count_bufs code (Andrius Bentkus) - -* unix, win: add send_queue_size and send_queue_count to uv_udp_t (Andrius - Bentkus) - -* unix, win: add uv_udp_try_send (Andrius Bentkus) - -* unix: return UV_EAGAIN if uv_try_write cannot write any data (Saúl Ibarra - Corretgé) - -* windows: fix compatibility with cygwin pipes (Jameson Nash) - -* windows: count queued bytes even if request completed immediately (Saúl - Ibarra Corretgé) - -* windows: disable CRT debug handler on MinGW32 (Saúl Ibarra Corretgé) - -* windows: map ERROR_INVALID_DRIVE to UV_ENOENT (Saúl Ibarra Corretgé) - -* unix: try to write immediately in uv_udp_send (Saúl Ibarra Corretgé) - -* unix: remove incorrect assert (Saúl Ibarra Corretgé) - -* openbsd: avoid requiring privileges for uv_resident_set_memory (Aaron Bieber) - -* unix: guarantee write queue cb execution order in streams (Andrius Bentkus) - -* img: add logo files (Saúl Ibarra Corretgé) - -* aix: improve AIX compatibility (Andrew Low) - -* windows: return bind error immediately when implicitly binding (Saúl Ibarra - Corretgé) - -* windows: don't use atexit for cleaning up the threadpool (Saúl Ibarra - Corretgé) - -* windows: destroy work queue elements when colsing a loop (Saúl Ibarra - Corretgé) - -* unix, windows: add uv_fs_mkdtemp (Pavel Platto) - -* build: handle platforms without multiprocessing.synchronize (Saúl Ibarra - Corretgé) - -* windows: change GENERIC_ALL to GENERIC_WRITE in fs__create_junction (Tony - Kelman) - -* windows: relay TCP bind errors via ipc (Alexis Campailla) - - -2014.07.32, Version 0.10.28 (Stable), 9c14b616f5fb84bfd7d45707bab4bbb85894443e - -Changes since version 0.10.27: - -* windows: fix handling closed socket while poll handle is closing (Saúl Ibarra - Corretgé) - -* unix: return system error on EAI_SYSTEM (Saúl Ibarra Corretgé) - -* unix: fix bogus structure field name (Saúl Ibarra Corretgé) - -* darwin: invoke `mach_timebase_info` only once (Fedor Indutny) - - -2014.06.28, Version 0.11.26 (Unstable), 115281a1058c4034d5c5ccedacb667fe3f6327ea - -Changes since version 0.11.25: - -* windows: add VT100 codes ?25l and ?25h (JD Ballard) - -* windows: add invert ANSI (7 / 27) emulation (JD Ballard) - -* unix: fix handling error on UDP socket creation (Saúl Ibarra Corretgé) - -* unix, windows: getnameinfo implementation (Rasmus Pedersen) - -* heap: fix `heap_remove()` (Fedor Indutny) - -* unix, windows: fix parsing scoped IPv6 addresses (Saúl Ibarra Corretgé) - -* windows: fix handling closed socket while poll handle is closing (Saúl Ibarra - Corretgé) - -* thread: barrier functions (Ben Noordhuis) - -* windows: fix PYTHON environment variable usage (Jay Satiro) - -* unix, windows: return system error on EAI_SYSTEM (Saúl Ibarra Corretgé) - -* windows: fix handling closed socket while poll handle is closing (Saúl Ibarra - Corretgé) - -* unix: don't run i/o callbacks after prepare callbacks (Saúl Ibarra Corretgé) - -* windows: add tty unicode support for input (Peter Atashian) - -* header: introduce `uv_loop_size()` (Andrius Bentkus) - -* darwin: invoke `mach_timebase_info` only once (Fedor Indutny) - - -2014.05.02, Version 0.11.25 (Unstable), 2acd544cff7142e06aa3b09ec64b4a33dd9ab996 - -Changes since version 0.11.24: - -* osx: pass const handle pointer to uv___stream_fd (Chernyshev Viacheslav) - -* unix, windows: pass const handle ptr to uv_tcp_get*name (Chernyshev - Viacheslav) - -* common: pass const sockaddr ptr to uv_ip*_name (Chernyshev Viacheslav) - -* unix, windows: validate flags on uv_udp|tcp_bind (Saúl Ibarra Corretgé) - -* unix: handle case when addr is not initialized after recvmsg (Saúl Ibarra - Corretgé) - -* unix, windows: uv_now constness (Rasmus Pedersen) - - -2014.04.15, Version 0.11.24 (Unstable), ed948c29f6e8c290f79325a6f0bc9ef35bcde644 - -Changes since version 0.11.23: - -* linux: reduce file descriptor count of async pipe (Ben Noordhuis) - -* sunos: support IPv6 qualified link-local addresses (Saúl Ibarra Corretgé) - -* windows: fix opening of read-only stdin pipes (Alexis Campailla) - -* windows: Fix an infinite loop in uv_spawn (Alex Crichton) - -* windows: fix console signal handler refcount (李港平) - -* inet: allow scopeid in uv_inet_pton (Fedor Indutny) - - -2014.04.07, Version 0.11.23 (Unstable), e54de537efcacd593f36fcaaf8b4cb9e64313275 - -Changes since version 0.11.22: - -* fs: avoid using readv/writev where possible (Fedor Indutny) - -* mingw: fix build with autotools (Saúl Ibarra Corretgé) - -* bsd: support IPv6 qualified link-local addresses (Saúl Ibarra Corretgé) - -* unix: add UV_HANDLE_IPV6 flag to tcp and udp handles (Saúl Ibarra Corretgé) - -* unix, windows: do not set SO_REUSEADDR by default on udp (Saúl Ibarra - Corretgé) - -* windows: fix check in uv_tty_endgame() (Maks Naumov) - -* unix, windows: add IPv6 support for uv_udp_multicast_interface (Saúl Ibarra - Corretgé) - -* unix: fallback to blocking writes if reopening a tty fails (Saúl Ibarra - Corretgé) - -* unix: fix handling uv__open_cloexec failure (Saúl Ibarra Corretgé) - -* unix, windows: add IPv6 support to uv_udp_set_membership (Saúl Ibarra - Corretgé) - -* unix, windows: removed unused status parameter (Saúl Ibarra Corretgé) - -* android: add support of ifaddrs in android (Javier Hernández) - -* build: fix SunOS and AIX build with autotools (Saúl Ibarra Corretgé) - -* build: freebsd link with libelf if dtrace enabled (Saúl Ibarra Corretgé) - -* stream: do not leak `alloc_cb` buffers on error (Fedor Indutny) - -* unix: fix setting written size on uv_wd (Saúl Ibarra Corretgé) - - -2014.03.11, Version 0.11.22 (Unstable), cd0c19b1d3c56acf0ade7687006e12e75fbda36d - -Changes since version 0.11.21: - -* unix, windows: map ERANGE errno (Saúl Ibarra Corretgé) - -* unix, windows: make uv_cwd be consistent with uv_exepath (Saúl Ibarra - Corretgé) - -* process: remove debug perror() prints (Fedor Indutny) - -* windows: fall back for volume info query (Isaiah Norton) - -* pipe: allow queueing pending handles (Fedor Indutny) - -* windows: fix winsock status codes for address errors (Raul Martins) - -* windows: Remove unused variable from uv__pipe_insert_pending_socket (David - Capello) - -* unix: workaround broken pthread_sigmask on Android (Paul Tan) - -* error: add ENXIO for O_NONBLOCK FIFO open() (Fedor Indutny) - -* freebsd: use accept4, introduced in version 10 (Saúl Ibarra Corretgé) - -* windows: fix warnings of MinGW -Wall -O3 (StarWing) - -* openbsd, osx: fix compilation warning on scandir (Saúl Ibarra Corretgé) - -* linux: always deregister closing fds from epoll (Geoffry Song) - -* unix: reopen tty as /dev/tty (Saúl Ibarra Corretgé) - -* kqueue: invalidate fd in uv_fs_event_t (Fedor Indutny) - - -2014.02.28, Version 0.11.21 (Unstable), 3ef958158ae1019e027ebaa93114160099db5206 - -Changes since version 0.11.20: - -* unix: fix uv_fs_write when using an empty buffer (Saúl Ibarra Corretgé) - -* unix, windows: add assertion in uv_loop_delete (Saúl Ibarra Corretgé) - - -2014.02.27, Version 0.11.20 (Unstable), 88355e081b51c69ee1e2b6b0015a4e3d38bd0579 - -Changes since version 0.11.19: - -* stream: start thread after assignments (Oguz Bastemur) - -* fs: `uv__cloexec()` opened fd (Fedor Indutny) - -* gyp: qualify `library` variable (Fedor Indutny) - -* unix, win: add uv_udp_set_multicast_interface() (Austin Foxley) - -* unix: fix uv_tcp_nodelay return value in case of error (Saúl Ibarra Corretgé) - -* unix: call setgoups before calling setuid/setgid (Saúl Ibarra Corretgé) - -* include: mark close_cb field as private (Saúl Ibarra Corretgé) - -* unix, windows: map EFBIG errno (Saúl Ibarra Corretgé) - -* unix: correct error when calling uv_shutdown twice (Keno Fischer) - -* windows: fix building on MinGW (Alex Crichton) - -* windows: always initialize uv_process_t (Alex Crichton) - -* include: expose libuv version in header files (Saúl Ibarra Corretgé) - -* fs: vectored IO API for filesystem read/write (Benjamin Saunders) - -* windows: freeze in uv_tcp_endgame (Alexis Campailla) - -* sunos: handle rearm errors (Fedor Indutny) - -* unix: use a heap for timers (Ben Noordhuis) - -* linux: always deregister closing fds from epoll (Geoffry Song) - -* linux: include grp.h for setgroups() (William Light) - -* unix, windows: add uv_loop_init and uv_loop_close (Saúl Ibarra Corretgé) - -* unix, windows: add uv_getrusage() function (Oleg Efimov) - -* win: minor error handle fix to uv_pipe_write_impl (Rasmus Pedersen) - -* heap: fix node removal (Keno Fischer) - -* win: fix C99/C++ comment (Rasmus Pedersen) - -* fs: vectored IO API for filesystem read/write (Benjamin Saunders) - -* unix, windows: add uv_pipe_getsockname (Saúl Ibarra Corretgé) - -* unix, windows: map ENOPROTOOPT errno (Saúl Ibarra Corretgé) - -* errno: add ETXTBSY (Fedor Indutny) - -* fsevent: rename filename field to path (Saúl Ibarra Corretgé) - -* unix, windows: add uv_fs_event_getpath (Saúl Ibarra Corretgé) - -* unix, windows: add uv_fs_poll_getpath (Saúl Ibarra Corretgé) - -* unix, windows: map ERANGE errno (Saúl Ibarra Corretgé) - -* unix, windows: set required size on UV_ENOBUFS (Saúl Ibarra Corretgé) - -* unix, windows: clarify what uv_stream_set_blocking does (Saúl Ibarra - Corretgé) - -* fs: use preadv on Linux if available (Brian White) - - -2014.01.30, Version 0.11.19 (Unstable), 336a1825309744f920230ec3e427e78571772347 - -Changes since version 0.11.18: - -* linux: move sscanf() out of the assert() (Trevor Norris) - -* linux: fix C99/C++ comment (Fedor Indutny) - - -2014.05.02, Version 0.10.27 (Stable), 6e24ce23b1e7576059f85a608eca13b766458a01 - -Changes since version 0.10.26: - -* windows: fix console signal handler refcount (Saúl Ibarra Corretgé) - -* win: always leave crit section in get_proc_title (Fedor Indutny) - - -2014.04.07, Version 0.10.26 (Stable), d864907611c25ec986c5e77d4d6d6dee88f26926 - -Changes since version 0.10.25: - -* process: don't close stdio fds during spawn (Tonis Tiigi) - -* build, windows: do not fail on Windows SDK Prompt (Marc Schlaich) - -* build, windows: fix x64 configuration issue (Marc Schlaich) - -* win: fix buffer leak on error in pipe.c (Fedor Indutny) - -* kqueue: invalidate fd in uv_fs_event_t (Fedor Indutny) - -* linux: always deregister closing fds from epoll (Geoffry Song) - -* error: add ENXIO for O_NONBLOCK FIFO open() (Fedor Indutny) - - -2014.02.19, Version 0.10.25 (Stable), d778dc588507588b12b9f9d2905078db542ed751 - -Changes since version 0.10.24: - -* stream: start thread after assignments (Oguz Bastemur) - -* unix: correct error when calling uv_shutdown twice (Saúl Ibarra Corretgé) - -2014.01.30, Version 0.10.24 (Stable), aecd296b6bce9b40f06a61c5c94e43d45ac7308a - -Changes since version 0.10.23: - -* linux: move sscanf() out of the assert() (Trevor Norris) - -* linux: fix C99/C++ comment (Fedor Indutny) - - -2014.01.23, Version 0.11.18 (Unstable), d47962e9d93d4a55a9984623feaf546406c9cdbb - -Changes since version 0.11.17: - -* osx: Fix a possible segfault in uv__io_poll (Alex Crichton) - -* windows: improved handling of invalid FDs (Alexis Campailla) - -* doc: adding ARCHS flag to OS X build command (Nathan Sweet) - -* tcp: reveal bind-time errors before listen (Alexis Campailla) - -* tcp: uv_tcp_dualstack() (Fedor Indutny) - -* linux: relax assumption on /proc/stat parsing (Luca Bruno) - -* openbsd: fix obvious bug in uv_cpu_info (Fedor Indutny) - -* process: close stdio after dup2'ing it (Fedor Indutny) - -* linux: move sscanf() out of the assert() (Trevor Norris) - - -2014.01.23, Version 0.10.23 (Stable), dbd218e699fec8be311d85e4788be9e28ae884f8 - -Changes since version 0.10.22: - -* linux: relax assumption on /proc/stat parsing (Luca Bruno) - -* openbsd: fix obvious bug in uv_cpu_info (Fedor Indutny) - -* process: close stdio after dup2'ing it (Fedor Indutny) - - -2014.01.08, Version 0.10.22 (Stable), f526c90eeff271d9323a9107b9a64a4671fd3103 - -Changes since version 0.10.21: - -* windows: avoid assertion failure when pipe server is closed (Bert Belder) - - -2013.12.32, Version 0.11.17 (Unstable), 589c224d4c2e79fec65db01d361948f1e4976858 - -Changes since version 0.11.16: - -* stream: allow multiple buffers for uv_try_write (Fedor Indutny) - -* unix: fix a possible memory leak in uv_fs_readdir (Alex Crichton) - -* unix, windows: add uv_loop_alive() function (Sam Roberts) - -* windows: avoid assertion failure when pipe server is closed (Bert Belder) - -* osx: Fix a possible segfault in uv__io_poll (Alex Crichton) - -* stream: fix uv__stream_osx_select (Fedor Indutny) - - -2013.12.14, Version 0.11.16 (Unstable), ae0ed8c49d0d313c935c22077511148b6e8408a4 - -Changes since version 0.11.15: - -* fsevents: remove kFSEventStreamCreateFlagNoDefer polyfill (ci-innoq) - -* libuv: add more getaddrinfo errors (Steven Kabbes) - -* unix: fix accept() EMFILE error handling (Ben Noordhuis) - -* linux: fix up SO_REUSEPORT back-port (Ben Noordhuis) - -* fsevents: fix subfolder check (Fedor Indutny) - -* fsevents: fix invalid memory access (huxingyi) - -* windows/timer: fix uv_hrtime discontinuity (Bert Belder) - -* unix: fix various memory leaks and undef behavior (Fedor Indutny) - -* unix, windows: always update loop time (Saúl Ibarra Corretgé) - -* windows: translate system errors in uv_spawn (Alexis Campailla) - -* windows: uv_spawn code refactor (Alexis Campailla) - -* unix, windows: detect errors in uv_ip4/6_addr (Yorkie) - -* stream: introduce uv_try_write(...) (Fedor Indutny) - - -2013.12.13, Version 0.10.20 (Stable), 04141464dd0fba90ace9aa6f7003ce139b888a40 - -Changes since version 0.10.19: - -* linux: fix up SO_REUSEPORT back-port (Ben Noordhuis) - -* fs-event: fix invalid memory access (huxingyi) - - -2013.11.21, Version 0.11.15 (Unstable), bfe645ed7e99ca5670d9279ad472b604c129d2e5 - -Changes since version 0.11.14: - -* fsevents: report errors to user (Fedor Indutny) - -* include: UV_FS_EVENT_RECURSIVE is a flag (Fedor Indutny) - -* linux: use CLOCK_MONOTONIC_COARSE if available (Ben Noordhuis) - -* build: make systemtap probes work with gyp build (Ben Noordhuis) - -* unix: update events from pevents between polls (Fedor Indutny) - -* fsevents: support japaneese characters in path (Chris Bank) - -* linux: don't turn on SO_REUSEPORT socket option (Ben Noordhuis) - -* queue: strengthen type checks (Ben Noordhuis) - -* include: remove uv_strlcat() and uv_strlcpy() (Ben Noordhuis) - -* build: fix windows smp build with gyp (Geert Jansen) - -* unix: return exec errors from uv_spawn, not async (Alex Crichton) - -* fsevents: use native character encoding file paths (Ben Noordhuis) - -* linux: handle EPOLLHUP without EPOLLIN/EPOLLOUT (Ben Noordhuis) - -* windows: use _snwprintf(), not swprintf() (Ben Noordhuis) - -* fsevents: use FlagNoDefer for FSEventStreamCreate (Fedor Indutny) - -* unix: fix reopened fd bug (Fedor Indutny) - -* core: fix fake watcher list and count preservation (Fedor Indutny) - -* unix: set close-on-exec flag on received fds (Ben Noordhuis) - -* netbsd, openbsd: enable futimes() wrapper (Ben Noordhuis) - -* unix: nicer error message when kqueue() fails (Ben Noordhuis) - -* samples: add socks5 proxy sample application (Ben Noordhuis) - - -2013.11.13, Version 0.10.19 (Stable), 33959f7524090b8d2c6c41e2400ca77e31755059 - -Changes since version 0.10.18: - -* darwin: avoid calling GetCurrentProcess (Fedor Indutny) - -* unix: update events from pevents between polls (Fedor Indutny) - -* fsevents: support japaneese characters in path (Chris Bank) - -* linux: don't turn on SO_REUSEPORT socket option (Ben Noordhuis) - -* build: fix windows smp build with gyp (Geert Jansen) - -* linux: handle EPOLLHUP without EPOLLIN/EPOLLOUT (Ben Noordhuis) - -* unix: fix reopened fd bug (Fedor Indutny) - -* core: fix fake watcher list and count preservation (Fedor Indutny) - - -2013.10.30, Version 0.11.14 (Unstable), d7a6482f45c1b4eb4a853dbe1a9ce8090a35633a - -Changes since version 0.11.13: - -* darwin: create fsevents thread on demand (Ben Noordhuis) - -* fsevents: FSEvents is most likely not thread-safe (Fedor Indutny) - -* fsevents: use shared FSEventStream (Fedor Indutny) - -* windows: make uv_fs_chmod() report errors correctly (Bert Belder) - -* windows: make uv_shutdown() for write-only pipes work (Bert Belder) - -* windows/fs: wrap multi-statement macros in do..while block (Bert Belder) - -* windows/fs: make uv_fs_open() report EINVAL correctly (Bert Belder) - -* windows/fs: handle _open_osfhandle() failure correctly (Bert Belder) - -* windows/fs: wrap multi-statement macros in do..while block (Bert Belder) - -* windows/fs: make uv_fs_open() report EINVAL correctly (Bert Belder) - -* windows/fs: handle _open_osfhandle() failure correctly (Bert Belder) - -* build: clarify instructions for Windows (Brian Kaisner) - -* build: remove GCC_WARN_ABOUT_MISSING_NEWLINE (Ben Noordhuis) - -* darwin: fix 10.6 build error in fsevents.c (Ben Noordhuis) - -* windows: run close callbacks after polling for i/o (Saúl Ibarra Corretgé) - -* include: clarify uv_tcp_bind() behavior (Ben Noordhuis) - -* include: clean up includes in uv.h (Ben Noordhuis) - -* include: remove UV_IO_PRIVATE_FIELDS macro (Ben Noordhuis) - -* include: fix typo in comment in uv.h (Ben Noordhuis) - -* include: update uv_is_active() documentation (Ben Noordhuis) - -* include: make uv_process_options_t.cwd const (Ben Noordhuis) - -* unix: wrap long lines at 80 columns (Ben Noordhuis) - -* unix, windows: make uv_is_*() always return 0 or 1 (Ben Noordhuis) - -* bench: measure total/init/dispatch/cleanup times (Ben Noordhuis) - -* build: use -pthread on sunos (Timothy J. Fontaine) - -* windows: remove duplicate check in stream.c (Ben Noordhuis) - -* unix: sanity-check fds before closing (Ben Noordhuis) - -* unix: remove uv__pipe_accept() (Ben Noordhuis) - -* unix: fix uv_spawn() NULL pointer deref on ENOMEM (Ben Noordhuis) - -* unix: don't close inherited fds on uv_spawn() fail (Ben Noordhuis) - -* unix: revert recent FSEvent changes (Ben Noordhuis) - -* fsevents: fix clever rescheduling (Fedor Indutny) - -* linux: ignore fractional time in uv_uptime() (Ben Noordhuis) - -* unix: fix SIGCHLD waitpid() race in process.c (Ben Noordhuis) - -* unix, windows: add uv_fs_event_start/stop functions (Saúl Ibarra Corretgé) - -* unix: fix non-synchronized access in signal.c (Ben Noordhuis) - -* unix: add atomic-ops.h (Ben Noordhuis) - -* unix: add spinlock.h (Ben Noordhuis) - -* unix: clean up uv_tty_set_mode() a little (Ben Noordhuis) - -* unix: make uv_tty_reset_mode() async signal-safe (Ben Noordhuis) - -* include: add E2BIG status code mapping (Ben Noordhuis) - -* windows: fix duplicate case build error (Ben Noordhuis) - -* windows: remove unneeded check (Saúl Ibarra Corretgé) - -* include: document pipe path truncation behavior (Ben Noordhuis) - -* fsevents: increase stack size for OSX 10.9 (Fedor Indutny) - -* windows: _snprintf expected wrong parameter type in string (Maks Naumov) - -* windows: "else" keyword is missing (Maks Naumov) - -* windows: incorrect check for SOCKET_ERROR (Maks Naumov) - -* windows: add stdlib.h to satisfy reference to abort (Sean Farrell) - -* build: fix check target for mingw (Sean Farrell) - -* unix: move uv_shutdown() assertion (Keno Fischer) - -* darwin: avoid calling GetCurrentProcess (Fedor Indutny) - - -2013.10.19, Version 0.10.18 (Stable), 9ec52963b585e822e87bdc5de28d6143aff0d2e5 - -Changes since version 0.10.17: - -* unix: fix uv_spawn() NULL pointer deref on ENOMEM (Ben Noordhuis) - -* unix: don't close inherited fds on uv_spawn() fail (Ben Noordhuis) - -* unix: revert recent FSEvent changes (Ben Noordhuis) - -* unix: fix non-synchronized access in signal.c (Ben Noordhuis) - - -2013.09.25, Version 0.10.17 (Stable), 9670e0a93540c2f0d86c84a375f2303383c11e7e - -Changes since version 0.10.16: - -* build: remove GCC_WARN_ABOUT_MISSING_NEWLINE (Ben Noordhuis) - -* darwin: fix 10.6 build error in fsevents.c (Ben Noordhuis) - - -2013.09.06, Version 0.10.16 (Stable), 2bce230d81f4853a23662cbeb26fe98010b1084b - -Changes since version 0.10.15: - -* windows: make uv_shutdown() for write-only pipes work (Bert Belder) - -* windows: make uv_fs_open() report EINVAL when invalid arguments are passed - (Bert Belder) - -* windows: make uv_fs_open() report _open_osfhandle() failure correctly (Bert - Belder) - -* windows: make uv_fs_chmod() report errors correctly (Bert Belder) - -* windows: wrap multi-statement macros in do..while block (Bert Belder) - - -2013.09.05, Version 0.11.13 (Unstable), f5b6db6c1d7f93d28281207fd47c3841c9a9792e - -Changes since version 0.11.12: - -* unix: define _GNU_SOURCE, exposes glibc-isms (Ben Noordhuis) - -* windows: check for nonconforming swprintf arguments (Brent Cook) - -* build: include internal headers in source list (Brent Cook) - -* include: merge uv_tcp_bind and uv_tcp_bind6 (Ben Noordhuis) - -* include: merge uv_tcp_connect and uv_tcp_connect6 (Ben Noordhuis) - -* include: merge uv_udp_bind and uv_udp_bind6 (Ben Noordhuis) - -* include: merge uv_udp_send and uv_udp_send6 (Ben Noordhuis) - - -2013.09.03, Version 0.11.12 (Unstable), 82d01d5f6780d178f5176a01425ec297583c0811 - -Changes since version 0.11.11: - -* test: fix epoll_wait() usage in test-embed.c (Ben Noordhuis) - -* include: uv_alloc_cb now takes uv_buf_t* (Ben Noordhuis) - -* include: uv_read{2}_cb now takes const uv_buf_t* (Ben Noordhuis) - -* include: uv_ip[46]_addr now takes sockaddr_in* (Ben Noordhuis) - -* include: uv_tcp_bind{6} now takes sockaddr_in* (Ben Noordhuis) - -* include: uv_tcp_connect{6} now takes sockaddr_in* (Ben Noordhuis) - -* include: uv_udp_recv_cb now takes const uv_buf_t* (Ben Noordhuis) - -* include: uv_udp_bind{6} now takes sockaddr_in* (Ben Noordhuis) - -* include: uv_udp_send{6} now takes sockaddr_in* (Ben Noordhuis) - -* include: uv_spawn takes const uv_process_options_t* (Ben Noordhuis) - -* include: make uv_write{2} const correct (Ben Noordhuis) - -* windows: fix flags assignment in uv_fs_readdir() (Ben Noordhuis) - -* windows: fix stray comments (Ben Noordhuis) - -* windows: remove unused is_path_dir() function (Ben Noordhuis) - - -2013.08.30, Version 0.11.11 (Unstable), ba876d53539ed0427c52039012419cd9374c6f0d - -Changes since version 0.11.10: - -* unix, windows: add thread-local storage API (Ben Noordhuis) - -* linux: don't turn on SO_REUSEPORT socket option (Ben Noordhuis) - -* darwin: fix 10.6 build error in fsevents.c (Ben Noordhuis) - -* windows: make uv_shutdown() for write-only pipes work (Bert Belder) - -* include: update uv_udp_open() / uv_udp_bind() docs (Ben Noordhuis) - -* unix: req queue must be empty when destroying loop (Ben Noordhuis) - -* unix: move loop functions from core.c to loop.c (Ben Noordhuis) - -* darwin: remove CoreFoundation dependency (Ben Noordhuis) - -* windows: make autotools build system work with mingw (Keno Fischer) - -* windows: fix mingw build (Alex Crichton) - -* windows: tweak Makefile.mingw for easier usage (Alex Crichton) - -* build: remove _GNU_SOURCE macro definition (Ben Noordhuis) - - -2013.08.25, Version 0.11.10 (Unstable), 742dadcb7154cc7bb89c0c228a223b767a36cf0d - -* windows: Re-implement uv_fs_stat. The st_ctime field now contains the change - time, not the creation time, like on unix systems. st_dev, st_ino, st_blocks - and st_blksize are now also filled out. (Bert Belder) - -* linux: fix setsockopt(SO_REUSEPORT) error handling (Ben Noordhuis) - -* windows: report uv_process_t exit code correctly (Bert Belder) - -* windows: make uv_fs_chmod() report errors correctly (Bert Belder) - -* windows: make some more NT apis available for libuv's internal use (Bert - Belder) - -* windows: squelch some compiler warnings (Bert Belder) - - -2013.08.24, Version 0.11.9 (Unstable), a2d29b5b068cbac93dc16138fb30a74e2669daad - -Changes since version 0.11.8: - -* fsevents: share FSEventStream between multiple FS watchers, which removes a - limit on the maximum number of file watchers that can be created on OS X. - (Fedor Indutny) - -* process: the `exit_status` parameter for a uv_process_t's exit callback now - is an int64_t, and no longer an int. (Bert Belder) - -* process: make uv_spawn() return some types of errors immediately on windows, - instead of passing the error code the the exit callback. This brings it on - par with libuv's behavior on unix. (Bert Belder) - - -2013.08.24, Version 0.10.15 (Stable), 221078a8fdd9b853c6b557b3d9a5dd744b4fdd6b - -Changes since version 0.10.14: - -* fsevents: create FSEvents thread on demand (Ben Noordhuis) - -* fsevents: use a single thread for interacting with FSEvents, because it's not - thread-safe. (Fedor Indutny) - -* fsevents: share FSEventStream between multiple FS watchers, which removes a - limit on the maximum number of file watchers that can be created on OS X. - (Fedor Indutny) - - -2013.08.22, Version 0.11.8 (Unstable), a5260462db80ab0deab6b9e6a8991dd8f5a9a2f8 - -Changes since version 0.11.7: - -* unix: fix missing return value warning in stream.c (Ben Noordhuis) - -* build: serial-tests was added in automake v1.12 (Ben Noordhuis) - -* windows: fix uninitialized local variable warning (Ben Noordhuis) - -* windows: fix missing return value warning (Ben Noordhuis) - -* build: fix string comparisons in autogen.sh (Ben Noordhuis) - -* windows: move INLINE macro, remove UNUSED (Ben Noordhuis) - -* unix: clean up __attribute__((quux)) usage (Ben Noordhuis) - -* sunos: remove futimes() macro (Ben Noordhuis) - -* unix: fix uv__signal_unlock() prototype (Ben Noordhuis) - -* unix, windows: allow NULL async callback (Ben Noordhuis) - -* build: apply dtrace -G to all object files (Timothy J. Fontaine) - -* darwin: fix indentation in uv__hrtime() (Ben Noordhuis) - -* darwin: create fsevents thread on demand (Ben Noordhuis) - -* darwin: reduce fsevents thread stack size (Ben Noordhuis) - -* darwin: call pthread_setname_np() if available (Ben Noordhuis) - -* build: fix automake serial-tests check again (Ben Noordhuis) - -* unix: retry waitpid() on EINTR (Ben Noordhuis) - -* darwin: fix ios build error (Ben Noordhuis) - -* darwin: fix ios compiler warning (Ben Noordhuis) - -* test: simplify test-ip6-addr.c (Ben Noordhuis) - -* unix, windows: fix ipv6 link-local address parsing (Ben Noordhuis) - -* fsevents: FSEvents is most likely not thread-safe (Fedor Indutny) - -* windows: omit stdint.h, fix msvc 2008 build error (Ben Noordhuis) - - -2013.08.22, Version 0.10.14 (Stable), 15d64132151c18b26346afa892444b95e2addad0 - -Changes since version 0.10.13: - -* unix: retry waitpid() on EINTR (Ben Noordhuis) - - -2013.08.07, Version 0.11.7 (Unstable), 3cad361f8776f70941b39d65bd9426bcb1aa817b - -Changes since version 0.11.6: - -* unix, windows: fix uv_fs_chown() function prototype (Ben Noordhuis) - -* unix, windows: remove unused variables (Brian White) - -* test: fix signed/unsigned comparison warnings (Ben Noordhuis) - -* build: dtrace shouldn't break out of tree builds (Timothy J. Fontaine) - -* unix, windows: don't read/recv if buf.len==0 (Ben Noordhuis) - -* build: add mingw makefile (Ben Noordhuis) - -* unix, windows: add MAC to uv_interface_addresses() (Brian White) - -* build: enable AM_INIT_AUTOMAKE([subdir-objects]) (Ben Noordhuis) - -* unix, windows: make buf arg to uv_fs_write const (Ben Noordhuis) - -* sunos: fix build breakage introduced in e3a657c (Ben Noordhuis) - -* aix: fix build breakage introduced in 3ee4d3f (Ben Noordhuis) - -* windows: fix mingw32 build, define JOB_OBJECT_XXX (Yasuhiro Matsumoto) - -* windows: fix mingw32 build, include limits.h (Yasuhiro Matsumoto) - -* test: replace sprintf() with snprintf() (Ben Noordhuis) - -* test: replace strcpy() with strncpy() (Ben Noordhuis) - -* openbsd: fix uv_ip6_addr() unused variable warnings (Ben Noordhuis) - -* openbsd: fix dlerror() const correctness warning (Ben Noordhuis) - -* openbsd: fix uv_fs_sendfile() unused variable warnings (Ben Noordhuis) - -* build: disable parallel automake tests (Ben Noordhuis) - -* test: add windows-only snprintf() function (Ben Noordhuis) - -* build: add automake serial-tests version check (Ben Noordhuis) - - -2013.07.26, Version 0.10.13 (Stable), 381312e1fe6fecbabc943ccd56f0e7d114b3d064 - -Changes since version 0.10.12: - -* unix, windows: fix uv_fs_chown() function prototype (Ben Noordhuis) - - -2013.07.21, Version 0.11.6 (Unstable), 6645b93273e0553d23823c576573b82b129bf28c - -Changes since version 0.11.5: - -* test: open stdout fd in write-only mode (Ben Noordhuis) - -* windows: uv_spawn shouldn't reject reparse points (Bert Belder) - -* windows: use WSAGetLastError(), not errno (Ben Noordhuis) - -* build: darwin: disable -fstrict-aliasing warnings (Ben Noordhuis) - -* test: fix signed/unsigned compiler warning (Ben Noordhuis) - -* test: add 'start timer from check handle' test (Ben Noordhuis) - -* build: `all` now builds static and dynamic lib (Ben Noordhuis) - -* unix, windows: add extra fields to uv_stat_t (Saúl Ibarra Corretgé) - -* build: add install target to the makefile (Navaneeth Kedaram Nambiathan) - -* build: switch to autotools (Ben Noordhuis) - -* build: use AM_PROG_AR conditionally (Ben Noordhuis) - -* test: fix fs_fstat test on sunos (Ben Noordhuis) - -* test: fix fs_chown when running as root (Ben Noordhuis) - -* test: fix spawn_setgid_fails and spawn_setuid_fails (Ben Noordhuis) - -* build: use AM_SILENT_RULES conditionally (Ben Noordhuis) - -* build: add DTrace detection for autotools (Timothy J. Fontaine) - -* linux,darwin,win: link-local IPv6 addresses (Miroslav Bajtoš) - -* unix: fix build when !defined(PTHREAD_MUTEX_ERRORCHECK) (Ben Noordhuis) - -* unix, windows: return error codes directly (Ben Noordhuis) - - -2013.07.10, Version 0.10.12 (Stable), 58a46221bba726746887a661a9f36fe9ff204209 - -Changes since version 0.10.11: - -* linux: add support for MIPS (Andrei Sedoi) - -* windows: uv_spawn shouldn't reject reparse points (Bert Belder) - -* windows: use WSAGetLastError(), not errno (Ben Noordhuis) - -* build: darwin: disable -fstrict-aliasing warnings (Ben Noordhuis) - -* build: `all` now builds static and dynamic lib (Ben Noordhuis) - -* unix: fix build when !defined(PTHREAD_MUTEX_ERRORCHECK) (Ben Noordhuis) - - -2013.06.27, Version 0.11.5 (Unstable), e3c63ff1627a14e96f54c1c62b0d68b446d8425b - -Changes since version 0.11.4: - -* build: remove CSTDFLAG, use only CFLAGS (Ben Noordhuis) - -* unix: support for android builds (Linus Mårtensson) - -* unix: avoid extra read, short-circuit on POLLHUP (Ben Noordhuis) - -* uv: support android libuv standalone build (Linus Mårtensson) - -* src: make queue.h c++ compatible (Ben Noordhuis) - -* unix: s/ngx-queue.h/queue.h/ in checksparse.sh (Ben Noordhuis) - -* unix: unconditionally stop handle on close (Ben Noordhuis) - -* freebsd: don't enable dtrace if it's not available (Brian White) - -* build: make HAVE_DTRACE=0 should disable dtrace (Timothy J. Fontaine) - -* unix: remove overzealous assert (Ben Noordhuis) - -* unix: remove unused function uv_fatal_error() (Ben Noordhuis) - -* unix, windows: clean up uv_thread_create() (Ben Noordhuis) - -* queue: fix pointer truncation on LLP64 platforms (Bert Belder) - -* build: set OS=="android" for android builds (Linus Mårtensson) - -* windows: don't use uppercase in include filename (Ben Noordhuis) - -* stream: add an API to make streams do blocking writes (Henry Rawas) - -* windows: use WSAGetLastError(), not errno (Ben Noordhuis) - - -2013.06.13, Version 0.10.11 (Stable), c3b75406a66a10222a589cb173e8f469e9665c7e - -Changes since version 0.10.10: - -* unix: unconditionally stop handle on close (Ben Noordhuis) - -* freebsd: don't enable dtrace if it's not available (Brian White) - -* build: make HAVE_DTRACE=0 should disable dtrace (Timothy J. Fontaine) - -* unix: remove overzealous assert (Ben Noordhuis) - -* unix: clear UV_STREAM_SHUTTING after shutdown() (Ben Noordhuis) - -* unix: fix busy loop, write if POLLERR or POLLHUP (Ben Noordhuis) - - -2013.06.05, Version 0.10.10 (Stable), 0d95a88bd35fce93863c57a460be613aea34d2c5 - -Changes since version 0.10.9: - -* include: document uv_update_time() and uv_now() (Ben Noordhuis) - -* linux: fix cpu model parsing on newer arm kernels (Ben Noordhuis) - -* linux: fix a memory leak in uv_cpu_info() error path (Ben Noordhuis) - -* linux: don't ignore out-of-memory errors in uv_cpu_info() (Ben Noordhuis) - -* unix, windows: move uv_now() to uv-common.c (Ben Noordhuis) - -* test: fix a compilation problem in test-osx-select.c that was caused by the - use of c-style comments (Bert Belder) - -* darwin: use uv_fs_sendfile() use the sendfile api correctly (Wynn Wilkes) - - -2013.05.30, Version 0.11.4 (Unstable), e43e5b3d954a0989db5588aa110e1fe4fe6e0219 - -Changes since version 0.11.3: - -* windows: make uv_spawn not fail when the libuv embedding application is run - under external job control (Bert Belder) - -* darwin: assume CFRunLoopStop() isn't thread-safe, fixing a race condition - when stopping the 'stdin select hack' thread (Fedor Indutny) - -* win: fix UV_EALREADY not being reported correctly to the libuv user in some - cases (Bert Belder) - -* darwin: make the uv__cf_loop_runner and uv__cf_loop_cb functions static (Ben - Noordhuis) - -* darwin: task_info() cannot fail (Ben Noordhuis) - -* unix: add error mapping for ENETDOWN (Ben Noordhuis) - -* unix: implicitly signal write errors to the libuv user (Ben Noordhuis) - -* unix: fix assertion error on signal pipe overflow (Bert Belder) - -* unix: turn off POLLOUT after stream connect (Ben Noordhuis) - -* unix: fix stream refcounting buglet (Ben Noordhuis) - -* unix: remove assert statements that are no longer correct (Ben Noordhuis) - -* unix: appease warning about non-standard `inline` (Sean Silva) - -* unix: add uv__is_closing() macro (Ben Noordhuis) - -* unix: stop stream POLLOUT watcher on write error (Ben Noordhuis) - -* include: document uv_update_time() and uv_now() (Ben Noordhuis) - -* linux: fix cpu model parsing on newer arm kernels (Ben Noordhuis) - -* linux: fix a memory leak in uv_cpu_info() error path (Ben Noordhuis) - -* linux: don't ignore out-of-memory errors in uv_cpu_info() (Ben Noordhuis) - -* unix, windows: move uv_now() to uv-common.c (Ben Noordhuis) - -* test: fix a compilation problem in test-osx-select.c that was caused by the - use of c-style comments (Bert Belder) - -* darwin: use uv_fs_sendfile() use the sendfile api correctly (Wynn Wilkes) - -* windows: call idle handles on every loop iteration, something the unix - implementation already did (Bert Belder) - -* test: update the idle-starvation test to verify that idle handles are called - in every loop iteration (Bert Belder) - -* unix, windows: ensure that uv_run() in RUN_ONCE mode calls timers that expire - after blocking (Ben Noordhuis) - - -2013.05.29, Version 0.10.9 (Stable), a195f9ace23d92345baf57582678bfc3017e6632 - -Changes since version 0.10.8: - -* unix: fix stream refcounting buglet (Ben Noordhuis) - -* unix: remove erroneous asserts (Ben Noordhuis) - -* unix: add uv__is_closing() macro (Ben Noordhuis) - -* unix: stop stream POLLOUT watcher on write error (Ben Noordhuis) - - -2013.05.25, Version 0.10.8 (Stable), 0f39be12926fe2d8766a9f025797a473003e6504 - -Changes since version 0.10.7: - -* windows: make uv_spawn not fail under job control (Bert Belder) - -* darwin: assume CFRunLoopStop() isn't thread-safe (Fedor Indutny) - -* win: fix UV_EALREADY incorrectly set (Bert Belder) - -* darwin: make two uv__cf_*() functions static (Ben Noordhuis) - -* darwin: task_info() cannot fail (Ben Noordhuis) - -* unix: add mapping for ENETDOWN (Ben Noordhuis) - -* unix: implicitly signal write errors to libuv user (Ben Noordhuis) - -* unix: fix assert on signal pipe overflow (Bert Belder) - -* unix: turn off POLLOUT after stream connect (Ben Noordhuis) - - -2013.05.16, Version 0.11.3 (Unstable), 0a48c05b5988aea84c605751900926fa25443b34 - -Changes since version 0.11.2: - -* unix: clean up uv_accept() (Ben Noordhuis) - -* unix: remove errno preserving code (Ben Noordhuis) - -* darwin: fix ios build, don't require ApplicationServices (Ben Noordhuis) - -* windows: kill child processes when the parent dies (Bert Belder) - -* build: set soname in shared library (Ben Noordhuis) - -* build: make `make test` link against .a again (Ben Noordhuis) - -* build: only set soname on shared object builds (Timothy J. Fontaine) - -* build: convert predefined $PLATFORM to lower case (Elliot Saba) - -* test: fix process_title failing on linux (Miroslav Bajtoš) - -* test, sunos: disable process_title test (Miroslav Bajtoš) - -* test: add error logging to tty unit test (Miroslav Bajtoš) - - -2013.05.15, Version 0.10.7 (Stable), 028baaf0846b686a81e992cb2f2f5a9b8e841fcf - -Changes since version 0.10.6: - -* windows: kill child processes when the parent dies (Bert Belder) - - -2013.05.15, Version 0.10.6 (Stable), 11e6613e6260d95c8cf11bf89a2759c24649319a - -Changes since version 0.10.5: - -* stream: fix osx select hack (Fedor Indutny) - -* stream: fix small nit in select hack, add test (Fedor Indutny) - -* build: link with libkvm on openbsd (Ben Noordhuis) - -* stream: use harder sync restrictions for osx-hack (Fedor Indutny) - -* unix: fix EMFILE error handling (Ben Noordhuis) - -* darwin: fix unnecessary include headers (Daisuke Murase) - -* darwin: rename darwin-getproctitle.m (Ben Noordhuis) - -* build: convert predefined $PLATFORM to lower case (Elliot Saba) - -* build: set soname in shared library (Ben Noordhuis) - -* build: make `make test` link against .a again (Ben Noordhuis) - -* darwin: fix ios build, don't require ApplicationServices (Ben Noordhuis) - -* build: only set soname on shared object builds (Timothy J. Fontaine) - - -2013.05.11, Version 0.11.2 (Unstable), 3fba0bf65f091b91a9760530c05c6339c658d88b - -Changes since version 0.11.1: - -* darwin: look up file path with F_GETPATH (Ben Noordhuis) - -* unix, windows: add uv_has_ref() function (Saúl Ibarra Corretgé) - -* build: avoid double / in paths for dtrace (Timothy J. Fontaine) - -* unix: remove src/unix/cygwin.c (Ben Noordhuis) - -* windows: deal with the fact that GetTickCount might lag (Bert Belder) - -* unix: silence STATIC_ASSERT compiler warnings (Ben Noordhuis) - -* linux: don't use fopen() in uv_resident_set_memory() (Ben Noordhuis) - - -2013.04.24, Version 0.10.5 (Stable), 6595a7732c52eb4f8e57c88655f72997a8567a67 - -Changes since version 0.10.4: - -* unix: silence STATIC_ASSERT compiler warnings (Ben Noordhuis) - -* windows: make timers handle large timeouts (Miroslav Bajtoš) - -* windows: remove superfluous assert statement (Bert Belder) - -* unix: silence STATIC_ASSERT compiler warnings (Ben Noordhuis) - -* linux: don't use fopen() in uv_resident_set_memory() (Ben Noordhuis) - - -2013.04.12, Version 0.10.4 (Stable), 85827e26403ac6dfa331af8ec9916ea7e27bd833 - -Changes since version 0.10.3: - -* include: update uv_backend_fd() documentation (Ben Noordhuis) - -* unix: include uv.h in src/version.c (Ben Noordhuis) - -* unix: don't write more than IOV_MAX iovecs (Fedor Indutny) - -* mingw-w64: don't call _set_invalid_parameter_handler (Nils Maier) - -* build: gyp disable thin archives (Timothy J. Fontaine) - -* sunos: re-export entire library when static (Timothy J. Fontaine) - -* unix: dtrace probes for tick-start and tick-stop (Timothy J. Fontaine) - -* windows: fix memory leak in fs__sendfile (Shannen Saez) - -* windows: remove double initialization in uv_tty_init (Shannen Saez) - -* build: fix dtrace-enabled out of tree build (Ben Noordhuis) - -* build: squelch -Wdollar-in-identifier-extension warnings (Ben Noordhuis) - -* inet: snprintf returns int, not size_t (Brian White) - -* win: refactor uv_cpu_info (Bert Belder) - -* build: add support for Visual Studio 2012 (Nicholas Vavilov) - -* build: -Wno-dollar-in-identifier-extension is clang only (Ben Noordhuis) - - -2013.04.11, Version 0.11.1 (Unstable), 5c10e82ae0bc99eff86d4b9baff1f1aa0bf84c0a - -This is the first versioned release from the current unstable libuv branch. - -Changes since Node.js v0.11.0: - -* all platforms: nanosecond resolution support for uv_fs_[fl]stat (Timothy J. - Fontaine) - -* all platforms: add netmask to uv_interface_address (Ben Kelly) - -* unix: make sure the `status` parameter passed to the `uv_getaddrinfo` is 0 or - -1 (Ben Noordhuis) - -* unix: limit the number of iovecs written in a single `writev` syscall to - IOV_MAX (Fedor Indutny) - -* unix: add dtrace probes for tick-start and tick-stop (Timothy J. Fontaine) - -* mingw-w64: don't call _set_invalid_parameter_handler (Nils Maier) - -* windows: fix memory leak in fs__sendfile (Shannen Saez) - -* windows: fix edge case bugs in uv_cpu_info (Bert Belder) - -* include: no longer ship with / include ngx-queue.h (Ben Noordhuis) - -* include: remove UV_VERSION_* macros from uv.h (Ben Noordhuis) - -* documentation updates (Kristian Evensen, Ben Kelly, Ben Noordhuis) - -* build: fix dtrace-enabled builds (Ben Noordhuis, Timothy J. Fontaine) - -* build: gyp disable thin archives (Timothy J. Fontaine) - -* build: add support for Visual Studio 2012 (Nicholas Vavilov) - - -2013.03.28, Version 0.10.3 (Stable), 31ebe23973dd98fd8a24c042b606f37a794e99d0 - -Changes since version 0.10.2: - -* include: remove extraneous const from uv_version() (Ben Noordhuis) - -* doc: update README, replace `OS` by `PLATFORM` (Ben Noordhuis) - -* build: simplify .buildstamp rule (Ben Noordhuis) - -* build: disable -Wstrict-aliasing on darwin (Ben Noordhuis) - -* darwin: don't select(&exceptfds) in fallback path (Ben Noordhuis) - -* unix: don't clear flags after closing UDP handle (Saúl Ibarra Corretgé) - - -2013.03.25, Version 0.10.2 (Stable), 0f36a00568f3e7608f97f6c6cdb081f4800a50c9 - -This is the first officially versioned release of libuv. Starting now -libuv will make releases independently of Node.js. - -Changes since Node.js v0.10.0: - -* test: add tap output for windows (Timothy J. Fontaine) - -* unix: fix uv_tcp_simultaneous_accepts() logic (Ben Noordhuis) - -* include: bump UV_VERSION_MINOR (Ben Noordhuis) - -* unix: improve uv_guess_handle() implementation (Ben Noordhuis) - -* stream: run try_select only for pipes and ttys (Fedor Indutny) - -Changes since Node.js v0.10.1: - -* build: rename OS to PLATFORM (Ben Noordhuis) - -* unix: make uv_timer_init() initialize repeat (Brian Mazza) - -* unix: make timers handle large timeouts (Ben Noordhuis) - -* build: add OBJC makefile var (Ben Noordhuis) - -* Add `uv_version()` and `uv_version_string()` APIs (Bert Belder) diff --git a/libuv/LICENSE b/libuv/LICENSE deleted file mode 100644 index 4d41167..0000000 --- a/libuv/LICENSE +++ /dev/null @@ -1,46 +0,0 @@ -libuv is part of the Node project: http://nodejs.org/ -libuv may be distributed alone under Node's license: - -==== - -Copyright Joyent, Inc. and other Node contributors. All rights reserved. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. - -==== - -This license applies to all parts of libuv that are not externally -maintained libraries. - -The externally maintained libraries used by libuv are: - - - tree.h (from FreeBSD), copyright Niels Provos. Two clause BSD license. - - - inet_pton and inet_ntop implementations, contained in src/inet.c, are - copyright the Internet Systems Consortium, Inc., and licensed under the ISC - license. - - - stdint-msvc2008.h (from msinttypes), copyright Alexander Chemeris. Three - clause BSD license. - - - pthread-fixes.h, pthread-fixes.c, copyright Google Inc. and Sony Mobile - Communications AB. Three clause BSD license. - - - android-ifaddrs.h, android-ifaddrs.c, copyright Berkeley Software Design - Inc, Kenneth MacKay and Emergya (Cloud4all, FP7/2007-2013, grant agreement - n° 289016). Three clause BSD license. diff --git a/libuv/Makefile.am b/libuv/Makefile.am deleted file mode 100644 index 6c25229..0000000 --- a/libuv/Makefile.am +++ /dev/null @@ -1,333 +0,0 @@ -# Copyright (c) 2013, Ben Noordhuis -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -ACLOCAL_AMFLAGS = -I m4 - -AM_CPPFLAGS = -I$(top_srcdir)/include \ - -I$(top_srcdir)/src - -include_HEADERS=include/uv.h include/uv-errno.h include/uv-threadpool.h include/uv-version.h - -CLEANFILES = - -lib_LTLIBRARIES = libuv.la -libuv_la_CFLAGS = @CFLAGS@ -libuv_la_LDFLAGS = -no-undefined -version-info 1:0:0 -libuv_la_SOURCES = src/fs-poll.c \ - src/heap-inl.h \ - src/inet.c \ - src/queue.h \ - src/threadpool.c \ - src/uv-common.c \ - src/uv-common.h \ - src/version.c - -if SUNOS -# Can't be turned into a CC_CHECK_CFLAGS in configure.ac, it makes compilers -# on other platforms complain that the argument is unused during compilation. -libuv_la_CFLAGS += -pthread -endif - -if WINNT - -include_HEADERS += include/uv-win.h include/tree.h -AM_CPPFLAGS += -I$(top_srcdir)/src/win \ - -DWIN32_LEAN_AND_MEAN \ - -D_WIN32_WINNT=0x0600 -LIBS += -lws2_32 -lpsapi -liphlpapi -lshell32 -libuv_la_SOURCES += src/win/async.c \ - src/win/atomicops-inl.h \ - src/win/core.c \ - src/win/dl.c \ - src/win/error.c \ - src/win/fs-event.c \ - src/win/fs.c \ - src/win/getaddrinfo.c \ - src/win/getnameinfo.c \ - src/win/handle.c \ - src/win/handle-inl.h \ - src/win/internal.h \ - src/win/loop-watcher.c \ - src/win/pipe.c \ - src/win/poll.c \ - src/win/process-stdio.c \ - src/win/process.c \ - src/win/req.c \ - src/win/req-inl.h \ - src/win/signal.c \ - src/win/stream.c \ - src/win/stream-inl.h \ - src/win/tcp.c \ - src/win/thread.c \ - src/win/timer.c \ - src/win/tty.c \ - src/win/udp.c \ - src/win/util.c \ - src/win/winapi.c \ - src/win/winapi.h \ - src/win/winsock.c \ - src/win/winsock.h - -else # WINNT - -include_HEADERS += include/uv-unix.h -AM_CPPFLAGS += -I$(top_srcdir)/src/unix -libuv_la_SOURCES += src/unix/async.c \ - src/unix/atomic-ops.h \ - src/unix/core.c \ - src/unix/dl.c \ - src/unix/fs.c \ - src/unix/getaddrinfo.c \ - src/unix/getnameinfo.c \ - src/unix/internal.h \ - src/unix/loop-watcher.c \ - src/unix/loop.c \ - src/unix/pipe.c \ - src/unix/poll.c \ - src/unix/process.c \ - src/unix/signal.c \ - src/unix/spinlock.h \ - src/unix/stream.c \ - src/unix/tcp.c \ - src/unix/thread.c \ - src/unix/timer.c \ - src/unix/tty.c \ - src/unix/udp.c - -endif # WINNT - -EXTRA_DIST = test/fixtures/empty_file \ - test/fixtures/load_error.node \ - include \ - test \ - docs \ - img \ - samples \ - android-configure \ - CONTRIBUTING.md \ - LICENSE \ - README.md \ - checksparse.sh \ - vcbuild.bat \ - Makefile.mingw \ - common.gypi \ - gyp_uv.py \ - uv.gyp - - - -TESTS = test/run-tests -check_PROGRAMS = test/run-tests -test_run_tests_CFLAGS = -test_run_tests_SOURCES = test/blackhole-server.c \ - test/dns-server.c \ - test/echo-server.c \ - test/run-tests.c \ - test/runner.c \ - test/runner.h \ - test/task.h \ - test/test-active.c \ - test/test-async.c \ - test/test-async-null-cb.c \ - test/test-barrier.c \ - test/test-callback-order.c \ - test/test-callback-stack.c \ - test/test-close-fd.c \ - test/test-close-order.c \ - test/test-condvar.c \ - test/test-connection-fail.c \ - test/test-cwd-and-chdir.c \ - test/test-default-loop-close.c \ - test/test-delayed-accept.c \ - test/test-dlerror.c \ - test/test-embed.c \ - test/test-emfile.c \ - test/test-error.c \ - test/test-fail-always.c \ - test/test-fs-event.c \ - test/test-fs-poll.c \ - test/test-fs.c \ - test/test-get-currentexe.c \ - test/test-get-loadavg.c \ - test/test-get-memory.c \ - test/test-getaddrinfo.c \ - test/test-getnameinfo.c \ - test/test-getsockname.c \ - test/test-handle-fileno.c \ - test/test-hrtime.c \ - test/test-idle.c \ - test/test-ip4-addr.c \ - test/test-ip6-addr.c \ - test/test-ipc-send-recv.c \ - test/test-ipc.c \ - test/test-list.h \ - test/test-loop-handles.c \ - test/test-loop-alive.c \ - test/test-loop-close.c \ - test/test-loop-stop.c \ - test/test-loop-time.c \ - test/test-loop-configure.c \ - test/test-multiple-listen.c \ - test/test-mutexes.c \ - test/test-osx-select.c \ - test/test-pass-always.c \ - test/test-ping-pong.c \ - test/test-pipe-bind-error.c \ - test/test-pipe-connect-error.c \ - test/test-pipe-getsockname.c \ - test/test-pipe-sendmsg.c \ - test/test-pipe-server-close.c \ - test/test-pipe-close-stdout-read-stdin.c \ - test/test-platform-output.c \ - test/test-poll-close.c \ - test/test-poll-close-doesnt-corrupt-stack.c \ - test/test-poll-closesocket.c \ - test/test-poll.c \ - test/test-process-title.c \ - test/test-ref.c \ - test/test-run-nowait.c \ - test/test-run-once.c \ - test/test-semaphore.c \ - test/test-shutdown-close.c \ - test/test-shutdown-eof.c \ - test/test-shutdown-twice.c \ - test/test-signal-multiple-loops.c \ - test/test-signal.c \ - test/test-socket-buffer-size.c \ - test/test-spawn.c \ - test/test-stdio-over-pipes.c \ - test/test-tcp-bind-error.c \ - test/test-tcp-bind6-error.c \ - test/test-tcp-close-accept.c \ - test/test-tcp-close-while-connecting.c \ - test/test-tcp-close.c \ - test/test-tcp-connect-error-after-write.c \ - test/test-tcp-connect-error.c \ - test/test-tcp-connect-timeout.c \ - test/test-tcp-connect6-error.c \ - test/test-tcp-flags.c \ - test/test-tcp-open.c \ - test/test-tcp-read-stop.c \ - test/test-tcp-shutdown-after-write.c \ - test/test-tcp-unexpected-read.c \ - test/test-tcp-write-to-half-open-connection.c \ - test/test-tcp-write-after-connect.c \ - test/test-tcp-writealot.c \ - test/test-tcp-try-write.c \ - test/test-tcp-write-queue-order.c \ - test/test-thread-equal.c \ - test/test-thread.c \ - test/test-threadpool-cancel.c \ - test/test-threadpool.c \ - test/test-timer-again.c \ - test/test-timer-from-check.c \ - test/test-timer.c \ - test/test-tty.c \ - test/test-udp-bind.c \ - test/test-udp-dgram-too-big.c \ - test/test-udp-ipv6.c \ - test/test-udp-multicast-interface.c \ - test/test-udp-multicast-interface6.c \ - test/test-udp-multicast-join.c \ - test/test-udp-multicast-join6.c \ - test/test-udp-multicast-ttl.c \ - test/test-udp-open.c \ - test/test-udp-options.c \ - test/test-udp-send-and-recv.c \ - test/test-udp-send-immediate.c \ - test/test-udp-send-unreachable.c \ - test/test-udp-try-send.c \ - test/test-walk-handles.c \ - test/test-watcher-cross-stop.c -test_run_tests_LDADD = libuv.la - -if WINNT -test_run_tests_SOURCES += test/runner-win.c \ - test/runner-win.h -else -test_run_tests_SOURCES += test/runner-unix.c \ - test/runner-unix.h -endif - -if AIX -test_run_tests_CFLAGS += -D_ALL_SOURCE -D_XOPEN_SOURCE=500 -D_LINUX_SOURCE_COMPAT -endif - -if SUNOS -test_run_tests_CFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=500 -endif - - -if AIX -libuv_la_CFLAGS += -D_ALL_SOURCE -D_XOPEN_SOURCE=500 -D_LINUX_SOURCE_COMPAT -libuv_la_SOURCES += src/unix/aix.c -endif - -if ANDROID -include_HEADERS += include/android-ifaddrs.h \ - include/pthread-fixes.h -libuv_la_SOURCES += src/unix/android-ifaddrs.c \ - src/unix/pthread-fixes.c -endif - -if DARWIN -include_HEADERS += include/uv-darwin.h -libuv_la_CFLAGS += -D_DARWIN_USE_64_BIT_INODE=1 -libuv_la_CFLAGS += -D_DARWIN_UNLIMITED_SELECT=1 -libuv_la_SOURCES += src/unix/darwin.c \ - src/unix/darwin-proctitle.c \ - src/unix/fsevents.c \ - src/unix/kqueue.c \ - src/unix/proctitle.c -endif - -if DRAGONFLY -include_HEADERS += include/uv-bsd.h -endif - -if FREEBSD -include_HEADERS += include/uv-bsd.h -libuv_la_SOURCES += src/unix/freebsd.c src/unix/kqueue.c -endif - -if LINUX -include_HEADERS += include/uv-linux.h -libuv_la_CFLAGS += -D_GNU_SOURCE -libuv_la_SOURCES += src/unix/linux-core.c \ - src/unix/linux-inotify.c \ - src/unix/linux-syscalls.c \ - src/unix/linux-syscalls.h \ - src/unix/proctitle.c -endif - -if NETBSD -include_HEADERS += include/uv-bsd.h -libuv_la_SOURCES += src/unix/kqueue.c src/unix/netbsd.c -endif - -if OPENBSD -include_HEADERS += include/uv-bsd.h -libuv_la_SOURCES += src/unix/kqueue.c src/unix/openbsd.c -endif - -if SUNOS -include_HEADERS += include/uv-sunos.h -libuv_la_CFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=500 -libuv_la_SOURCES += src/unix/sunos.c -endif - -if HAVE_PKG_CONFIG -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = @PACKAGE_NAME@.pc -endif diff --git a/libuv/Makefile.mingw b/libuv/Makefile.mingw deleted file mode 100644 index 156f15d..0000000 --- a/libuv/Makefile.mingw +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright (c) 2013, Ben Noordhuis -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -CC ?= gcc - -CFLAGS += -Wall \ - -Wextra \ - -Wno-unused-parameter \ - -Iinclude \ - -Isrc \ - -Isrc/win \ - -DWIN32_LEAN_AND_MEAN \ - -D_WIN32_WINNT=0x0600 - -INCLUDES = include/stdint-msvc2008.h \ - include/tree.h \ - include/uv-errno.h \ - include/uv-threadpool.h \ - include/uv-version.h \ - include/uv-win.h \ - include/uv.h \ - src/heap-inl.h \ - src/queue.h \ - src/uv-common.h \ - src/win/atomicops-inl.h \ - src/win/handle-inl.h \ - src/win/internal.h \ - src/win/req-inl.h \ - src/win/stream-inl.h \ - src/win/winapi.h \ - src/win/winsock.h - -OBJS = src/fs-poll.o \ - src/inet.o \ - src/threadpool.o \ - src/uv-common.o \ - src/version.o \ - src/win/async.o \ - src/win/core.o \ - src/win/dl.o \ - src/win/error.o \ - src/win/fs-event.o \ - src/win/fs.o \ - src/win/getaddrinfo.o \ - src/win/getnameinfo.o \ - src/win/handle.o \ - src/win/loop-watcher.o \ - src/win/pipe.o \ - src/win/poll.o \ - src/win/process-stdio.o \ - src/win/process.o \ - src/win/req.o \ - src/win/signal.o \ - src/win/stream.o \ - src/win/tcp.o \ - src/win/thread.o \ - src/win/timer.o \ - src/win/tty.o \ - src/win/udp.o \ - src/win/util.o \ - src/win/winapi.o \ - src/win/winsock.o - -all: libuv.a - -clean: - -$(RM) $(OBJS) libuv.a - -libuv.a: $(OBJS) - $(AR) crs $@ $^ - -$(OBJS): %.o : %.c $(INCLUDES) - $(CC) $(CFLAGS) -c -o $@ $< diff --git a/libuv/README.md b/libuv/README.md deleted file mode 100644 index a267f0d..0000000 --- a/libuv/README.md +++ /dev/null @@ -1,186 +0,0 @@ -![libuv][libuv_banner] - -## Overview - -libuv is a multi-platform support library with a focus on asynchronous I/O. It -was primarily developed for use by [Node.js](http://nodejs.org), but it's also -used by [Luvit](http://luvit.io/), [Julia](http://julialang.org/), -[pyuv](https://github.com/saghul/pyuv), and [others](https://github.com/libuv/libuv/wiki/Projects-that-use-libuv). - -## Feature highlights - - * Full-featured event loop backed by epoll, kqueue, IOCP, event ports. - - * Asynchronous TCP and UDP sockets - - * Asynchronous DNS resolution - - * Asynchronous file and file system operations - - * File system events - - * ANSI escape code controlled TTY - - * IPC with socket sharing, using Unix domain sockets or named pipes (Windows) - - * Child processes - - * Thread pool - - * Signal handling - - * High resolution clock - - * Threading and synchronization primitives - -## Versioning - -Starting with version 1.0.0 libuv follows the [semantic versioning](http://semver.org/) -scheme. The API change and backwards compatibility rules are those indicated by -SemVer. libuv will keep a stable ABI across major releases. - -## Community - - * [Mailing list](http://groups.google.com/group/libuv) - * [IRC chatroom (#libuv@irc.freenode.org)](http://webchat.freenode.net?channels=libuv&uio=d4) - -## Documentation - -### Official API documentation - -Located in the docs/ subdirectory. It uses the [Sphinx](http://sphinx-doc.org/) -framework, which makes it possible to build the documentation in multiple -formats. - -Show different supported building options: - - $ make help - -Build documentation as HTML: - - $ make html - -Build documentation as man pages: - - $ make man - -Build documentation as ePub: - - $ make epub - -NOTE: Windows users need to use make.bat instead of plain 'make'. - -Documentation can be browsed online [here](http://docs.libuv.org). - -### Other resources - - * [An Introduction to libuv](http://nikhilm.github.com/uvbook/) - — An overview of libuv with tutorials. - * [LXJS 2012 talk](http://www.youtube.com/watch?v=nGn60vDSxQ4) - — High-level introductory talk about libuv. - * [Tests and benchmarks](https://github.com/libuv/libuv/tree/master/test) - — API specification and usage examples. - * [libuv-dox](https://github.com/thlorenz/libuv-dox) - — Documenting types and methods of libuv, mostly by reading uv.h. - * [learnuv](https://github.com/thlorenz/learnuv) - — Learn uv for fun and profit, a self guided workshop to libuv. - -## Build Instructions - -For GCC there are two build methods: via autotools or via [GYP][]. -GYP is a meta-build system which can generate MSVS, Makefile, and XCode -backends. It is best used for integration into other projects. - -To build with autotools: - - $ sh autogen.sh - $ ./configure - $ make - $ make check - $ make install - -### Windows - -First, [Python][] 2.6 or 2.7 must be installed as it is required by [GYP][]. -If python is not in your path, set the environment variable `PYTHON` to its -location. For example: `set PYTHON=C:\Python27\python.exe` - -To build with Visual Studio, launch a git shell (e.g. Cmd or PowerShell) -and run vcbuild.bat which will checkout the GYP code into build/gyp and -generate uv.sln as well as related project files. - -To have GYP generate build script for another system, checkout GYP into the -project tree manually: - - $ git clone https://chromium.googlesource.com/external/gyp.git build/gyp - OR - $ svn co http://gyp.googlecode.com/svn/trunk build/gyp - -### Unix - -Run: - - $ ./gyp_uv.py -f make - $ make -C out - -Run `./gyp_uv.py -f make -Dtarget_arch=x32` to build [x32][] binaries. - -### OS X - -Run: - - $ ./gyp_uv.py -f xcode - $ xcodebuild -ARCHS="x86_64" -project uv.xcodeproj \ - -configuration Release -target All - -Using Homebrew: - - $ brew install --HEAD libuv - -Note to OS X users: - -Make sure that you specify the architecture you wish to build for in the -"ARCHS" flag. You can specify more than one by delimiting with a space -(e.g. "x86_64 i386"). - -### Android - -Run: - - $ source ./android-configure NDK_PATH gyp - $ make -C out - -Note for UNIX users: compile your project with `-D_LARGEFILE_SOURCE` and -`-D_FILE_OFFSET_BITS=64`. GYP builds take care of that automatically. - -### Running tests - -Run: - - $ ./gyp_uv.py -f make - $ make -C out - $ ./out/Debug/run-tests - -## Supported Platforms - -Microsoft Windows operating systems since Windows XP SP2. It can be built -with either Visual Studio or MinGW. Consider using -[Visual Studio Express 2010][] or later if you do not have a full Visual -Studio license. - -Linux using the GCC toolchain. - -OS X using the GCC or XCode toolchain. - -Solaris 121 and later using GCC toolchain. - -## Patches - -See the [guidelines for contributing][]. - -[node.js]: http://nodejs.org/ -[GYP]: http://code.google.com/p/gyp/ -[Python]: https://www.python.org/downloads/ -[Visual Studio Express 2010]: http://www.microsoft.com/visualstudio/eng/products/visual-studio-2010-express -[guidelines for contributing]: https://github.com/libuv/libuv/blob/master/CONTRIBUTING.md -[libuv_banner]: https://raw.githubusercontent.com/libuv/libuv/master/img/banner.png diff --git a/libuv/android-configure b/libuv/android-configure deleted file mode 100755 index 9750581..0000000 --- a/libuv/android-configure +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -export TOOLCHAIN=$PWD/android-toolchain -mkdir -p $TOOLCHAIN -$1/build/tools/make-standalone-toolchain.sh \ - --toolchain=arm-linux-androideabi-4.8 \ - --arch=arm \ - --install-dir=$TOOLCHAIN \ - --platform=android-9 -export PATH=$TOOLCHAIN/bin:$PATH -export AR=arm-linux-androideabi-ar -export CC=arm-linux-androideabi-gcc -export CXX=arm-linux-androideabi-g++ -export LINK=arm-linux-androideabi-g++ -export PLATFORM=android - -if [ $2 -a $2 == 'gyp' ] - then - ./gyp_uv.py -Dtarget_arch=arm -DOS=android -fi diff --git a/libuv/autogen.sh b/libuv/autogen.sh deleted file mode 100755 index 0574778..0000000 --- a/libuv/autogen.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/sh - -# Copyright (c) 2013, Ben Noordhuis -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -cd `dirname "$0"` - -if [ "$LIBTOOLIZE" = "" ] && [ "`uname`" = "Darwin" ]; then - LIBTOOLIZE=glibtoolize -fi - -ACLOCAL=${ACLOCAL:-aclocal} -AUTOCONF=${AUTOCONF:-autoconf} -AUTOMAKE=${AUTOMAKE:-automake} -LIBTOOLIZE=${LIBTOOLIZE:-libtoolize} - -automake_version=`"$AUTOMAKE" --version | head -n 1 | sed 's/[^.0-9]//g'` -automake_version_major=`echo "$automake_version" | cut -d. -f1` -automake_version_minor=`echo "$automake_version" | cut -d. -f2` - -UV_EXTRA_AUTOMAKE_FLAGS= -if test "$automake_version_major" -gt 1 || \ - test "$automake_version_major" -eq 1 && \ - test "$automake_version_minor" -gt 11; then - # serial-tests is available in v1.12 and newer. - UV_EXTRA_AUTOMAKE_FLAGS="$UV_EXTRA_AUTOMAKE_FLAGS serial-tests" -fi -echo "m4_define([UV_EXTRA_AUTOMAKE_FLAGS], [$UV_EXTRA_AUTOMAKE_FLAGS])" \ - > m4/libuv-extra-automake-flags.m4 - -set -ex -"$LIBTOOLIZE" -"$ACLOCAL" -I m4 -"$AUTOCONF" -"$AUTOMAKE" --add-missing --copy diff --git a/libuv/checksparse.sh b/libuv/checksparse.sh deleted file mode 100755 index d2dc3a5..0000000 --- a/libuv/checksparse.sh +++ /dev/null @@ -1,232 +0,0 @@ -#!/bin/sh - -# Copyright (c) 2013, Ben Noordhuis -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -SPARSE=${SPARSE:-sparse} - -SPARSE_FLAGS=${SPARSE_FLAGS:-" --D__POSIX__ --Wsparse-all --Wno-do-while --Wno-transparent-union --Iinclude --Isrc -"} - -SOURCES=" -include/tree.h -include/uv-unix.h -include/uv.h -src/fs-poll.c -src/inet.c -src/queue.h -src/unix/async.c -src/unix/core.c -src/unix/dl.c -src/unix/fs.c -src/unix/getaddrinfo.c -src/unix/internal.h -src/unix/loop-watcher.c -src/unix/loop.c -src/unix/pipe.c -src/unix/poll.c -src/unix/process.c -src/unix/signal.c -src/unix/stream.c -src/unix/tcp.c -src/unix/thread.c -src/unix/threadpool.c -src/unix/timer.c -src/unix/tty.c -src/unix/udp.c -src/uv-common.c -src/uv-common.h -" - -TESTS=" -test/benchmark-async-pummel.c -test/benchmark-async.c -test/benchmark-fs-stat.c -test/benchmark-getaddrinfo.c -test/benchmark-loop-count.c -test/benchmark-million-async.c -test/benchmark-million-timers.c -test/benchmark-multi-accept.c -test/benchmark-ping-pongs.c -test/benchmark-pound.c -test/benchmark-pump.c -test/benchmark-sizes.c -test/benchmark-spawn.c -test/benchmark-tcp-write-batch.c -test/benchmark-thread.c -test/benchmark-udp-pummel.c -test/blackhole-server.c -test/dns-server.c -test/echo-server.c -test/run-benchmarks.c -test/run-tests.c -test/runner-unix.c -test/runner-unix.h -test/runner.c -test/runner.h -test/task.h -test/test-active.c -test/test-async.c -test/test-barrier.c -test/test-callback-order.c -test/test-callback-stack.c -test/test-condvar.c -test/test-connection-fail.c -test/test-cwd-and-chdir.c -test/test-delayed-accept.c -test/test-dlerror.c -test/test-embed.c -test/test-error.c -test/test-fail-always.c -test/test-fs-event.c -test/test-fs-poll.c -test/test-fs.c -test/test-get-currentexe.c -test/test-get-loadavg.c -test/test-get-memory.c -test/test-getaddrinfo.c -test/test-getsockname.c -test/test-hrtime.c -test/test-idle.c -test/test-ip6-addr.c -test/test-ipc-send-recv.c -test/test-ipc.c -test/test-loop-handles.c -test/test-multiple-listen.c -test/test-mutexes.c -test/test-pass-always.c -test/test-ping-pong.c -test/test-pipe-bind-error.c -test/test-pipe-connect-error.c -test/test-pipe-sendmsg.c -test/test-pipe-server-close.c -test/test-platform-output.c -test/test-poll-close.c -test/test-poll.c -test/test-process-title.c -test/test-ref.c -test/test-run-nowait.c -test/test-run-once.c -test/test-semaphore.c -test/test-shutdown-close.c -test/test-shutdown-eof.c -test/test-signal-multiple-loops.c -test/test-signal.c -test/test-spawn.c -test/test-stdio-over-pipes.c -test/test-tcp-bind-error.c -test/test-tcp-bind6-error.c -test/test-tcp-close-while-connecting.c -test/test-tcp-close-accept.c -test/test-tcp-close.c -test/test-tcp-connect-error-after-write.c -test/test-tcp-connect-error.c -test/test-tcp-connect-timeout.c -test/test-tcp-connect6-error.c -test/test-tcp-flags.c -test/test-tcp-open.c -test/test-tcp-read-stop.c -test/test-tcp-shutdown-after-write.c -test/test-tcp-unexpected-read.c -test/test-tcp-write-error.c -test/test-tcp-write-to-half-open-connection.c -test/test-tcp-writealot.c -test/test-thread.c -test/test-threadpool-cancel.c -test/test-threadpool.c -test/test-timer-again.c -test/test-timer.c -test/test-tty.c -test/test-udp-dgram-too-big.c -test/test-udp-ipv6.c -test/test-udp-multicast-join.c -test/test-udp-multicast-ttl.c -test/test-udp-open.c -test/test-udp-options.c -test/test-udp-send-and-recv.c -test/test-walk-handles.c -test/test-watcher-cross-stop.c -" - -case `uname -s` in -AIX) - SPARSE_FLAGS="$SPARSE_FLAGS -D_AIX=1" - SOURCES="$SOURCES - src/unix/aix.c" - ;; -Darwin) - SPARSE_FLAGS="$SPARSE_FLAGS -D__APPLE__=1" - SOURCES="$SOURCES - include/uv-bsd.h - src/unix/darwin.c - src/unix/kqueue.c - src/unix/fsevents.c" - ;; -DragonFly) - SPARSE_FLAGS="$SPARSE_FLAGS -D__DragonFly__=1" - SOURCES="$SOURCES - include/uv-bsd.h - src/unix/kqueue.c - src/unix/freebsd.c" - ;; -FreeBSD) - SPARSE_FLAGS="$SPARSE_FLAGS -D__FreeBSD__=1" - SOURCES="$SOURCES - include/uv-bsd.h - src/unix/kqueue.c - src/unix/freebsd.c" - ;; -Linux) - SPARSE_FLAGS="$SPARSE_FLAGS -D__linux__=1" - SOURCES="$SOURCES - include/uv-linux.h - src/unix/linux-inotify.c - src/unix/linux-core.c - src/unix/linux-syscalls.c - src/unix/linux-syscalls.h" - ;; -NetBSD) - SPARSE_FLAGS="$SPARSE_FLAGS -D__NetBSD__=1" - SOURCES="$SOURCES - include/uv-bsd.h - src/unix/kqueue.c - src/unix/netbsd.c" - ;; -OpenBSD) - SPARSE_FLAGS="$SPARSE_FLAGS -D__OpenBSD__=1" - SOURCES="$SOURCES - include/uv-bsd.h - src/unix/kqueue.c - src/unix/openbsd.c" - ;; -SunOS) - SPARSE_FLAGS="$SPARSE_FLAGS -D__sun=1" - SOURCES="$SOURCES - include/uv-sunos.h - src/unix/sunos.c" - ;; -esac - -for ARCH in __i386__ __x86_64__ __arm__ __mips__; do - $SPARSE $SPARSE_FLAGS -D$ARCH=1 $SOURCES -done - -# Tests are architecture independent. -$SPARSE $SPARSE_FLAGS -Itest $TESTS diff --git a/libuv/common.gypi b/libuv/common.gypi deleted file mode 100644 index ecf9475..0000000 --- a/libuv/common.gypi +++ /dev/null @@ -1,210 +0,0 @@ -{ - 'variables': { - 'visibility%': 'hidden', # V8's visibility setting - 'target_arch%': 'ia32', # set v8's target architecture - 'host_arch%': 'ia32', # set v8's host architecture - 'uv_library%': 'static_library', # allow override to 'shared_library' for DLL/.so builds - 'component%': 'static_library', # NB. these names match with what V8 expects - 'msvs_multi_core_compile': '0', # we do enable multicore compiles, but not using the V8 way - }, - - 'target_defaults': { - 'default_configuration': 'Debug', - 'configurations': { - 'Debug': { - 'defines': [ 'DEBUG', '_DEBUG' ], - 'cflags': [ '-g', '-O0', '-fwrapv' ], - 'msvs_settings': { - 'VCCLCompilerTool': { - 'target_conditions': [ - ['uv_library=="static_library"', { - 'RuntimeLibrary': 1, # static debug - }, { - 'RuntimeLibrary': 3, # DLL debug - }], - ], - 'Optimization': 0, # /Od, no optimization - 'MinimalRebuild': 'false', - 'OmitFramePointers': 'false', - 'BasicRuntimeChecks': 3, # /RTC1 - }, - 'VCLinkerTool': { - 'LinkIncremental': 2, # enable incremental linking - }, - }, - 'xcode_settings': { - 'GCC_OPTIMIZATION_LEVEL': '0', - 'OTHER_CFLAGS': [ '-Wno-strict-aliasing' ], - }, - 'conditions': [ - ['OS != "win"', { - 'defines': [ 'EV_VERIFY=2' ], - }], - ] - }, - 'Release': { - 'defines': [ 'NDEBUG' ], - 'cflags': [ - '-O3', - '-fstrict-aliasing', - '-fomit-frame-pointer', - '-fdata-sections', - '-ffunction-sections', - ], - 'msvs_settings': { - 'VCCLCompilerTool': { - 'target_conditions': [ - ['uv_library=="static_library"', { - 'RuntimeLibrary': 0, # static release - }, { - 'RuntimeLibrary': 2, # debug release - }], - ], - 'Optimization': 3, # /Ox, full optimization - 'FavorSizeOrSpeed': 1, # /Ot, favour speed over size - 'InlineFunctionExpansion': 2, # /Ob2, inline anything eligible - 'WholeProgramOptimization': 'true', # /GL, whole program optimization, needed for LTCG - 'OmitFramePointers': 'true', - 'EnableFunctionLevelLinking': 'true', - 'EnableIntrinsicFunctions': 'true', - }, - 'VCLibrarianTool': { - 'AdditionalOptions': [ - '/LTCG', # link time code generation - ], - }, - 'VCLinkerTool': { - 'LinkTimeCodeGeneration': 1, # link-time code generation - 'OptimizeReferences': 2, # /OPT:REF - 'EnableCOMDATFolding': 2, # /OPT:ICF - 'LinkIncremental': 1, # disable incremental linking - }, - }, - } - }, - 'msvs_settings': { - 'VCCLCompilerTool': { - 'StringPooling': 'true', # pool string literals - 'DebugInformationFormat': 3, # Generate a PDB - 'WarningLevel': 3, - 'BufferSecurityCheck': 'true', - 'ExceptionHandling': 1, # /EHsc - 'SuppressStartupBanner': 'true', - 'WarnAsError': 'false', - 'AdditionalOptions': [ - '/MP', # compile across multiple CPUs - ], - }, - 'VCLibrarianTool': { - }, - 'VCLinkerTool': { - 'GenerateDebugInformation': 'true', - 'RandomizedBaseAddress': 2, # enable ASLR - 'DataExecutionPrevention': 2, # enable DEP - 'AllowIsolation': 'true', - 'SuppressStartupBanner': 'true', - 'target_conditions': [ - ['_type=="executable"', { - 'SubSystem': 1, # console executable - }], - ], - }, - }, - 'conditions': [ - ['OS == "win"', { - 'msvs_cygwin_shell': 0, # prevent actions from trying to use cygwin - 'defines': [ - 'WIN32', - # we don't really want VC++ warning us about - # how dangerous C functions are... - '_CRT_SECURE_NO_DEPRECATE', - # ... or that C implementations shouldn't use - # POSIX names - '_CRT_NONSTDC_NO_DEPRECATE', - ], - 'target_conditions': [ - ['target_arch=="x64"', { - 'msvs_configuration_platform': 'x64' - }] - ] - }], - ['OS in "freebsd linux openbsd solaris android"', { - 'cflags': [ '-Wall' ], - 'cflags_cc': [ '-fno-rtti', '-fno-exceptions' ], - 'target_conditions': [ - ['_type=="static_library"', { - 'standalone_static_library': 1, # disable thin archive which needs binutils >= 2.19 - }], - ], - 'conditions': [ - [ 'host_arch != target_arch and target_arch=="ia32"', { - 'cflags': [ '-m32' ], - 'ldflags': [ '-m32' ], - }], - [ 'target_arch=="x32"', { - 'cflags': [ '-mx32' ], - 'ldflags': [ '-mx32' ], - }], - [ 'OS=="linux"', { - 'cflags': [ '-ansi' ], - }], - [ 'OS=="solaris"', { - 'cflags': [ '-pthreads' ], - 'ldflags': [ '-pthreads' ], - }], - [ 'OS not in "solaris android"', { - 'cflags': [ '-pthread' ], - 'ldflags': [ '-pthread' ], - }], - [ 'visibility=="hidden"', { - 'cflags': [ '-fvisibility=hidden' ], - }], - ], - }], - ['OS=="mac"', { - 'xcode_settings': { - 'ALWAYS_SEARCH_USER_PATHS': 'NO', - 'GCC_CW_ASM_SYNTAX': 'NO', # No -fasm-blocks - 'GCC_DYNAMIC_NO_PIC': 'NO', # No -mdynamic-no-pic - # (Equivalent to -fPIC) - 'GCC_ENABLE_CPP_EXCEPTIONS': 'NO', # -fno-exceptions - 'GCC_ENABLE_CPP_RTTI': 'NO', # -fno-rtti - 'GCC_ENABLE_PASCAL_STRINGS': 'NO', # No -mpascal-strings - # GCC_INLINES_ARE_PRIVATE_EXTERN maps to -fvisibility-inlines-hidden - 'GCC_INLINES_ARE_PRIVATE_EXTERN': 'YES', - 'GCC_SYMBOLS_PRIVATE_EXTERN': 'YES', # -fvisibility=hidden - 'GCC_THREADSAFE_STATICS': 'NO', # -fno-threadsafe-statics - 'PREBINDING': 'NO', # No -Wl,-prebind - 'USE_HEADERMAP': 'NO', - 'OTHER_CFLAGS': [ - '-fstrict-aliasing', - ], - 'WARNING_CFLAGS': [ - '-Wall', - '-Wendif-labels', - '-W', - '-Wno-unused-parameter', - ], - }, - 'conditions': [ - ['target_arch=="ia32"', { - 'xcode_settings': {'ARCHS': ['i386']}, - }], - ['target_arch=="x64"', { - 'xcode_settings': {'ARCHS': ['x86_64']}, - }], - ], - 'target_conditions': [ - ['_type!="static_library"', { - 'xcode_settings': {'OTHER_LDFLAGS': ['-Wl,-search_paths_first']}, - }], - ], - }], - ['OS=="solaris"', { - 'cflags': [ '-fno-omit-frame-pointer' ], - # pull in V8's postmortem metadata - 'ldflags': [ '-Wl,-z,allextract' ] - }], - ], - }, -} diff --git a/libuv/configure.ac b/libuv/configure.ac deleted file mode 100644 index 0418335..0000000 --- a/libuv/configure.ac +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright (c) 2013, Ben Noordhuis -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -AC_PREREQ(2.57) -AC_INIT([libuv], [1.3.0], [https://github.com/libuv/libuv/issues]) -AC_CONFIG_MACRO_DIR([m4]) -m4_include([m4/libuv-extra-automake-flags.m4]) -m4_include([m4/as_case.m4]) -m4_include([m4/libuv-check-flags.m4]) -AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects] UV_EXTRA_AUTOMAKE_FLAGS) -AC_CANONICAL_HOST -AC_ENABLE_SHARED -AC_ENABLE_STATIC -AC_PROG_CC -AM_PROG_CC_C_O -CC_CHECK_CFLAGS_APPEND([-fvisibility=hidden]) -CC_CHECK_CFLAGS_APPEND([-g]) -CC_CHECK_CFLAGS_APPEND([-std=gnu89]) -CC_CHECK_CFLAGS_APPEND([-pedantic]) -CC_CHECK_CFLAGS_APPEND([-Wall]) -CC_CHECK_CFLAGS_APPEND([-Wextra]) -CC_CHECK_CFLAGS_APPEND([-Wno-unused-parameter]) -# AM_PROG_AR is not available in automake v0.11 but it's essential in v0.12. -m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) -# autoconf complains if AC_PROG_LIBTOOL precedes AM_PROG_AR. -AC_PROG_LIBTOOL -m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) -LT_INIT -# TODO(bnoordhuis) Check for -pthread vs. -pthreads -AC_CHECK_LIB([dl], [dlopen]) -AC_CHECK_LIB([kstat], [kstat_lookup]) -AC_CHECK_LIB([kvm], [kvm_open]) -AC_CHECK_LIB([nsl], [gethostbyname]) -AC_CHECK_LIB([perfstat], [perfstat_cpu]) -AC_CHECK_LIB([pthread], [pthread_mutex_init]) -AC_CHECK_LIB([rt], [clock_gettime]) -AC_CHECK_LIB([sendfile], [sendfile]) -AC_CHECK_LIB([socket], [socket]) -AC_SYS_LARGEFILE -AM_CONDITIONAL([AIX], [AS_CASE([$host_os],[aix*], [true], [false])]) -AM_CONDITIONAL([ANDROID], [AS_CASE([$host_os],[linux-android*],[true], [false])]) -AM_CONDITIONAL([DARWIN], [AS_CASE([$host_os],[darwin*], [true], [false])]) -AM_CONDITIONAL([DRAGONFLY],[AS_CASE([$host_os],[dragonfly*], [true], [false])]) -AM_CONDITIONAL([FREEBSD], [AS_CASE([$host_os],[freebsd*], [true], [false])]) -AM_CONDITIONAL([LINUX], [AS_CASE([$host_os],[linux*], [true], [false])]) -AM_CONDITIONAL([NETBSD], [AS_CASE([$host_os],[netbsd*], [true], [false])]) -AM_CONDITIONAL([OPENBSD], [AS_CASE([$host_os],[openbsd*], [true], [false])]) -AM_CONDITIONAL([SUNOS], [AS_CASE([$host_os],[solaris*], [true], [false])]) -AM_CONDITIONAL([WINNT], [AS_CASE([$host_os],[mingw*], [true], [false])]) -AC_CHECK_PROG(PKG_CONFIG, pkg-config, yes) -AM_CONDITIONAL([HAVE_PKG_CONFIG], [test "x$PKG_CONFIG" != "x"]) -AS_IF([test "x$PKG_CONFIG" != "x"], [ - AC_CONFIG_FILES([libuv.pc]) -]) -AC_CONFIG_FILES([Makefile]) -AC_OUTPUT diff --git a/libuv/docs/make.bat b/libuv/docs/make.bat deleted file mode 100644 index aa7089a..0000000 --- a/libuv/docs/make.bat +++ /dev/null @@ -1,243 +0,0 @@ -@ECHO OFF - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set BUILDDIR=build -set SRCDIR=src -set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% %SRCDIR% -set I18NSPHINXOPTS=%SPHINXOPTS% %SRCDIR% -if NOT "%PAPER%" == "" ( - set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% - set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% -) - -if "%1" == "" goto help - -if "%1" == "help" ( - :help - echo.Please use `make ^` where ^ is one of - echo. html to make standalone HTML files - echo. dirhtml to make HTML files named index.html in directories - echo. singlehtml to make a single large HTML file - echo. pickle to make pickle files - echo. json to make JSON files - echo. htmlhelp to make HTML files and a HTML help project - echo. qthelp to make HTML files and a qthelp project - echo. devhelp to make HTML files and a Devhelp project - echo. epub to make an epub - echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter - echo. text to make text files - echo. man to make manual pages - echo. texinfo to make Texinfo files - echo. gettext to make PO message catalogs - echo. changes to make an overview over all changed/added/deprecated items - echo. xml to make Docutils-native XML files - echo. pseudoxml to make pseudoxml-XML files for display purposes - echo. linkcheck to check all external links for integrity - echo. doctest to run all doctests embedded in the documentation if enabled - goto end -) - -if "%1" == "clean" ( - for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i - del /q /s %BUILDDIR%\* - goto end -) - - -%SPHINXBUILD% 2> nul -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 -) - -if "%1" == "html" ( - %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/html. - goto end -) - -if "%1" == "dirhtml" ( - %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. - goto end -) - -if "%1" == "singlehtml" ( - %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. - goto end -) - -if "%1" == "pickle" ( - %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the pickle files. - goto end -) - -if "%1" == "json" ( - %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the JSON files. - goto end -) - -if "%1" == "htmlhelp" ( - %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run HTML Help Workshop with the ^ -.hhp project file in %BUILDDIR%/htmlhelp. - goto end -) - -if "%1" == "qthelp" ( - %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run "qcollectiongenerator" with the ^ -.qhcp project file in %BUILDDIR%/qthelp, like this: - echo.^> qcollectiongenerator %BUILDDIR%\qthelp\libuv.qhcp - echo.To view the help file: - echo.^> assistant -collectionFile %BUILDDIR%\qthelp\libuv.ghc - goto end -) - -if "%1" == "devhelp" ( - %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. - goto end -) - -if "%1" == "epub" ( - %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The epub file is in %BUILDDIR%/epub. - goto end -) - -if "%1" == "latex" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "latexpdf" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - cd %BUILDDIR%/latex - make all-pdf - cd %BUILDDIR%/.. - echo. - echo.Build finished; the PDF files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "latexpdfja" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - cd %BUILDDIR%/latex - make all-pdf-ja - cd %BUILDDIR%/.. - echo. - echo.Build finished; the PDF files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "text" ( - %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The text files are in %BUILDDIR%/text. - goto end -) - -if "%1" == "man" ( - %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The manual pages are in %BUILDDIR%/man. - goto end -) - -if "%1" == "texinfo" ( - %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. - goto end -) - -if "%1" == "gettext" ( - %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The message catalogs are in %BUILDDIR%/locale. - goto end -) - -if "%1" == "changes" ( - %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes - if errorlevel 1 exit /b 1 - echo. - echo.The overview file is in %BUILDDIR%/changes. - goto end -) - -if "%1" == "linkcheck" ( - %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck - if errorlevel 1 exit /b 1 - echo. - echo.Link check complete; look for any errors in the above output ^ -or in %BUILDDIR%/linkcheck/output.txt. - goto end -) - -if "%1" == "doctest" ( - %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest - if errorlevel 1 exit /b 1 - echo. - echo.Testing of doctests in the sources finished, look at the ^ -results in %BUILDDIR%/doctest/output.txt. - goto end -) - -if "%1" == "xml" ( - %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The XML files are in %BUILDDIR%/xml. - goto end -) - -if "%1" == "pseudoxml" ( - %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. - goto end -) - -:end diff --git a/libuv/docs/src/async.rst b/libuv/docs/src/async.rst deleted file mode 100644 index 5c40045..0000000 --- a/libuv/docs/src/async.rst +++ /dev/null @@ -1,57 +0,0 @@ - -.. _async: - -:c:type:`uv_async_t` --- Async handle -===================================== - -Async handles allow the user to "wakeup" the event loop and get a callback -called from another thread. - - -Data types ----------- - -.. c:type:: uv_async_t - - Async handle type. - -.. c:type:: void (*uv_async_cb)(uv_async_t* handle) - - Type definition for callback passed to :c:func:`uv_async_init`. - - -Public members -^^^^^^^^^^^^^^ - -N/A - -.. seealso:: The :c:type:`uv_handle_t` members also apply. - - -API ---- - -.. c:function:: int uv_async_init(uv_loop_t* loop, uv_async_t* async, uv_async_cb async_cb) - - Initialize the handle. A NULL callback is allowed. - - .. note:: - Unlike other handle initialization functions, it immediately starts the handle. - -.. c:function:: int uv_async_send(uv_async_t* async) - - Wakeup the event loop and call the async handle's callback. - - .. note:: - It's safe to call this function from any thread. The callback will be called on the - loop thread. - - .. warning:: - libuv will coalesce calls to :c:func:`uv_async_send`, that is, not every call to it will - yield an execution of the callback. For example: if :c:func:`uv_async_send` is called 5 - times in a row before the callback is called, the callback will only be called once. If - :c:func:`uv_async_send` is called again after the callback was called, it will be called - again. - -.. seealso:: - The :c:type:`uv_handle_t` API functions also apply. diff --git a/libuv/docs/src/check.rst b/libuv/docs/src/check.rst deleted file mode 100644 index 8d48f22..0000000 --- a/libuv/docs/src/check.rst +++ /dev/null @@ -1,46 +0,0 @@ - -.. _check: - -:c:type:`uv_check_t` --- Check handle -===================================== - -Check handles will run the given callback once per loop iteration, right -after polling for i/o. - - -Data types ----------- - -.. c:type:: uv_check_t - - Check handle type. - -.. c:type:: void (*uv_check_cb)(uv_check_t* handle) - - Type definition for callback passed to :c:func:`uv_check_start`. - - -Public members -^^^^^^^^^^^^^^ - -N/A - -.. seealso:: The :c:type:`uv_handle_t` members also apply. - - -API ---- - -.. c:function:: int uv_check_init(uv_loop_t*, uv_check_t* check) - - Initialize the handle. - -.. c:function:: int uv_check_start(uv_check_t* check, uv_check_cb cb) - - Start the handle with the given callback. - -.. c:function:: int uv_check_stop(uv_check_t* check) - - Stop the handle, the callback will no longer be called. - -.. seealso:: The :c:type:`uv_handle_t` API functions also apply. diff --git a/libuv/docs/src/conf.py b/libuv/docs/src/conf.py deleted file mode 100644 index f614fc5..0000000 --- a/libuv/docs/src/conf.py +++ /dev/null @@ -1,348 +0,0 @@ -# -*- coding: utf-8 -*- -# -# libuv API documentation documentation build configuration file, created by -# sphinx-quickstart on Sun Jul 27 11:47:51 2014. -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import os -import re -import sys - - -def get_libuv_version(): - with open('../../include/uv-version.h') as f: - data = f.read() - try: - m = re.search(r"""^#define UV_VERSION_MAJOR (\d)$""", data, re.MULTILINE) - major = int(m.group(1)) - m = re.search(r"""^#define UV_VERSION_MINOR (\d)$""", data, re.MULTILINE) - minor = int(m.group(1)) - m = re.search(r"""^#define UV_VERSION_PATCH (\d)$""", data, re.MULTILINE) - patch = int(m.group(1)) - m = re.search(r"""^#define UV_VERSION_IS_RELEASE (\d)$""", data, re.MULTILINE) - is_release = int(m.group(1)) - m = re.search(r"""^#define UV_VERSION_SUFFIX \"(\w*)\"$""", data, re.MULTILINE) - suffix = m.group(1) - return '%d.%d.%d%s' % (major, minor, patch, '-%s' % suffix if not is_release else '') - except Exception: - return 'unknown' - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) - -# -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'libuv API documentation' -copyright = u'libuv contributors' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = get_libuv_version() -# The full version, including alpha/beta/rc tags. -release = version - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = [] - -# The reST default role (used for this markup: `text`) to use for all -# documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - -# If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False - - -# -- Options for HTML output ---------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = 'nature' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -html_title = 'libuv API documentation' - -# A shorter title for the navigation bar. Default is the same as html_title. -html_short_title = 'libuv %s API documentation' % version - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -html_logo = 'static/logo.png' - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -html_favicon = 'static/favicon.ico' - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['static'] - -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -#html_extra_path = [] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_domain_indices = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = 'libuv' - - -# -- Options for LaTeX output --------------------------------------------- - -latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - ('index', 'libuv.tex', u'libuv API documentation', - u'libuv contributors', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# If true, show page references after internal links. -#latex_show_pagerefs = False - -# If true, show URL addresses after external links. -#latex_show_urls = False - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_domain_indices = True - - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'libuv', u'libuv API documentation', - [u'libuv contributors'], 1) -] - -# If true, show URL addresses after external links. -#man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ('index', 'libuv', u'libuv API documentation', - u'libuv contributors', 'libuv', 'Cross-platform asynchronous I/O', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -#texinfo_appendices = [] - -# If false, no module index is generated. -#texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -#texinfo_no_detailmenu = False - - -# -- Options for Epub output ---------------------------------------------- - -# Bibliographic Dublin Core info. -epub_title = u'libuv API documentation' -epub_author = u'libuv contributors' -epub_publisher = u'libuv contributors' -epub_copyright = u'2014, libuv contributors' - -# The basename for the epub file. It defaults to the project name. -epub_basename = u'libuv' - -# The HTML theme for the epub output. Since the default themes are not optimized -# for small screen space, using the same theme for HTML and epub output is -# usually not wise. This defaults to 'epub', a theme designed to save visual -# space. -#epub_theme = 'epub' - -# The language of the text. It defaults to the language option -# or en if the language is not set. -#epub_language = '' - -# The scheme of the identifier. Typical schemes are ISBN or URL. -#epub_scheme = '' - -# The unique identifier of the text. This can be a ISBN number -# or the project homepage. -#epub_identifier = '' - -# A unique identification for the text. -#epub_uid = '' - -# A tuple containing the cover image and cover page html template filenames. -#epub_cover = () - -# A sequence of (type, uri, title) tuples for the guide element of content.opf. -#epub_guide = () - -# HTML files that should be inserted before the pages created by sphinx. -# The format is a list of tuples containing the path and title. -#epub_pre_files = [] - -# HTML files shat should be inserted after the pages created by sphinx. -# The format is a list of tuples containing the path and title. -#epub_post_files = [] - -# A list of files that should not be packed into the epub file. -epub_exclude_files = ['search.html'] - -# The depth of the table of contents in toc.ncx. -#epub_tocdepth = 3 - -# Allow duplicate toc entries. -#epub_tocdup = True - -# Choose between 'default' and 'includehidden'. -#epub_tocscope = 'default' - -# Fix unsupported image types using the PIL. -#epub_fix_images = False - -# Scale large images. -#epub_max_image_width = 0 - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -#epub_show_urls = 'inline' - -# If false, no index is generated. -#epub_use_index = True diff --git a/libuv/docs/src/design.rst b/libuv/docs/src/design.rst deleted file mode 100644 index 63141be..0000000 --- a/libuv/docs/src/design.rst +++ /dev/null @@ -1,137 +0,0 @@ - -.. _design: - -Design overview -=============== - -libuv is cross-platform support library which was originally written for NodeJS. It's designed -around the event-driven asynchronous I/O model. - -The library provides much more than simply abstraction over different I/O polling mechanisms: -'handles' and 'streams' provide a high level abstraction for sockets and other entities; -cross-platform file I/O and threading functionality is also provided, amongst other things. - -Here is a diagram illustrating the different parts that compose libuv and what subsystem they -relate to: - -.. image:: static/architecture.png - :scale: 75% - :align: center - - -Handles and requests -^^^^^^^^^^^^^^^^^^^^ - -libuv provides users with 2 abstractions to work with, in combination with the event loop: -handles and requests. - -Handles represent long-lived objects capable of performing certain operations while active. Some -examples: a prepare handle gets its callback called once every loop iteration when active, and -a TCP server handle get its connection callback called every time there is a new connection. - -Requests represent (typically) short-lived operations. These operations can be performed over a -handle: write requests are used to write data on a handle; or standalone: getaddrinfo requests -don't need a handle they run directly on the loop. - - -The I/O loop -^^^^^^^^^^^^ - -The I/O (or event) loop is the central part of libuv. It establishes the content for all I/O -operations, and it's meant to be tied to a single thread. One can run multiple event loops -as long as each runs in a different thread. The libuv event loop (or any other API involving -the loop or handles, for that matter) **is not thread-safe** except stated otherwise. - -The event loop follows the rather usual single threaded asynchronous I/O approach: all (network) -I/O is performed on non-blocking sockets which are polled using the best mechanism available -on the given platform: epoll on Linux, kqueue on OSX and other BSDs, event ports on SunOS and IOCP -on Windows. As part of a loop iteration the loop will block waiting for I/O activity on sockets -which have been added to the poller and callbacks will be fired indicating socket conditions -(readable, writable hangup) so handles can read, write or perform the desired I/O operation. - -In order to better understand how the event loop operates, the following diagram illustrates all -stages of a loop iteration: - -.. image:: static/loop_iteration.png - :scale: 75% - :align: center - - -#. The loop concept of 'now' is updated. The event loop caches the current time at the start of - the event loop tick in order to reduce the number of time-related system calls. - -#. If the loop is *alive* an iteration is started, otherwise the loop will exit immediately. So, - when is a loop considered to be *alive*? If a loop has active and ref'd handles, active - requests or closing handles it's considered to be *alive*. - -#. Due timers are run. All active timers scheduled for a time before the loop's concept of *now* - get their callbacks called. - -#. Pending callbacks are called. All I/O callbacks are called right after polling for I/O, for the - most part. There are cases, however, in which calling such a callback is deferred for the next - loop iteration. If the previous iteration deferred any I/O callback it will be run at this point. - -#. Idle handle callbacks are called. Despite the unfortunate name, idle handles are run on every - loop iteration, if they are active. - -#. Prepare handle callbacks are called. Prepare handles get their callbacks called right before - the loop will block for I/O. - -#. Poll timeout is calculated. Before blocking for I/O the loop calculates for how long it should - block. These are the rules when calculating the timeout: - - * If the loop was run with the ``UV_RUN_NOWAIT`` flag, the timeout is 0. - * If the loop is going to be stopped (:c:func:`uv_stop` was called), the timeout is 0. - * If there are no active handles or requests, the timeout is 0. - * If there are any idle handles active, the timeout is 0. - * If there are any handles pending to be closed, the timeout is 0. - * If none of the above cases was matched, the timeout of the closest timer is taken, or - if there are no active timers, infinity. - -#. The loop blocks for I/O. At this point the loop will block for I/O for the timeout calculated - on the previous step. All I/O related handles that were monitoring a given file descriptor - for a read or write operation get their callbacks called at this point. - -#. Check handle callbacks are called. Check handles get their callbacks called right after the - loop has blocked for I/O. Check handles are essentially the counterpart of prepare handles. - -#. Close callbacks are called. If a handle was closed by calling :c:func:`uv_close` it will - get the close callback called. - -#. Special case in case the loop was run with ``UV_RUN_ONCE``, as it implies forward progress. - It's possible that no I/O callbacks were fired after blocking for I/O, but some time has passed - so there might be timers which are due, those timers get their callbacks called. - -#. Iteration ends. If the loop was run with ``UV_RUN_NOWAIT`` or ``UV_RUN_ONCE`` modes the - iteration is ended and :c:func:`uv_run` will return. If the loop was run with ``UV_RUN_DEFAULT`` - it will continue from the start if it's still *alive*, otherwise it will also end. - - -.. important:: - libuv uses a thread pool to make asynchronous file I/O operations possible, but - network I/O is **always** performed in a single thread, each loop's thread. - -.. note:: - While the polling mechanism is different, libuv makes the execution model consistent - Unix systems and Windows. - - -File I/O -^^^^^^^^ - -Unlike network I/O, there are no platform-specific file I/O primitives libuv could rely on, -so the current approach is to run blocking file I/O operations in a thread pool. - -For a thorough explanation of the cross-platform file I/O landscape, checkout -`this post `_. - -libuv currently uses a global thread pool on which all loops can queue work on. 3 types of -operations are currently run on this pool: - - * Filesystem operations - * DNS functions (getaddrinfo and getnameinfo) - * User specified code via :c:func:`uv_queue_work` - -.. warning:: - See the :c:ref:`threadpool` section for more details, but keep in mind the thread pool size - is quite limited. diff --git a/libuv/docs/src/dll.rst b/libuv/docs/src/dll.rst deleted file mode 100644 index 3fb11e1..0000000 --- a/libuv/docs/src/dll.rst +++ /dev/null @@ -1,44 +0,0 @@ - -.. _dll: - -Shared library handling -======================= - -libuv provides cross platform utilities for loading shared libraries and -retrieving symbols from them, using the following API. - - -Data types ----------- - -.. c:type:: uv_lib_t - - Shared library data type. - - -Public members -^^^^^^^^^^^^^^ - -N/A - - -API ---- - -.. c:function:: int uv_dlopen(const char* filename, uv_lib_t* lib) - - Opens a shared library. The filename is in utf-8. Returns 0 on success and - -1 on error. Call :c:func:`uv_dlerror` to get the error message. - -.. c:function:: void uv_dlclose(uv_lib_t* lib) - - Close the shared library. - -.. c:function:: uv_dlsym(uv_lib_t* lib, const char* name, void** ptr) - - Retrieves a data pointer from a dynamic library. It is legal for a symbol - to map to NULL. Returns 0 on success and -1 if the symbol was not found. - -.. c:function:: const char* uv_dlerror(const uv_lib_t* lib) - - Returns the last uv_dlopen() or uv_dlsym() error message. diff --git a/libuv/docs/src/dns.rst b/libuv/docs/src/dns.rst deleted file mode 100644 index 3b15377..0000000 --- a/libuv/docs/src/dns.rst +++ /dev/null @@ -1,96 +0,0 @@ - -.. _dns: - -DNS utility functions -===================== - -libuv provides asynchronous variants of `getaddrinfo` and `getnameinfo`. - - -Data types ----------- - -.. c:type:: uv_getaddrinfo_t - - `getaddrinfo` request type. - -.. c:type:: void (*uv_getaddrinfo_cb)(uv_getaddrinfo_t* req, int status, struct addrinfo* res) - - Callback which will be called with the getaddrinfo request result once - complete. In case it was cancelled, `status` will have a value of - ``UV_ECANCELED``. - -.. c:type:: uv_getnameinfo_t - - `getnameinfo` request type. - -.. c:type:: void (*uv_getnameinfo_cb)(uv_getnameinfo_t* req, int status, const char* hostname, const char* service) - - Callback which will be called with the getnameinfo request result once - complete. In case it was cancelled, `status` will have a value of - ``UV_ECANCELED``. - - -Public members -^^^^^^^^^^^^^^ - -.. c:member:: uv_loop_t* uv_getaddrinfo_t.loop - - Loop that started this getaddrinfo request and where completion will be - reported. Readonly. - -.. c:member:: struct addrinfo* uv_getaddrinfo_t.addrinfo - - Pointer to a `struct addrinfo` containing the result. Must be freed by the user - with :c:func:`uv_freeaddrinfo`. - - .. versionchanged:: 1.3.0 the field is declared as public. - -.. c:member:: uv_loop_t* uv_getnameinfo_t.loop - - Loop that started this getnameinfo request and where completion will be - reported. Readonly. - -.. seealso:: The :c:type:`uv_req_t` members also apply. - - -API ---- - -.. c:function:: int uv_getaddrinfo(uv_loop_t* loop, uv_getaddrinfo_t* req, uv_getaddrinfo_cb getaddrinfo_cb, const char* node, const char* service, const struct addrinfo* hints) - - Asynchronous ``getaddrinfo(3)``. - - Either node or service may be NULL but not both. - - `hints` is a pointer to a struct addrinfo with additional address type - constraints, or NULL. Consult `man -s 3 getaddrinfo` for more details. - - Returns 0 on success or an error code < 0 on failure. If successful, the - callback will get called sometime in the future with the lookup result, - which is either: - - * status == 0, the res argument points to a valid `struct addrinfo`, or - * status < 0, the res argument is NULL. See the UV_EAI_* constants. - - Call :c:func:`uv_freeaddrinfo` to free the addrinfo structure. - - .. versionchanged:: 1.3.0 the callback parameter is now allowed to be NULL, - in which case the request will run **synchronously**. - -.. c:function:: void uv_freeaddrinfo(struct addrinfo* ai) - - Free the struct addrinfo. Passing NULL is allowed and is a no-op. - -.. c:function:: int uv_getnameinfo(uv_loop_t* loop, uv_getnameinfo_t* req, uv_getnameinfo_cb getnameinfo_cb, const struct sockaddr* addr, int flags) - - Asynchronous ``getnameinfo(3)``. - - Returns 0 on success or an error code < 0 on failure. If successful, the - callback will get called sometime in the future with the lookup result. - Consult `man -s 3 getnameinfo` for more details. - - .. versionchanged:: 1.3.0 the callback parameter is now allowed to be NULL, - in which case the request will run **synchronously**. - -.. seealso:: The :c:type:`uv_req_t` API functions also apply. diff --git a/libuv/docs/src/errors.rst b/libuv/docs/src/errors.rst deleted file mode 100644 index 5d59dc3..0000000 --- a/libuv/docs/src/errors.rst +++ /dev/null @@ -1,329 +0,0 @@ - -.. _errors: - -Error handling -============== - -In libuv errors are negative numbered constants. As a rule of thumb, whenever -there is a status parameter, or an API functions returns an integer, a negative -number will imply an error. - -.. note:: - Implementation detail: on Unix error codes are the negated `errno` (or `-errno`), while on - Windows they are defined by libuv to arbitrary negative numbers. - - -Error constants ---------------- - -.. c:macro:: UV_E2BIG - - argument list too long - -.. c:macro:: UV_EACCES - - permission denied - -.. c:macro:: UV_EADDRINUSE - - address already in use - -.. c:macro:: UV_EADDRNOTAVAIL - - address not available - -.. c:macro:: UV_EAFNOSUPPORT - - address family not supported - -.. c:macro:: UV_EAGAIN - - resource temporarily unavailable - -.. c:macro:: UV_EAI_ADDRFAMILY - - address family not supported - -.. c:macro:: UV_EAI_AGAIN - - temporary failure - -.. c:macro:: UV_EAI_BADFLAGS - - bad ai_flags value - -.. c:macro:: UV_EAI_BADHINTS - - invalid value for hints - -.. c:macro:: UV_EAI_CANCELED - - request canceled - -.. c:macro:: UV_EAI_FAIL - - permanent failure - -.. c:macro:: UV_EAI_FAMILY - - ai_family not supported - -.. c:macro:: UV_EAI_MEMORY - - out of memory - -.. c:macro:: UV_EAI_NODATA - - no address - -.. c:macro:: UV_EAI_NONAME - - unknown node or service - -.. c:macro:: UV_EAI_OVERFLOW - - argument buffer overflow - -.. c:macro:: UV_EAI_PROTOCOL - - resolved protocol is unknown - -.. c:macro:: UV_EAI_SERVICE - - service not available for socket type - -.. c:macro:: UV_EAI_SOCKTYPE - - socket type not supported - -.. c:macro:: UV_EALREADY - - connection already in progress - -.. c:macro:: UV_EBADF - - bad file descriptor - -.. c:macro:: UV_EBUSY - - resource busy or locked - -.. c:macro:: UV_ECANCELED - - operation canceled - -.. c:macro:: UV_ECHARSET - - invalid Unicode character - -.. c:macro:: UV_ECONNABORTED - - software caused connection abort - -.. c:macro:: UV_ECONNREFUSED - - connection refused - -.. c:macro:: UV_ECONNRESET - - connection reset by peer - -.. c:macro:: UV_EDESTADDRREQ - - destination address required - -.. c:macro:: UV_EEXIST - - file already exists - -.. c:macro:: UV_EFAULT - - bad address in system call argument - -.. c:macro:: UV_EFBIG - - file too large - -.. c:macro:: UV_EHOSTUNREACH - - host is unreachable - -.. c:macro:: UV_EINTR - - interrupted system call - -.. c:macro:: UV_EINVAL - - invalid argument - -.. c:macro:: UV_EIO - - i/o error - -.. c:macro:: UV_EISCONN - - socket is already connected - -.. c:macro:: UV_EISDIR - - illegal operation on a directory - -.. c:macro:: UV_ELOOP - - too many symbolic links encountered - -.. c:macro:: UV_EMFILE - - too many open files - -.. c:macro:: UV_EMSGSIZE - - message too long - -.. c:macro:: UV_ENAMETOOLONG - - name too long - -.. c:macro:: UV_ENETDOWN - - network is down - -.. c:macro:: UV_ENETUNREACH - - network is unreachable - -.. c:macro:: UV_ENFILE - - file table overflow - -.. c:macro:: UV_ENOBUFS - - no buffer space available - -.. c:macro:: UV_ENODEV - - no such device - -.. c:macro:: UV_ENOENT - - no such file or directory - -.. c:macro:: UV_ENOMEM - - not enough memory - -.. c:macro:: UV_ENONET - - machine is not on the network - -.. c:macro:: UV_ENOPROTOOPT - - protocol not available - -.. c:macro:: UV_ENOSPC - - no space left on device - -.. c:macro:: UV_ENOSYS - - function not implemented - -.. c:macro:: UV_ENOTCONN - - socket is not connected - -.. c:macro:: UV_ENOTDIR - - not a directory - -.. c:macro:: UV_ENOTEMPTY - - directory not empty - -.. c:macro:: UV_ENOTSOCK - - socket operation on non-socket - -.. c:macro:: UV_ENOTSUP - - operation not supported on socket - -.. c:macro:: UV_EPERM - - operation not permitted - -.. c:macro:: UV_EPIPE - - broken pipe - -.. c:macro:: UV_EPROTO - - protocol error - -.. c:macro:: UV_EPROTONOSUPPORT - - protocol not supported - -.. c:macro:: UV_EPROTOTYPE - - protocol wrong type for socket - -.. c:macro:: UV_ERANGE - - result too large - -.. c:macro:: UV_EROFS - - read-only file system - -.. c:macro:: UV_ESHUTDOWN - - cannot send after transport endpoint shutdown - -.. c:macro:: UV_ESPIPE - - invalid seek - -.. c:macro:: UV_ESRCH - - no such process - -.. c:macro:: UV_ETIMEDOUT - - connection timed out - -.. c:macro:: UV_ETXTBSY - - text file is busy - -.. c:macro:: UV_EXDEV - - cross-device link not permitted - -.. c:macro:: UV_UNKNOWN - - unknown error - -.. c:macro:: UV_EOF - - end of file - -.. c:macro:: UV_ENXIO - - no such device or address - -.. c:macro:: UV_EMLINK - - too many links - - -API ---- - -.. c:function:: const char* uv_strerror(int err) - - Returns the error message for the given error code. - -.. c:function:: const char* uv_err_name(int err) - - Returns the error name for the given error code. diff --git a/libuv/docs/src/fs.rst b/libuv/docs/src/fs.rst deleted file mode 100644 index cd535f7..0000000 --- a/libuv/docs/src/fs.rst +++ /dev/null @@ -1,278 +0,0 @@ - -.. _fs: - -Filesystem operations -===================== - -libuv provides a wide variety of cross-platform sync and async filesystem -operations. All functions defined in this document take a callback, which is -allowed to be NULL. If the callback is NULL the request is completed synchronously, -otherwise it will be performed asynchronously. - -All file operations are run on the threadpool, see :ref:`threadpool` for information -on the threadpool size. - - -Data types ----------- - -.. c:type:: uv_fs_t - - Filesystem request type. - -.. c:type:: uv_timespec_t - - Portable equivalent of ``struct timespec``. - - :: - - typedef struct { - long tv_sec; - long tv_nsec; - } uv_timespec_t; - -.. c:type:: uv_stat_t - - Portable equivalent of ``struct stat``. - - :: - - typedef struct { - uint64_t st_dev; - uint64_t st_mode; - uint64_t st_nlink; - uint64_t st_uid; - uint64_t st_gid; - uint64_t st_rdev; - uint64_t st_ino; - uint64_t st_size; - uint64_t st_blksize; - uint64_t st_blocks; - uint64_t st_flags; - uint64_t st_gen; - uv_timespec_t st_atim; - uv_timespec_t st_mtim; - uv_timespec_t st_ctim; - uv_timespec_t st_birthtim; - } uv_stat_t; - -.. c:type:: uv_fs_type - - Filesystem request type. - - :: - - typedef enum { - UV_FS_UNKNOWN = -1, - UV_FS_CUSTOM, - UV_FS_OPEN, - UV_FS_CLOSE, - UV_FS_READ, - UV_FS_WRITE, - UV_FS_SENDFILE, - UV_FS_STAT, - UV_FS_LSTAT, - UV_FS_FSTAT, - UV_FS_FTRUNCATE, - UV_FS_UTIME, - UV_FS_FUTIME, - UV_FS_ACCESS, - UV_FS_CHMOD, - UV_FS_FCHMOD, - UV_FS_FSYNC, - UV_FS_FDATASYNC, - UV_FS_UNLINK, - UV_FS_RMDIR, - UV_FS_MKDIR, - UV_FS_MKDTEMP, - UV_FS_RENAME, - UV_FS_SCANDIR, - UV_FS_LINK, - UV_FS_SYMLINK, - UV_FS_READLINK, - UV_FS_CHOWN, - UV_FS_FCHOWN - } uv_fs_type; - -.. c:type:: uv_dirent_t - - Cross platform (reduced) equivalent of ``struct dirent``. - Used in :c:func:`uv_fs_scandir_next`. - - :: - - typedef enum { - UV_DIRENT_UNKNOWN, - UV_DIRENT_FILE, - UV_DIRENT_DIR, - UV_DIRENT_LINK, - UV_DIRENT_FIFO, - UV_DIRENT_SOCKET, - UV_DIRENT_CHAR, - UV_DIRENT_BLOCK - } uv_dirent_type_t; - - typedef struct uv_dirent_s { - const char* name; - uv_dirent_type_t type; - } uv_dirent_t; - - -Public members -^^^^^^^^^^^^^^ - -.. c:member:: uv_loop_t* uv_fs_t.loop - - Loop that started this request and where completion will be reported. - Readonly. - -.. c:member:: uv_fs_type uv_fs_t.fs_type - - FS request type. - -.. c:member:: const char* uv_fs_t.path - - Path affecting the request. - -.. c:member:: ssize_t uv_fs_t.result - - Result of the request. < 0 means error, success otherwise. On requests such - as :c:func:`uv_fs_read` or :c:func:`uv_fs_write` it indicates the amount of - data that was read or written, respectively. - -.. c:member:: uv_stat_t uv_fs_t.statbuf - - Stores the result of :c:func:`uv_fs_stat` and other stat requests. - -.. c:member:: void* uv_fs_t.ptr - - Stores the result of :c:func:`uv_fs_readlink` and serves as an alias to - `statbuf`. - -.. seealso:: The :c:type:`uv_req_t` members also apply. - - -API ---- - -.. c:function:: void uv_fs_req_cleanup(uv_fs_t* req) - - Cleanup request. Must be called after a request is finished to deallocate - any memory libuv might have allocated. - -.. c:function:: int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) - - Equivalent to ``close(2)``. - -.. c:function:: int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int mode, uv_fs_cb cb) - - Equivalent to ``open(2)``. - -.. c:function:: int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb) - - Equivalent to ``preadv(2)``. - -.. c:function:: int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) - - Equivalent to ``unlink(2)``. - -.. c:function:: int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb) - - Equivalent to ``pwritev(2)``. - -.. c:function:: int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb) - - Equivalent to ``mkdir(2)``. - - .. note:: - `mode` is currently not implemented on Windows. - -.. c:function:: int uv_fs_mkdtemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl, uv_fs_cb cb) - - Equivalent to ``mkdtemp(3)``. - - .. note:: - The result can be found as a null terminated string at `req->path`. - -.. c:function:: int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) - - Equivalent to ``rmdir(2)``. - -.. c:function:: int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb) -.. c:function:: int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) - - Equivalent to ``scandir(3)``, with a slightly different API. Once the callback - for the request is called, the user can use :c:func:`uv_fs_scandir_next` to - get `ent` populated with the next directory entry data. When there are no - more entries ``UV_EOF`` will be returned. - -.. c:function:: int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) -.. c:function:: int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) -.. c:function:: int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) - - Equivalent to ``(f/l)stat(2)``. - -.. c:function:: int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb) - - Equivalent to ``rename(2)``. - -.. c:function:: int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) - - Equivalent to ``fsync(2)``. - -.. c:function:: int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) - - Equivalent to ``fdatasync(2)``. - -.. c:function:: int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file file, int64_t offset, uv_fs_cb cb) - - Equivalent to ``ftruncate(2)``. - -.. c:function:: int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file out_fd, uv_file in_fd, int64_t in_offset, size_t length, uv_fs_cb cb) - - Limited equivalent to ``sendfile(2)``. - -.. c:function:: int uv_fs_access(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb) - - Equivalent to ``access(2)`` on Unix. Windows uses ``GetFileAttributesW()``. - -.. c:function:: int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb) -.. c:function:: int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, int mode, uv_fs_cb cb) - - Equivalent to ``(f)chmod(2)``. - -.. c:function:: int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb) -.. c:function:: int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime, double mtime, uv_fs_cb cb) - - Equivalent to ``(f)utime(s)(2)``. - -.. c:function:: int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb) - - Equivalent to ``link(2)``. - -.. c:function:: int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, int flags, uv_fs_cb cb) - - Equivalent to ``symlink(2)``. - - .. note:: - On Windows the `flags` parameter can be specified to control how the symlink will - be created: - - * ``UV_FS_SYMLINK_DIR``: indicates that `path` points to a directory. - - * ``UV_FS_SYMLINK_JUNCTION``: request that the symlink is created - using junction points. - -.. c:function:: int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) - - Equivalent to ``readlink(2)``. - -.. c:function:: int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb) -.. c:function:: int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb) - - Equivalent to ``(f)chown(2)``. - - .. note:: - These functions are not implemented on Windows. - -.. seealso:: The :c:type:`uv_req_t` API functions also apply. diff --git a/libuv/docs/src/fs_event.rst b/libuv/docs/src/fs_event.rst deleted file mode 100644 index 681ae52..0000000 --- a/libuv/docs/src/fs_event.rst +++ /dev/null @@ -1,108 +0,0 @@ - -.. _fs_event: - -:c:type:`uv_fs_event_t` --- FS Event handle -=========================================== - -FS Event handles allow the user to monitor a given path for changes, for example, -if the file was renamed or there was a generic change in it. This handle uses -the best backend for the job on each platform. - - -Data types ----------- - -.. c:type:: uv_fs_event_t - - FS Event handle type. - -.. c:type:: void (*uv_fs_event_cb)(uv_fs_event_t* handle, const char* filename, int events, int status) - - Callback passed to :c:func:`uv_fs_event_start` which will be called repeatedly - after the handle is started. If the handle was started with a directory the - `filename` parameter will be a relative path to a file contained in the directory. - The `events` parameter is an ORed mask of :c:type:`uv_fs_event` elements. - -.. c:type:: uv_fs_event - - Event types that :c:type:`uv_fs_event_t` handles monitor. - - :: - - enum uv_fs_event { - UV_RENAME = 1, - UV_CHANGE = 2 - }; - -.. c:type:: uv_fs_event_flags - - Flags that can be passed to :c:func:`uv_fs_event_start` to control its - behavior. - - :: - - enum uv_fs_event_flags { - /* - * By default, if the fs event watcher is given a directory name, we will - * watch for all events in that directory. This flags overrides this behavior - * and makes fs_event report only changes to the directory entry itself. This - * flag does not affect individual files watched. - * This flag is currently not implemented yet on any backend. - */ - UV_FS_EVENT_WATCH_ENTRY = 1, - /* - * By default uv_fs_event will try to use a kernel interface such as inotify - * or kqueue to detect events. This may not work on remote filesystems such - * as NFS mounts. This flag makes fs_event fall back to calling stat() on a - * regular interval. - * This flag is currently not implemented yet on any backend. - */ - UV_FS_EVENT_STAT = 2, - /* - * By default, event watcher, when watching directory, is not registering - * (is ignoring) changes in it's subdirectories. - * This flag will override this behaviour on platforms that support it. - */ - UV_FS_EVENT_RECURSIVE = 4 - }; - - -Public members -^^^^^^^^^^^^^^ - -N/A - -.. seealso:: The :c:type:`uv_handle_t` members also apply. - - -API ---- - -.. c:function:: int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) - - Initialize the handle. - -.. c:function:: int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb, const char* path, unsigned int flags) - - Start the handle with the given callback, which will watch the specified - `path` for changes. `flags` can be an ORed mask of :c:type:`uv_fs_event_flags`. - - .. note:: Currently the only supported flag is ``UV_FS_EVENT_RECURSIVE`` and - only on OSX. - -.. c:function:: int uv_fs_event_stop(uv_fs_event_t* handle) - - Stop the handle, the callback will no longer be called. - -.. c:function:: int uv_fs_event_getpath(uv_fs_event_t* handle, char* buffer, size_t* size) - - Get the path being monitored by the handle. The buffer must be preallocated - by the user. Returns 0 on success or an error code < 0 in case of failure. - On success, `buffer` will contain the path and `size` its length. If the buffer - is not big enough UV_ENOBUFS will be returned and len will be set to the - required size. - - .. versionchanged:: 1.3.0 the returned length no longer includes the terminating null byte, - and the buffer is not null terminated. - -.. seealso:: The :c:type:`uv_handle_t` API functions also apply. diff --git a/libuv/docs/src/fs_poll.rst b/libuv/docs/src/fs_poll.rst deleted file mode 100644 index 4efb244..0000000 --- a/libuv/docs/src/fs_poll.rst +++ /dev/null @@ -1,72 +0,0 @@ - -.. _fs_poll: - -:c:type:`uv_fs_poll_t` --- FS Poll handle -========================================= - -FS Poll handles allow the user to monitor a given path for changes. Unlike -:c:type:`uv_fs_event_t`, fs poll handles use `stat` to detect when a file has -changed so they can work on file systems where fs event handles can't. - - -Data types ----------- - -.. c:type:: uv_fs_poll_t - - FS Poll handle type. - -.. c:type:: void (*uv_fs_poll_cb)(uv_fs_poll_t* handle, int status, const uv_stat_t* prev, const uv_stat_t* curr) - - Callback passed to :c:func:`uv_fs_poll_start` which will be called repeatedly - after the handle is started, when any change happens to the monitored path. - - The callback is invoked with `status < 0` if `path` does not exist - or is inaccessible. The watcher is *not* stopped but your callback is - not called again until something changes (e.g. when the file is created - or the error reason changes). - - When `status == 0`, the callback receives pointers to the old and new - :c:type:`uv_stat_t` structs. They are valid for the duration of the - callback only. - - -Public members -^^^^^^^^^^^^^^ - -N/A - -.. seealso:: The :c:type:`uv_handle_t` members also apply. - - -API ---- - -.. c:function:: int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle) - - Initialize the handle. - -.. c:function:: int uv_fs_poll_start(uv_fs_poll_t* handle, uv_fs_poll_cb poll_cb, const char* path, unsigned int interval) - - Check the file at `path` for changes every `interval` milliseconds. - - .. note:: - For maximum portability, use multi-second intervals. Sub-second intervals will not detect - all changes on many file systems. - -.. c:function:: int uv_fs_poll_stop(uv_fs_poll_t* handle) - - Stop the handle, the callback will no longer be called. - -.. c:function:: int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buffer, size_t* size) - - Get the path being monitored by the handle. The buffer must be preallocated - by the user. Returns 0 on success or an error code < 0 in case of failure. - On success, `buffer` will contain the path and `size` its length. If the buffer - is not big enough UV_ENOBUFS will be returned and len will be set to the - required size. - - .. versionchanged:: 1.3.0 the returned length no longer includes the terminating null byte, - and the buffer is not null terminated. - -.. seealso:: The :c:type:`uv_handle_t` API functions also apply. diff --git a/libuv/docs/src/handle.rst b/libuv/docs/src/handle.rst deleted file mode 100644 index 6ba597a..0000000 --- a/libuv/docs/src/handle.rst +++ /dev/null @@ -1,181 +0,0 @@ - -.. _handle: - -:c:type:`uv_handle_t` --- Base handle -===================================== - -`uv_handle_t` is the base type for all libuv handle types. - -Structures are aligned so that any libuv handle can be cast to `uv_handle_t`. -All API functions defined here work with any handle type. - - -Data types ----------- - -.. c:type:: uv_handle_t - - The base libuv handle type. - -.. c:type:: uv_any_handle - - Union of all handle types. - -.. c:type:: void (*uv_alloc_cb)(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) - - Type definition for callback passed to :c:func:`uv_read_start` and - :c:func:`uv_udp_recv_start`. The user must fill the supplied :c:type:`uv_buf_t` - structure with whatever size, as long as it's > 0. A suggested size (65536 at the moment) - is provided, but it doesn't need to be honored. Setting the buffer's length to 0 - will trigger a ``UV_ENOBUFS`` error in the :c:type:`uv_udp_recv_cb` or - :c:type:`uv_read_cb` callback. - -.. c:type:: void (*uv_close_cb)(uv_handle_t* handle) - - Type definition for callback passed to :c:func:`uv_close`. - - -Public members -^^^^^^^^^^^^^^ - -.. c:member:: uv_loop_t* uv_handle_t.loop - - Pointer to the :c:type:`uv_loop_t` where the handle is running on. Readonly. - -.. c:member:: void* uv_handle_t.data - - Space for user-defined arbitrary data. libuv does not use this field. - - -API ---- - -.. c:function:: int uv_is_active(const uv_handle_t* handle) - - Returns non-zero if the handle is active, zero if it's inactive. What - "active" means depends on the type of handle: - - - A uv_async_t handle is always active and cannot be deactivated, except - by closing it with uv_close(). - - - A uv_pipe_t, uv_tcp_t, uv_udp_t, etc. handle - basically any handle that - deals with i/o - is active when it is doing something that involves i/o, - like reading, writing, connecting, accepting new connections, etc. - - - A uv_check_t, uv_idle_t, uv_timer_t, etc. handle is active when it has - been started with a call to uv_check_start(), uv_idle_start(), etc. - - Rule of thumb: if a handle of type `uv_foo_t` has a `uv_foo_start()` - function, then it's active from the moment that function is called. - Likewise, `uv_foo_stop()` deactivates the handle again. - -.. c:function:: int uv_is_closing(const uv_handle_t* handle) - - Returns non-zero if the handle is closing or closed, zero otherwise. - - .. note:: - This function should only be used between the initialization of the handle and the - arrival of the close callback. - -.. c:function:: void uv_close(uv_handle_t* handle, uv_close_cb close_cb) - - Request handle to be closed. `close_cb` will be called asynchronously after - this call. This MUST be called on each handle before memory is released. - - Handles that wrap file descriptors are closed immediately but - `close_cb` will still be deferred to the next iteration of the event loop. - It gives you a chance to free up any resources associated with the handle. - - In-progress requests, like uv_connect_t or uv_write_t, are cancelled and - have their callbacks called asynchronously with status=UV_ECANCELED. - -.. c:function:: void uv_ref(uv_handle_t* handle) - - Reference the given handle. References are idempotent, that is, if a handle - is already referenced calling this function again will have no effect. - - See :ref:`refcount`. - -.. c:function:: void uv_unref(uv_handle_t* handle) - - Un-reference the given handle. References are idempotent, that is, if a handle - is not referenced calling this function again will have no effect. - - See :ref:`refcount`. - -.. c:function:: int uv_has_ref(const uv_handle_t* handle) - - Returns non-zero if the handle referenced, zero otherwise. - - See :ref:`refcount`. - -.. c:function:: size_t uv_handle_size(uv_handle_type type) - - Returns the size of the given handle type. Useful for FFI binding writers - who don't want to know the structure layout. - - -Miscellaneous API functions ---------------------------- - -The following API functions take a :c:type:`uv_handle_t` argument but they work -just for some handle types. - -.. c:function:: int uv_send_buffer_size(uv_handle_t* handle, int* value) - - Gets or sets the size of the send buffer that the operating - system uses for the socket. - - If `*value` == 0, it will return the current send buffer size, - otherwise it will use `*value` to set the new send buffer size. - - This function works for TCP, pipe and UDP handles on Unix and for TCP and - UDP handles on Windows. - - .. note:: - Linux will set double the size and return double the size of the original set value. - -.. c:function:: int uv_recv_buffer_size(uv_handle_t* handle, int* value) - - Gets or sets the size of the receive buffer that the operating - system uses for the socket. - - If `*value` == 0, it will return the current receive buffer size, - otherwise it will use `*value` to set the new receive buffer size. - - This function works for TCP, pipe and UDP handles on Unix and for TCP and - UDP handles on Windows. - - .. note:: - Linux will set double the size and return double the size of the original set value. - -.. c:function:: int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd) - - Gets the platform dependent file descriptor equivalent. - - The following handles are supported: TCP, pipes, TTY, UDP and poll. Passing - any other handle type will fail with `UV_EINVAL`. - - If a handle doesn't have an attached file descriptor yet or the handle - itself has been closed, this function will return `UV_EBADF`. - - .. warning:: - Be very careful when using this function. libuv assumes it's in control of the file - descriptor so any change to it may lead to malfunction. - - -.. _refcount: - -Reference counting ------------------- - -The libuv event loop (if run in the default mode) will run until there are no -active `and` referenced handles left. The user can force the loop to exit early -by unreferencing handles which are active, for example by calling :c:func:`uv_unref` -after calling :c:func:`uv_timer_start`. - -A handle can be referenced or unreferenced, the refcounting scheme doesn't use -a counter, so both operations are idempotent. - -All handles are referenced when active by default, see :c:func:`uv_is_active` -for a more detailed explanation on what being `active` involves. diff --git a/libuv/docs/src/idle.rst b/libuv/docs/src/idle.rst deleted file mode 100644 index 81f51d2..0000000 --- a/libuv/docs/src/idle.rst +++ /dev/null @@ -1,54 +0,0 @@ - -.. _idle: - -:c:type:`uv_idle_t` --- Idle handle -=================================== - -Idle handles will run the given callback once per loop iteration, right -before the :c:type:`uv_prepare_t` handles. - -.. note:: - The notable difference with prepare handles is that when there are active idle handles, - the loop will perform a zero timeout poll instead of blocking for i/o. - -.. warning:: - Despite the name, idle handles will get their callbacks called on every loop iteration, - not when the loop is actually "idle". - - -Data types ----------- - -.. c:type:: uv_idle_t - - Idle handle type. - -.. c:type:: void (*uv_idle_cb)(uv_idle_t* handle) - - Type definition for callback passed to :c:func:`uv_idle_start`. - - -Public members -^^^^^^^^^^^^^^ - -N/A - -.. seealso:: The :c:type:`uv_handle_t` members also apply. - - -API ---- - -.. c:function:: int uv_idle_init(uv_loop_t*, uv_idle_t* idle) - - Initialize the handle. - -.. c:function:: int uv_idle_start(uv_idle_t* idle, uv_idle_cb cb) - - Start the handle with the given callback. - -.. c:function:: int uv_idle_stop(uv_idle_t* idle) - - Stop the handle, the callback will no longer be called. - -.. seealso:: The :c:type:`uv_handle_t` API functions also apply. diff --git a/libuv/docs/src/index.rst b/libuv/docs/src/index.rst deleted file mode 100644 index 9cdc494..0000000 --- a/libuv/docs/src/index.rst +++ /dev/null @@ -1,94 +0,0 @@ - -Welcome to the libuv API documentation -====================================== - -Overview --------- - -libuv is a multi-platform support library with a focus on asynchronous I/O. It -was primarily developed for use by `Node.js`_, but it's also used by `Luvit`_, -`Julia`_, `pyuv`_, and `others`_. - -.. note:: - In case you find errors in this documentation you can help by sending - `pull requests `_! - -.. _Node.js: http://nodejs.org -.. _Luvit: http://luvit.io -.. _Julia: http://julialang.org -.. _pyuv: https://github.com/saghul/pyuv -.. _others: https://github.com/libuv/libuv/wiki/Projects-that-use-libuv - - -Features --------- - -* Full-featured event loop backed by epoll, kqueue, IOCP, event ports. -* Asynchronous TCP and UDP sockets -* Asynchronous DNS resolution -* Asynchronous file and file system operations -* File system events -* ANSI escape code controlled TTY -* IPC with socket sharing, using Unix domain sockets or named pipes (Windows) -* Child processes -* Thread pool -* Signal handling -* High resolution clock -* Threading and synchronization primitives - - -Downloads ---------- - -libuv can be downloaded from `here `_. - - -Installation ------------- - -Installation instructions can be found on `the README `_. - - -Upgrading ---------- - -Migration guides for different libuv versions, starting with 1.0. - -.. toctree:: - :maxdepth: 1 - - migration_010_100 - - -Documentation -------------- - -.. toctree:: - :maxdepth: 1 - - design - errors - loop - handle - request - timer - prepare - check - idle - async - poll - signal - process - stream - tcp - pipe - tty - udp - fs_event - fs_poll - fs - threadpool - dns - dll - threading - misc diff --git a/libuv/docs/src/loop.rst b/libuv/docs/src/loop.rst deleted file mode 100644 index 203672b..0000000 --- a/libuv/docs/src/loop.rst +++ /dev/null @@ -1,164 +0,0 @@ - -.. _loop: - -:c:type:`uv_loop_t` --- Event loop -================================== - -The event loop is the central part of libuv's functionality. It takes care -of polling for i/o and scheduling callbacks to be run based on different sources -of events. - - -Data types ----------- - -.. c:type:: uv_loop_t - - Loop data type. - -.. c:type:: uv_run_mode - - Mode used to run the loop with :c:func:`uv_run`. - - :: - - typedef enum { - UV_RUN_DEFAULT = 0, - UV_RUN_ONCE, - UV_RUN_NOWAIT - } uv_run_mode; - -.. c:type:: void (*uv_walk_cb)(uv_handle_t* handle, void* arg) - - Type definition for callback passed to :c:func:`uv_walk`. - - -Public members -^^^^^^^^^^^^^^ - -.. c:member:: void* uv_loop_t.data - - Space for user-defined arbitrary data. libuv does not use this field. libuv does, however, - initialize it to NULL in :c:func:`uv_loop_init`, and it poisons the value (on debug builds) - on :c:func:`uv_loop_close`. - - -API ---- - -.. c:function:: int uv_loop_init(uv_loop_t* loop) - - Initializes the given `uv_loop_t` structure. - -.. c:function:: int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...) - - .. versionadded:: 1.0.2 - - Set additional loop options. You should normally call this before the - first call to :c:func:`uv_run` unless mentioned otherwise. - - Returns 0 on success or a UV_E* error code on failure. Be prepared to - handle UV_ENOSYS; it means the loop option is not supported by the platform. - - Supported options: - - - UV_LOOP_BLOCK_SIGNAL: Block a signal when polling for new events. The - second argument to :c:func:`uv_loop_configure` is the signal number. - - This operation is currently only implemented for SIGPROF signals, - to suppress unnecessary wakeups when using a sampling profiler. - Requesting other signals will fail with UV_EINVAL. - -.. c:function:: int uv_loop_close(uv_loop_t* loop) - - Closes all internal loop resources. This function must only be called once - the loop has finished its execution or it will return UV_EBUSY. After this - function returns the user shall free the memory allocated for the loop. - -.. c:function:: uv_loop_t* uv_default_loop(void) - - Returns the initialized default loop. It may return NULL in case of - allocation failure. - - This function is just a convenient way for having a global loop throughout - an application, the default loop is in no way different than the ones - initialized with :c:func:`uv_loop_init`. As such, the default loop can (and - should) be closed with :c:func:`uv_loop_close` so the resources associated - with it are freed. - -.. c:function:: int uv_run(uv_loop_t* loop, uv_run_mode mode) - - This function runs the event loop. It will act differently depending on the - specified mode: - - - UV_RUN_DEFAULT: Runs the event loop until there are no more active and - referenced handles or requests. Always returns zero. - - UV_RUN_ONCE: Poll for i/o once. Note that this function blocks if - there are no pending callbacks. Returns zero when done (no active handles - or requests left), or non-zero if more callbacks are expected (meaning - you should run the event loop again sometime in the future). - - UV_RUN_NOWAIT: Poll for i/o once but don't block if there are no - pending callbacks. Returns zero if done (no active handles - or requests left), or non-zero if more callbacks are expected (meaning - you should run the event loop again sometime in the future). - -.. c:function:: int uv_loop_alive(const uv_loop_t* loop) - - Returns non-zero if there are active handles or request in the loop. - -.. c:function:: void uv_stop(uv_loop_t* loop) - - Stop the event loop, causing :c:func:`uv_run` to end as soon as - possible. This will happen not sooner than the next loop iteration. - If this function was called before blocking for i/o, the loop won't block - for i/o on this iteration. - -.. c:function:: size_t uv_loop_size(void) - - Returns the size of the `uv_loop_t` structure. Useful for FFI binding - writers who don't want to know the structure layout. - -.. c:function:: int uv_backend_fd(const uv_loop_t* loop) - - Get backend file descriptor. Only kqueue, epoll and event ports are - supported. - - This can be used in conjunction with `uv_run(loop, UV_RUN_NOWAIT)` to - poll in one thread and run the event loop's callbacks in another see - test/test-embed.c for an example. - - .. note:: - Embedding a kqueue fd in another kqueue pollset doesn't work on all platforms. It's not - an error to add the fd but it never generates events. - -.. c:function:: int uv_backend_timeout(const uv_loop_t* loop) - - Get the poll timeout. The return value is in milliseconds, or -1 for no - timeout. - -.. c:function:: uint64_t uv_now(const uv_loop_t* loop) - - Return the current timestamp in milliseconds. The timestamp is cached at - the start of the event loop tick, see :c:func:`uv_update_time` for details - and rationale. - - The timestamp increases monotonically from some arbitrary point in time. - Don't make assumptions about the starting point, you will only get - disappointed. - - .. note:: - Use :c:func:`uv_hrtime` if you need sub-millisecond granularity. - -.. c:function:: void uv_update_time(uv_loop_t* loop) - - Update the event loop's concept of "now". Libuv caches the current time - at the start of the event loop tick in order to reduce the number of - time-related system calls. - - You won't normally need to call this function unless you have callbacks - that block the event loop for longer periods of time, where "longer" is - somewhat subjective but probably on the order of a millisecond or more. - -.. c:function:: void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) - - Walk the list of handles: `walk_cb` will be executed with the given `arg`. diff --git a/libuv/docs/src/migration_010_100.rst b/libuv/docs/src/migration_010_100.rst deleted file mode 100644 index bb6ac1a..0000000 --- a/libuv/docs/src/migration_010_100.rst +++ /dev/null @@ -1,244 +0,0 @@ - -.. _migration_010_100: - -libuv 0.10 -> 1.0.0 migration guide -=================================== - -Some APIs changed quite a bit throughout the 1.0.0 development process. Here -is a migration guide for the most significant changes that happened after 0.10 -was released. - - -Loop initialization and closing -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In libuv 0.10 (and previous versions), loops were created with `uv_loop_new`, which -allocated memory for a new loop and initialized it; and destroyed with `uv_loop_delete`, -which destroyed the loop and freed the memory. Starting with 1.0, those are deprecated -and the user is responsible for allocating the memory and then initializing the loop. - -libuv 0.10 - -:: - - uv_loop_t* loop = uv_loop_new(); - ... - uv_loop_delete(loop); - -libuv 1.0 - -:: - - uv_loop_t* loop = malloc(sizeof *loop); - uv_loop_init(loop); - ... - uv_loop_close(loop); - free(loop); - -.. note:: - Error handling was omitted for brevity. Check the documentation for :c:func:`uv_loop_init` - and :c:func:`uv_loop_close`. - - -Error handling -~~~~~~~~~~~~~~ - -Error handling had a major overhaul in libuv 1.0. In general, functions and status parameters -would get 0 for success and -1 for failure on libuv 0.10, and the user had to use `uv_last_error` -to fetch the error code, which was a positive number. - -In 1.0, functions and status parameters contain the actual error code, which is 0 for success, or -a negative number in case of error. - -libuv 0.10 - -:: - - ... assume 'server' is a TCP server which is already listening - r = uv_listen((uv_stream_t*) server, 511, NULL); - if (r == -1) { - uv_err_t err = uv_last_error(uv_default_loop()); - /* err.code contains UV_EADDRINUSE */ - } - -libuv 1.0 - -:: - - ... assume 'server' is a TCP server which is already listening - r = uv_listen((uv_stream_t*) server, 511, NULL); - if (r < 0) { - /* r contains UV_EADDRINUSE */ - } - - -Threadpool changes -~~~~~~~~~~~~~~~~~~ - -In libuv 0.10 Unix used a threadpool which defaulted to 4 threads, while Windows used the -`QueueUserWorkItem` API, which uses a Windows internal threadpool, which defaults to 512 -threads per process. - -In 1.0, we unified both implementations, so Windows now uses the same implementation Unix -does. The threadpool size can be set by exporting the ``UV_THREADPOOL_SIZE`` environment -variable. See :c:ref:`threadpool`. - - -Allocation callback API change -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In libuv 0.10 the callback had to return a filled :c:type:`uv_buf_t` by value: - -:: - - uv_buf_t alloc_cb(uv_handle_t* handle, size_t size) { - return uv_buf_init(malloc(size), size); - } - -In libuv 1.0 a pointer to a buffer is passed to the callback, which the user -needs to fill: - -:: - - void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) { - buf->base = malloc(size); - buf->len = size; - } - - -Unification of IPv4 / IPv6 APIs -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -libuv 1.0 unified the IPv4 and IPv6 APIS. There is no longer a `uv_tcp_bind` and `uv_tcp_bind6` -duality, there is only :c:func:`uv_tcp_bind` now. - -IPv4 functions took ``struct sockaddr_in`` structures by value, and IPv6 functions took -``struct sockaddr_in6``. Now functions take a ``struct sockaddr*`` (note it's a pointer). -It can be stack allocated. - -libuv 0.10 - -:: - - struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", 1234); - ... - uv_tcp_bind(&server, addr) - -libuv 1.0 - -:: - - struct sockaddr_in addr; - uv_ip4_addr("0.0.0.0", 1234, &addr) - ... - uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); - -The IPv4 and IPv6 struct creating functions (:c:func:`uv_ip4_addr` and :c:func:`uv_ip6_addr`) -have also changed, make sure you check the documentation. - -..note:: - This change applies to all functions that made a distinction between IPv4 and IPv6 - addresses. - - -Streams / UDP data receive callback API change -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The streams and UDP data receive callbacks now get a pointer to a :c:type:`uv_buf_t` buffer, -not a structure by value. - -libuv 0.10 - -:: - - void on_read(uv_stream_t* handle, - ssize_t nread, - uv_buf_t buf) { - ... - } - - void recv_cb(uv_udp_t* handle, - ssize_t nread, - uv_buf_t buf, - struct sockaddr* addr, - unsigned flags) { - ... - } - -libuv 1.0 - -:: - - void on_read(uv_stream_t* handle, - ssize_t nread, - const uv_buf_t* buf) { - ... - } - - void recv_cb(uv_udp_t* handle, - ssize_t nread, - const uv_buf_t* buf, - const struct sockaddr* addr, - unsigned flags) { - ... - } - - -Receiving handles over pipes API change -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In libuv 0.10 (and earlier versions) the `uv_read2_start` function was used to start reading -data on a pipe, which could also result in the reception of handles over it. The callback -for such function looked like this: - -:: - - void on_read(uv_pipe_t* pipe, - ssize_t nread, - uv_buf_t buf, - uv_handle_type pending) { - ... - } - -In libuv 1.0, `uv_read2_start` was removed, and the user needs to check if there are pending -handles using :c:func:`uv_pipe_pending_count` and :c:func:`uv_pipe_pending_type` while in -the read callback: - -:: - - void on_read(uv_stream_t* handle, - ssize_t nread, - const uv_buf_t* buf) { - ... - while (uv_pipe_pending_count((uv_pipe_t*) handle) != 0) { - pending = uv_pipe_pending_type((uv_pipe_t*) handle); - ... - } - ... - } - - -Extracting the file descriptor out of a handle -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -While it wasn't supported by the API, users often accessed the libuv internals in -order to get access to the file descriptor of a TCP handle, for example. - -:: - - fd = handle->io_watcher.fd; - -This is now properly exposed through the :c:func:`uv_fileno` function. - - -uv_fs_readdir rename and API change -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -`uv_fs_readdir` returned a list of strings in the `req->ptr` field upon completion in -libuv 0.10. In 1.0, this function got renamed to :c:func:`uv_fs_scandir`, since it's -actually implemented using ``scandir(3)``. - -In addition, instead of allocating a full list strings, the user is able to get one -result at a time by using the :c:func:`uv_fs_scandir_next` function. This function -does not need to make a roundtrip to the threadpool, because libuv will keep the -list of *dents* returned by ``scandir(3)`` around. diff --git a/libuv/docs/src/misc.rst b/libuv/docs/src/misc.rst deleted file mode 100644 index 10c349e..0000000 --- a/libuv/docs/src/misc.rst +++ /dev/null @@ -1,232 +0,0 @@ - -.. _misc: - -Miscellaneous utilities -======================= - -This section contains miscellaneous functions that don't really belong in any -other section. - - -Data types ----------- - -.. c:type:: uv_buf_t - - Buffer data type. - -.. c:type:: uv_file - - Cross platform representation of a file handle. - -.. c:type:: uv_os_sock_t - - Cross platform representation of a socket handle. - -.. c:type:: uv_os_fd_t - - Abstract representation of a file descriptor. On Unix systems this is a - `typedef` of `int` and on Windows fa `HANDLE`. - -.. c:type:: uv_rusage_t - - Data type for resource usage results. - - :: - - typedef struct { - uv_timeval_t ru_utime; /* user CPU time used */ - uv_timeval_t ru_stime; /* system CPU time used */ - uint64_t ru_maxrss; /* maximum resident set size */ - uint64_t ru_ixrss; /* integral shared memory size */ - uint64_t ru_idrss; /* integral unshared data size */ - uint64_t ru_isrss; /* integral unshared stack size */ - uint64_t ru_minflt; /* page reclaims (soft page faults) */ - uint64_t ru_majflt; /* page faults (hard page faults) */ - uint64_t ru_nswap; /* swaps */ - uint64_t ru_inblock; /* block input operations */ - uint64_t ru_oublock; /* block output operations */ - uint64_t ru_msgsnd; /* IPC messages sent */ - uint64_t ru_msgrcv; /* IPC messages received */ - uint64_t ru_nsignals; /* signals received */ - uint64_t ru_nvcsw; /* voluntary context switches */ - uint64_t ru_nivcsw; /* involuntary context switches */ - } uv_rusage_t; - -.. c:type:: uv_cpu_info_t - - Data type for CPU information. - - :: - - typedef struct uv_cpu_info_s { - char* model; - int speed; - struct uv_cpu_times_s { - uint64_t user; - uint64_t nice; - uint64_t sys; - uint64_t idle; - uint64_t irq; - } cpu_times; - } uv_cpu_info_t; - -.. c:type:: uv_interface_address_t - - Data type for interface addresses. - - :: - - typedef struct uv_interface_address_s { - char* name; - char phys_addr[6]; - int is_internal; - union { - struct sockaddr_in address4; - struct sockaddr_in6 address6; - } address; - union { - struct sockaddr_in netmask4; - struct sockaddr_in6 netmask6; - } netmask; - } uv_interface_address_t; - - -API ---- - -.. c:function:: uv_handle_type uv_guess_handle(uv_file file) - - Used to detect what type of stream should be used with a given file - descriptor. Usually this will be used during initialization to guess the - type of the stdio streams. - - For ``isatty()`` functionality use this function and test for ``UV_TTY``. - -.. c:function:: unsigned int uv_version(void) - - Returns the libuv version packed into a single integer. 8 bits are used for - each component, with the patch number stored in the 8 least significant - bits. E.g. for libuv 1.2.3 this would return 0x010203. - -.. c:function:: const char* uv_version_string(void) - - Returns the libuv version number as a string. For non-release versions - "-pre" is appended, so the version number could be "1.2.3-pre". - -.. c:function:: uv_buf_t uv_buf_init(char* base, unsigned int len) - - Constructor for :c:type:`uv_buf_t`. - - Due to platform differences the user cannot rely on the ordering of the - `base` and `len` members of the uv_buf_t struct. The user is responsible for - freeing `base` after the uv_buf_t is done. Return struct passed by value. - -.. c:function:: char** uv_setup_args(int argc, char** argv) - - Store the program arguments. Required for getting / setting the process title. - -.. c:function:: int uv_get_process_title(char* buffer, size_t size) - - Gets the title of the current process. - -.. c:function:: int uv_set_process_title(const char* title) - - Sets the current process title. - -.. c:function:: int uv_resident_set_memory(size_t* rss) - - Gets the resident set size (RSS) for the current process. - -.. c:function:: int uv_uptime(double* uptime) - - Gets the current system uptime. - -.. c:function:: int uv_getrusage(uv_rusage_t* rusage) - - Gets the resource usage measures for the current process. - - .. note:: - On Windows not all fields are set, the unsupported fields are filled with zeroes. - -.. c:function:: int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) - - Gets information about the CPUs on the system. The `cpu_infos` array will - have `count` elements and needs to be freed with :c:func:`uv_free_cpu_info`. - -.. c:function:: void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) - - Frees the `cpu_infos` array previously allocated with :c:func:`uv_cpu_info`. - -.. c:function:: int uv_interface_addresses(uv_interface_address_t** addresses, int* count) - - Gets address information about the network interfaces on the system. An - array of `count` elements is allocated and returned in `addresses`. It must - be freed by the user, calling :c:func:`uv_free_interface_addresses`. - -.. c:function:: void uv_free_interface_addresses(uv_interface_address_t* addresses, int count) - - Free an array of :c:type:`uv_interface_address_t` which was returned by - :c:func:`uv_interface_addresses`. - -.. c:function:: void uv_loadavg(double avg[3]) - - Gets the load average. See: ``_ - - .. note:: - Returns [0,0,0] on Windows (i.e., it's not implemented). - -.. c:function:: int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr) - - Convert a string containing an IPv4 addresses to a binary structure. - -.. c:function:: int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr) - - Convert a string containing an IPv6 addresses to a binary structure. - -.. c:function:: int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size) - - Convert a binary structure containing an IPv4 address to a string. - -.. c:function:: int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size) - - Convert a binary structure containing an IPv6 address to a string. - -.. c:function:: int uv_inet_ntop(int af, const void* src, char* dst, size_t size) -.. c:function:: int uv_inet_pton(int af, const char* src, void* dst) - - Cross-platform IPv6-capable implementation of the 'standard' ``inet_ntop()`` - and ``inet_pton()`` functions. On success they return 0. In case of error - the target `dst` pointer is unmodified. - -.. c:function:: int uv_exepath(char* buffer, size_t* size) - - Gets the executable path. - -.. c:function:: int uv_cwd(char* buffer, size_t* size) - - Gets the current working directory. - - .. versionchanged:: 1.1.0 - - On Unix the path no longer ends in a slash. - -.. c:function:: int uv_chdir(const char* dir) - - Changes the current working directory. - -.. uint64_t uv_get_free_memory(void) -.. c:function:: uint64_t uv_get_total_memory(void) - - Gets memory information (in bytes). - -.. c:function:: uint64_t uv_hrtime(void) - - Returns the current high-resolution real time. This is expressed in - nanoseconds. It is relative to an arbitrary time in the past. It is not - related to the time of day and therefore not subject to clock drift. The - primary use is for measuring performance between intervals. - - .. note:: - Not every platform can support nanosecond resolution; however, this value will always - be in nanoseconds. diff --git a/libuv/docs/src/pipe.rst b/libuv/docs/src/pipe.rst deleted file mode 100644 index 8f8402c..0000000 --- a/libuv/docs/src/pipe.rst +++ /dev/null @@ -1,100 +0,0 @@ - -.. _pipe: - -:c:type:`uv_pipe_t` --- Pipe handle -=================================== - -Pipe handles provide an abstraction over local domain sockets on Unix and named -pipes on Windows. - -:c:type:`uv_pipe_t` is a 'subclass' of :c:type:`uv_stream_t`. - - -Data types ----------- - -.. c:type:: uv_pipe_t - - Pipe handle type. - - -Public members -^^^^^^^^^^^^^^ - -N/A - -.. seealso:: The :c:type:`uv_stream_t` members also apply. - - -API ---- - -.. c:function:: int uv_pipe_init(uv_loop_t*, uv_pipe_t* handle, int ipc) - - Initialize a pipe handle. The `ipc` argument is a boolean to indicate if - this pipe will be used for handle passing between processes. - -.. c:function:: int uv_pipe_open(uv_pipe_t*, uv_file file) - - Open an existing file descriptor or HANDLE as a pipe. - - .. versionchanged:: 1.2.1 the file descriptor is set to non-blocking mode. - -.. c:function:: int uv_pipe_bind(uv_pipe_t* handle, const char* name) - - Bind the pipe to a file path (Unix) or a name (Windows). - - .. note:: - Paths on Unix get truncated to ``sizeof(sockaddr_un.sun_path)`` bytes, typically between - 92 and 108 bytes. - -.. c:function:: void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, const char* name, uv_connect_cb cb) - - Connect to the Unix domain socket or the named pipe. - - .. note:: - Paths on Unix get truncated to ``sizeof(sockaddr_un.sun_path)`` bytes, typically between - 92 and 108 bytes. - -.. c:function:: int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) - - Get the name of the Unix domain socket or the named pipe. - - A preallocated buffer must be provided. The size parameter holds the length - of the buffer and it's set to the number of bytes written to the buffer on - output. If the buffer is not big enough ``UV_ENOBUFS`` will be returned and - len will contain the required size. - - .. versionchanged:: 1.3.0 the returned length no longer includes the terminating null byte, - and the buffer is not null terminated. - -.. c:function:: int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) - - Get the name of the Unix domain socket or the named pipe to which the handle - is connected. - - A preallocated buffer must be provided. The size parameter holds the length - of the buffer and it's set to the number of bytes written to the buffer on - output. If the buffer is not big enough ``UV_ENOBUFS`` will be returned and - len will contain the required size. - - .. versionadded:: 1.3.0 - -.. c:function:: void uv_pipe_pending_instances(uv_pipe_t* handle, int count) - - Set the number of pending pipe instance handles when the pipe server is - waiting for connections. - - .. note:: - This setting applies to Windows only. - -.. c:function:: int uv_pipe_pending_count(uv_pipe_t* handle) -.. c:function:: uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) - - Used to receive handles over IPC pipes. - - First - call :c:func:`uv_pipe_pending_count`, if it's > 0 then initialize - a handle of the given `type`, returned by :c:func:`uv_pipe_pending_type` - and call ``uv_accept(pipe, handle)``. - -.. seealso:: The :c:type:`uv_stream_t` API functions also apply. diff --git a/libuv/docs/src/poll.rst b/libuv/docs/src/poll.rst deleted file mode 100644 index 907cb1a..0000000 --- a/libuv/docs/src/poll.rst +++ /dev/null @@ -1,103 +0,0 @@ - -.. _poll: - -:c:type:`uv_poll_t` --- Poll handle -=================================== - -Poll handles are used to watch file descriptors for readability and -writability, similar to the purpose of poll(2). - -The purpose of poll handles is to enable integrating external libraries that -rely on the event loop to signal it about the socket status changes, like -c-ares or libssh2. Using uv_poll_t for any other purpose is not recommended; -:c:type:`uv_tcp_t`, :c:type:`uv_udp_t`, etc. provide an implementation that is faster and -more scalable than what can be achieved with :c:type:`uv_poll_t`, especially on -Windows. - -It is possible that poll handles occasionally signal that a file descriptor is -readable or writable even when it isn't. The user should therefore always -be prepared to handle EAGAIN or equivalent when it attempts to read from or -write to the fd. - -It is not okay to have multiple active poll handles for the same socket, this -can cause libuv to busyloop or otherwise malfunction. - -The user should not close a file descriptor while it is being polled by an -active poll handle. This can cause the handle to report an error, -but it might also start polling another socket. However the fd can be safely -closed immediately after a call to :c:func:`uv_poll_stop` or :c:func:`uv_close`. - -.. note:: - On windows only sockets can be polled with poll handles. On Unix any file - descriptor that would be accepted by poll(2) can be used. - - -Data types ----------- - -.. c:type:: uv_poll_t - - Poll handle type. - -.. c:type:: void (*uv_poll_cb)(uv_poll_t* handle, int status, int events) - - Type definition for callback passed to :c:func:`uv_poll_start`. - -.. c:type:: uv_poll_event - - Poll event types - - :: - - enum uv_poll_event { - UV_READABLE = 1, - UV_WRITABLE = 2 - }; - - -Public members -^^^^^^^^^^^^^^ - -N/A - -.. seealso:: The :c:type:`uv_handle_t` members also apply. - - -API ---- - -.. c:function:: int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) - - Initialize the handle using a file descriptor. - - .. versionchanged:: 1.2.2 the file descriptor is set to non-blocking mode. - -.. c:function:: int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle, uv_os_sock_t socket) - - Initialize the handle using a socket descriptor. On Unix this is identical - to :c:func:`uv_poll_init`. On windows it takes a SOCKET handle. - - .. versionchanged:: 1.2.2 the socket is set to non-blocking mode. - -.. c:function:: int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb cb) - - Starts polling the file descriptor. `events` is a bitmask consisting made up - of UV_READABLE and UV_WRITABLE. As soon as an event is detected the callback - will be called with `status` set to 0, and the detected events set on the - `events` field. - - If an error happens while polling, `status` will be < 0 and corresponds - with one of the UV_E* error codes (see :ref:`errors`). The user should - not close the socket while the handle is active. If the user does that - anyway, the callback *may* be called reporting an error status, but this - is **not** guaranteed. - - .. note:: - Calling :c:func:`uv_poll_start` on a handle that is already active is fine. Doing so - will update the events mask that is being watched for. - -.. c:function:: int uv_poll_stop(uv_poll_t* poll) - - Stop polling the file descriptor, the callback will no longer be called. - -.. seealso:: The :c:type:`uv_handle_t` API functions also apply. diff --git a/libuv/docs/src/prepare.rst b/libuv/docs/src/prepare.rst deleted file mode 100644 index aca5815..0000000 --- a/libuv/docs/src/prepare.rst +++ /dev/null @@ -1,46 +0,0 @@ - -.. _prepare: - -:c:type:`uv_prepare_t` --- Prepare handle -========================================= - -Prepare handles will run the given callback once per loop iteration, right -before polling for i/o. - - -Data types ----------- - -.. c:type:: uv_prepare_t - - Prepare handle type. - -.. c:type:: void (*uv_prepare_cb)(uv_prepare_t* handle) - - Type definition for callback passed to :c:func:`uv_prepare_start`. - - -Public members -^^^^^^^^^^^^^^ - -N/A - -.. seealso:: The :c:type:`uv_handle_t` members also apply. - - -API ---- - -.. c:function:: int uv_prepare_init(uv_loop_t* loop, uv_prepare_t* prepare) - - Initialize the handle. - -.. c:function:: int uv_prepare_start(uv_prepare_t* prepare, uv_prepare_cb cb) - - Start the handle with the given callback. - -.. c:function:: int uv_prepare_stop(uv_prepare_t* prepare) - - Stop the handle, the callback will no longer be called. - -.. seealso:: The :c:type:`uv_handle_t` API functions also apply. diff --git a/libuv/docs/src/process.rst b/libuv/docs/src/process.rst deleted file mode 100644 index b0380dd..0000000 --- a/libuv/docs/src/process.rst +++ /dev/null @@ -1,225 +0,0 @@ - -.. _process: - -:c:type:`uv_process_t` --- Process handle -========================================= - -Process handles will spawn a new process and allow the user to control it and -establish communication channels with it using streams. - - -Data types ----------- - -.. c:type:: uv_process_t - - Process handle type. - -.. c:type:: uv_process_options_t - - Options for spawning the process (passed to :c:func:`uv_spawn`. - - :: - - typedef struct uv_process_options_s { - uv_exit_cb exit_cb; - const char* file; - char** args; - char** env; - const char* cwd; - unsigned int flags; - int stdio_count; - uv_stdio_container_t* stdio; - uv_uid_t uid; - uv_gid_t gid; - } uv_process_options_t; - -.. c:type:: void (*uv_exit_cb)(uv_process_t*, int64_t exit_status, int term_signal) - - Type definition for callback passed in :c:type:`uv_process_options_t` which - will indicate the exit status and the signal that caused the process to - terminate, if any. - -.. c:type:: uv_process_flags - - Flags to be set on the flags field of :c:type:`uv_process_options_t`. - - :: - - enum uv_process_flags { - /* - * Set the child process' user id. - */ - UV_PROCESS_SETUID = (1 << 0), - /* - * Set the child process' group id. - */ - UV_PROCESS_SETGID = (1 << 1), - /* - * Do not wrap any arguments in quotes, or perform any other escaping, when - * converting the argument list into a command line string. This option is - * only meaningful on Windows systems. On Unix it is silently ignored. - */ - UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS = (1 << 2), - /* - * Spawn the child process in a detached state - this will make it a process - * group leader, and will effectively enable the child to keep running after - * the parent exits. Note that the child process will still keep the - * parent's event loop alive unless the parent process calls uv_unref() on - * the child's process handle. - */ - UV_PROCESS_DETACHED = (1 << 3), - /* - * Hide the subprocess console window that would normally be created. This - * option is only meaningful on Windows systems. On Unix it is silently - * ignored. - */ - UV_PROCESS_WINDOWS_HIDE = (1 << 4) - }; - -.. c:type:: uv_stdio_container_t - - Container for each stdio handle or fd passed to a child process. - - :: - - typedef struct uv_stdio_container_s { - uv_stdio_flags flags; - union { - uv_stream_t* stream; - int fd; - } data; - } uv_stdio_container_t; - -.. c:type:: uv_stdio_flags - - Flags specifying how a stdio should be transmitted to the child process. - - :: - - typedef enum { - UV_IGNORE = 0x00, - UV_CREATE_PIPE = 0x01, - UV_INHERIT_FD = 0x02, - UV_INHERIT_STREAM = 0x04, - /* - * When UV_CREATE_PIPE is specified, UV_READABLE_PIPE and UV_WRITABLE_PIPE - * determine the direction of flow, from the child process' perspective. Both - * flags may be specified to create a duplex data stream. - */ - UV_READABLE_PIPE = 0x10, - UV_WRITABLE_PIPE = 0x20 - } uv_stdio_flags; - - -Public members -^^^^^^^^^^^^^^ - -.. c:member:: uv_process_t.pid - - The PID of the spawned process. It's set after calling :c:func:`uv_spawn`. - -.. note:: - The :c:type:`uv_handle_t` members also apply. - -.. c:member:: uv_process_options_t.exit_cb - - Callback called after the process exits. - -.. c:member:: uv_process_options_t.file - - Path pointing to the program to be executed. - -.. c:member:: uv_process_options_t.args - - Command line arguments. args[0] should be the path to the program. On - Windows this uses `CreateProcess` which concatenates the arguments into a - string this can cause some strange errors. See the - ``UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS`` flag on :c:type:`uv_process_flags`. - -.. c:member:: uv_process_options_t.env - - Environment for the new process. If NULL the parents environment is used. - -.. c:member:: uv_process_options_t.cwd - - Current working directory for the subprocess. - -.. c:member:: uv_process_options_t.flags - - Various flags that control how :c:func:`uv_spawn` behaves. See - :c:type:`uv_process_flags`. - -.. c:member:: uv_process_options_t.stdio_count -.. c:member:: uv_process_options_t.stdio - - The `stdio` field points to an array of :c:type:`uv_stdio_container_t` - structs that describe the file descriptors that will be made available to - the child process. The convention is that stdio[0] points to stdin, - fd 1 is used for stdout, and fd 2 is stderr. - - .. note:: - On Windows file descriptors greater than 2 are available to the child process only if - the child processes uses the MSVCRT runtime. - -.. c:member:: uv_process_options_t.uid -.. c:member:: uv_process_options_t.gid - - Libuv can change the child process' user/group id. This happens only when - the appropriate bits are set in the flags fields. - - .. note:: - This is not supported on Windows, :c:func:`uv_spawn` will fail and set the error - to ``UV_ENOTSUP``. - -.. c:member:: uv_stdio_container_t.flags - - Flags specifying how the stdio container should be passed to the child. See - :c:type:`uv_stdio_flags`. - -.. c:member:: uv_stdio_container_t.data - - Union containing either the stream or fd to be passed on to the child - process. - - -API ---- - -.. c:function:: void uv_disable_stdio_inheritance(void) - - Disables inheritance for file descriptors / handles that this process - inherited from its parent. The effect is that child processes spawned by - this process don't accidentally inherit these handles. - - It is recommended to call this function as early in your program as possible, - before the inherited file descriptors can be closed or duplicated. - - .. note:: - This function works on a best-effort basis: there is no guarantee that libuv can discover - all file descriptors that were inherited. In general it does a better job on Windows than - it does on Unix. - -.. c:function:: int uv_spawn(uv_loop_t* loop, uv_process_t* handle, const uv_process_options_t* options) - - Initializes the process handle and starts the process. If the process is - successfully spawned, this function will return 0. Otherwise, the - negative error code corresponding to the reason it couldn't spawn is - returned. - - Possible reasons for failing to spawn would include (but not be limited to) - the file to execute not existing, not having permissions to use the setuid or - setgid specified, or not having enough memory to allocate for the new - process. - -.. c:function:: int uv_process_kill(uv_process_t* handle, int signum) - - Sends the specified signal to the given process handle. Check the documentation - on :c:ref:`signal` for signal support, specially on Windows. - -.. c:function:: int uv_kill(int pid, int signum) - - Sends the specified signal to the given PID. Check the documentation - on :c:ref:`signal` for signal support, specially on Windows. - -.. seealso:: The :c:type:`uv_handle_t` API functions also apply. diff --git a/libuv/docs/src/request.rst b/libuv/docs/src/request.rst deleted file mode 100644 index 2f58d46..0000000 --- a/libuv/docs/src/request.rst +++ /dev/null @@ -1,82 +0,0 @@ - -.. _request: - -:c:type:`uv_req_t` --- Base request -=================================== - -`uv_req_t` is the base type for all libuv request types. - -Structures are aligned so that any libuv request can be cast to `uv_req_t`. -All API functions defined here work with any request type. - - -Data types ----------- - -.. c:type:: uv_req_t - - The base libuv request structure. - -.. c:type:: uv_any_req - - Union of all request types. - - -Public members -^^^^^^^^^^^^^^ - -.. c:member:: void* uv_request_t.data - - Space for user-defined arbitrary data. libuv does not use this field. - -.. c:member:: uv_req_type uv_req_t.type - - Indicated the type of request. Readonly. - - :: - - typedef enum { - UV_UNKNOWN_REQ = 0, - UV_REQ, - UV_CONNECT, - UV_WRITE, - UV_SHUTDOWN, - UV_UDP_SEND, - UV_FS, - UV_WORK, - UV_GETADDRINFO, - UV_GETNAMEINFO, - UV_REQ_TYPE_PRIVATE, - UV_REQ_TYPE_MAX, - } uv_req_type; - - -API ---- - -.. c:function:: int uv_cancel(uv_req_t* req) - - Cancel a pending request. Fails if the request is executing or has finished - executing. - - Returns 0 on success, or an error code < 0 on failure. - - Only cancellation of :c:type:`uv_fs_t`, :c:type:`uv_getaddrinfo_t`, - :c:type:`uv_getnameinfo_t` and :c:type:`uv_work_t` requests is - currently supported. - - Cancelled requests have their callbacks invoked some time in the future. - It's **not** safe to free the memory associated with the request until the - callback is called. - - Here is how cancellation is reported to the callback: - - * A :c:type:`uv_fs_t` request has its req->result field set to `UV_ECANCELED`. - - * A :c:type:`uv_work_t`, :c:type:`uv_getaddrinfo_t` or c:type:`uv_getnameinfo_t` - request has its callback invoked with status == `UV_ECANCELED`. - -.. c:function:: size_t uv_req_size(uv_req_type type) - - Returns the size of the given request type. Useful for FFI binding writers - who don't want to know the structure layout. diff --git a/libuv/docs/src/signal.rst b/libuv/docs/src/signal.rst deleted file mode 100644 index 2167594..0000000 --- a/libuv/docs/src/signal.rst +++ /dev/null @@ -1,77 +0,0 @@ - -.. _signal: - -:c:type:`uv_signal_t` --- Signal handle -======================================= - -Signal handles implement Unix style signal handling on a per-event loop bases. - -Reception of some signals is emulated on Windows: - -* SIGINT is normally delivered when the user presses CTRL+C. However, like - on Unix, it is not generated when terminal raw mode is enabled. - -* SIGBREAK is delivered when the user pressed CTRL + BREAK. - -* SIGHUP is generated when the user closes the console window. On SIGHUP the - program is given approximately 10 seconds to perform cleanup. After that - Windows will unconditionally terminate it. - -* SIGWINCH is raised whenever libuv detects that the console has been - resized. SIGWINCH is emulated by libuv when the program uses a :c:type:`uv_tty_t` - handle to write to the console. SIGWINCH may not always be delivered in a - timely manner; libuv will only detect size changes when the cursor is - being moved. When a readable :c:type:`uv_tty_t` handle is used in raw mode, - resizing the console buffer will also trigger a SIGWINCH signal. - -Watchers for other signals can be successfully created, but these signals -are never received. These signals are: `SIGILL`, `SIGABRT`, `SIGFPE`, `SIGSEGV`, -`SIGTERM` and `SIGKILL.` - -Calls to raise() or abort() to programmatically raise a signal are -not detected by libuv; these will not trigger a signal watcher. - -.. note:: - On Linux SIGRT0 and SIGRT1 (signals 32 and 33) are used by the NPTL pthreads library to - manage threads. Installing watchers for those signals will lead to unpredictable behavior - and is strongly discouraged. Future versions of libuv may simply reject them. - - -Data types ----------- - -.. c:type:: uv_signal_t - - Signal handle type. - -.. c:type:: void (*uv_signal_cb)(uv_signal_t* handle, int signum) - - Type definition for callback passed to :c:func:`uv_signal_start`. - - -Public members -^^^^^^^^^^^^^^ - -.. c:member:: int uv_signal_t.signum - - Signal being monitored by this handle. Readonly. - -.. seealso:: The :c:type:`uv_handle_t` members also apply. - - -API ---- - -.. c:function:: int uv_signal_init(uv_loop_t*, uv_signal_t* signal) - - Initialize the handle. - -.. c:function:: int uv_signal_start(uv_signal_t* signal, uv_signal_cb cb, int signum) - - Start the handle with the given callback, watching for the given signal. - -.. c:function:: int uv_signal_stop(uv_signal_t* signal) - - Stop the handle, the callback will no longer be called. - -.. seealso:: The :c:type:`uv_handle_t` API functions also apply. diff --git a/libuv/docs/src/static/architecture.png b/libuv/docs/src/static/architecture.png deleted file mode 100644 index 81e8749..0000000 Binary files a/libuv/docs/src/static/architecture.png and /dev/null differ diff --git a/libuv/docs/src/static/diagrams.key/Data/st0-311.jpg b/libuv/docs/src/static/diagrams.key/Data/st0-311.jpg deleted file mode 100644 index 439f581..0000000 Binary files a/libuv/docs/src/static/diagrams.key/Data/st0-311.jpg and /dev/null differ diff --git a/libuv/docs/src/static/diagrams.key/Data/st1-475.jpg b/libuv/docs/src/static/diagrams.key/Data/st1-475.jpg deleted file mode 100644 index ffb21ff..0000000 Binary files a/libuv/docs/src/static/diagrams.key/Data/st1-475.jpg and /dev/null differ diff --git a/libuv/docs/src/static/diagrams.key/Index.zip b/libuv/docs/src/static/diagrams.key/Index.zip deleted file mode 100644 index 17aedac..0000000 Binary files a/libuv/docs/src/static/diagrams.key/Index.zip and /dev/null differ diff --git a/libuv/docs/src/static/diagrams.key/Metadata/BuildVersionHistory.plist b/libuv/docs/src/static/diagrams.key/Metadata/BuildVersionHistory.plist deleted file mode 100644 index 39dd4fe..0000000 --- a/libuv/docs/src/static/diagrams.key/Metadata/BuildVersionHistory.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - Template: White (2014-02-28 09:41) - M6.2.2-1878-1 - - diff --git a/libuv/docs/src/static/diagrams.key/Metadata/DocumentIdentifier b/libuv/docs/src/static/diagrams.key/Metadata/DocumentIdentifier deleted file mode 100644 index ddb18f0..0000000 --- a/libuv/docs/src/static/diagrams.key/Metadata/DocumentIdentifier +++ /dev/null @@ -1 +0,0 @@ -F69E9CD9-EEF1-4223-9DA4-A1EA7FE112BA \ No newline at end of file diff --git a/libuv/docs/src/static/diagrams.key/Metadata/Properties.plist b/libuv/docs/src/static/diagrams.key/Metadata/Properties.plist deleted file mode 100644 index 74bc693..0000000 Binary files a/libuv/docs/src/static/diagrams.key/Metadata/Properties.plist and /dev/null differ diff --git a/libuv/docs/src/static/diagrams.key/preview-micro.jpg b/libuv/docs/src/static/diagrams.key/preview-micro.jpg deleted file mode 100644 index dd8decd..0000000 Binary files a/libuv/docs/src/static/diagrams.key/preview-micro.jpg and /dev/null differ diff --git a/libuv/docs/src/static/diagrams.key/preview-web.jpg b/libuv/docs/src/static/diagrams.key/preview-web.jpg deleted file mode 100644 index aadd401..0000000 Binary files a/libuv/docs/src/static/diagrams.key/preview-web.jpg and /dev/null differ diff --git a/libuv/docs/src/static/diagrams.key/preview.jpg b/libuv/docs/src/static/diagrams.key/preview.jpg deleted file mode 100644 index fc80025..0000000 Binary files a/libuv/docs/src/static/diagrams.key/preview.jpg and /dev/null differ diff --git a/libuv/docs/src/static/favicon.ico b/libuv/docs/src/static/favicon.ico deleted file mode 100644 index 2c40694..0000000 Binary files a/libuv/docs/src/static/favicon.ico and /dev/null differ diff --git a/libuv/docs/src/static/logo.png b/libuv/docs/src/static/logo.png deleted file mode 100644 index eaf1eee..0000000 Binary files a/libuv/docs/src/static/logo.png and /dev/null differ diff --git a/libuv/docs/src/static/loop_iteration.png b/libuv/docs/src/static/loop_iteration.png deleted file mode 100644 index e769cf3..0000000 Binary files a/libuv/docs/src/static/loop_iteration.png and /dev/null differ diff --git a/libuv/docs/src/stream.rst b/libuv/docs/src/stream.rst deleted file mode 100644 index 2c669cf..0000000 --- a/libuv/docs/src/stream.rst +++ /dev/null @@ -1,217 +0,0 @@ - -.. _stream: - -:c:type:`uv_stream_t` --- Stream handle -======================================= - -Stream handles provide an abstraction of a duplex communication channel. -:c:type:`uv_stream_t` is an abstract type, libuv provides 3 stream implementations -in the for of :c:type:`uv_tcp_t`, :c:type:`uv_pipe_t` and :c:type:`uv_tty_t`. - - -Data types ----------- - -.. c:type:: uv_stream_t - - Stream handle type. - -.. c:type:: uv_connect_t - - Connect request type. - -.. c:type:: uv_shutdown_t - - Shutdown request type. - -.. c:type:: uv_write_t - - Write request type. - -.. c:type:: void (*uv_read_cb)(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) - - Callback called when data was read on a stream. - - `nread` is > 0 if there is data available, 0 if libuv is done reading for - now, or < 0 on error. - - The callee is responsible for stopping closing the stream when an error happens - by calling :c:func:`uv_read_stop` or :c:func:`uv_close`. Trying to read - from the stream again is undefined. - - The callee is responsible for freeing the buffer, libuv does not reuse it. - The buffer may be a null buffer (where buf->base=NULL and buf->len=0) on - error. - -.. c:type:: void (*uv_write_cb)(uv_write_t* req, int status) - - Callback called after data was written on a stream. `status` will be 0 in - case of success, < 0 otherwise. - -.. c:type:: void (*uv_connect_cb)(uv_connect_t* req, int status) - - Callback called after a connection started by :c:func:`uv_connect` is done. - `status` will be 0 in case of success, < 0 otherwise. - -.. c:type:: void (*uv_shutdown_cb)(uv_shutdown_t* req, int status) - - Callback called after s shutdown request has been completed. `status` will - be 0 in case of success, < 0 otherwise. - -.. c:type:: void (*uv_connection_cb)(uv_stream_t* server, int status) - - Callback called when a stream server has received an incoming connection. - The user can accept the connection by calling :c:func:`uv_accept`. - `status` will be 0 in case of success, < 0 otherwise. - - -Public members -^^^^^^^^^^^^^^ - -.. c:member:: size_t uv_stream_t.write_queue_size - - Contains the amount of queued bytes waiting to be sent. Readonly. - -.. c:member:: uv_stream_t* uv_connect_t.handle - - Pointer to the stream where this connection request is running. - -.. c:member:: uv_stream_t* uv_shutdown_t.handle - - Pointer to the stream where this shutdown request is running. - -.. c:member:: uv_stream_t* uv_write_t.handle - - Pointer to the stream where this write request is running. - -.. c:member:: uv_stream_t* uv_write_t.send_handle - - Pointer to the stream being sent using this write request.. - -.. seealso:: The :c:type:`uv_handle_t` members also apply. - - -API ---- - -.. c:function:: int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) - - Shutdown the outgoing (write) side of a duplex stream. It waits for pending - write requests to complete. The `handle` should refer to a initialized stream. - `req` should be an uninitialized shutdown request struct. The `cb` is called - after shutdown is complete. - -.. c:function:: int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) - - Start listening for incoming connections. `backlog` indicates the number of - connections the kernel might queue, same as ``listen(2)``. When a new - incoming connection is received the :c:type:`uv_connection_cb` callback is - called. - -.. c:function:: int uv_accept(uv_stream_t* server, uv_stream_t* client) - - This call is used in conjunction with :c:func:`uv_listen` to accept incoming - connections. Call this function after receiving a :c:type:`uv_connection_cb` - to accept the connection. Before calling this function the client handle must - be initialized. < 0 return value indicates an error. - - When the :c:type:`uv_connection_cb` callback is called it is guaranteed that - this function will complete successfully the first time. If you attempt to use - it more than once, it may fail. It is suggested to only call this function once - per :c:type:`uv_connection_cb` call. - - .. note:: - `server` and `client` must be handles running on the same loop. - -.. c:function:: int uv_read_start(uv_stream_t*, uv_alloc_cb alloc_cb, uv_read_cb read_cb) - - Read data from an incoming stream. The callback will be made several - times until there is no more data to read or :c:func:`uv_read_stop` is called. - When we've reached EOF `nread` will be set to ``UV_EOF``. - - When `nread` < 0, the `buf` parameter might not point to a valid buffer; - in that case `buf.len` and `buf.base` are both set to 0. - - .. note:: - `nread` might also be 0, which does *not* indicate an error or EOF, it happens when - libuv requested a buffer through the alloc callback but then decided that it didn't - need that buffer. - -.. c:function:: int uv_read_stop(uv_stream_t*) - - Stop reading data from the stream. The :c:type:`uv_read_cb` callback will - no longer be called. - -.. c:function:: int uv_write(uv_write_t* req, uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb) - - Write data to stream. Buffers are written in order. Example: - - :: - - uv_buf_t a[] = { - { .base = "1", .len = 1 }, - { .base = "2", .len = 1 } - }; - - uv_buf_t b[] = { - { .base = "3", .len = 1 }, - { .base = "4", .len = 1 } - }; - - uv_write_t req1; - uv_write_t req2; - - /* writes "1234" */ - uv_write(&req1, stream, a, 2); - uv_write(&req2, stream, b, 2); - -.. c:function:: int uv_write2(uv_write_t* req, uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs, uv_stream_t* send_handle, uv_write_cb cb) - - Extended write function for sending handles over a pipe. The pipe must be - initialized with `ipc` == 1. - - .. note:: - `send_handle` must be a TCP socket or pipe, which is a server or a connection (listening - or connected state). Bound sockets or pipes will be assumed to be servers. - -.. c:function:: int uv_try_write(uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs) - - Same as :c:func:`uv_write`, but won't queue a write request if it can't be - completed immediately. - - Will return either: - - * > 0: number of bytes written (can be less than the supplied buffer size). - * < 0: negative error code (``UV_EAGAIN`` is returned if no data can be sent - immediately). - -.. c:function:: int uv_is_readable(const uv_stream_t* handle) - - Returns 1 if the stream is readable, 0 otherwise. - -.. c:function:: int uv_is_writable(const uv_stream_t* handle) - - Returns 1 if the stream is writable, 0 otherwise. - -.. c:function:: int uv_stream_set_blocking(uv_stream_t* handle, int blocking) - - Enable or disable blocking mode for a stream. - - When blocking mode is enabled all writes complete synchronously. The - interface remains unchanged otherwise, e.g. completion or failure of the - operation will still be reported through a callback which is made - asynchronously. - - .. warning:: - Relying too much on this API is not recommended. It is likely to change - significantly in the future. - - Currently this only works on Windows and only for - :c:type:`uv_pipe_t` handles. - - Also libuv currently makes no ordering guarantee when the blocking mode - is changed after write requests have already been submitted. Therefore it is - recommended to set the blocking mode immediately after opening or creating - the stream. - -.. seealso:: The :c:type:`uv_handle_t` API functions also apply. diff --git a/libuv/docs/src/tcp.rst b/libuv/docs/src/tcp.rst deleted file mode 100644 index 8baedde..0000000 --- a/libuv/docs/src/tcp.rst +++ /dev/null @@ -1,95 +0,0 @@ - -.. _tcp: - -:c:type:`uv_tcp_t` --- TCP handle -================================= - -TCP handles are used to represent both TCP streams and servers. - -:c:type:`uv_tcp_t` is a 'subclass' of :c:type:`uv_stream_t`. - - -Data types ----------- - -.. c:type:: uv_tcp_t - - TCP handle type. - - -Public members -^^^^^^^^^^^^^^ - -N/A - -.. seealso:: The :c:type:`uv_stream_t` members also apply. - - -API ---- - -.. c:function:: int uv_tcp_init(uv_loop_t*, uv_tcp_t* handle) - - Initialize the handle. - -.. c:function:: int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) - - Open an existing file descriptor or SOCKET as a TCP handle. - - .. versionchanged:: 1.2.1 the file descriptor is set to non-blocking mode. - -.. c:function:: int uv_tcp_nodelay(uv_tcp_t* handle, int enable) - - Enable / disable Nagle's algorithm. - -.. c:function:: int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) - - Enable / disable TCP keep-alive. `delay` is the initial delay in seconds, - ignored when `enable` is zero. - -.. c:function:: int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) - - Enable / disable simultaneous asynchronous accept requests that are - queued by the operating system when listening for new TCP connections. - - This setting is used to tune a TCP server for the desired performance. - Having simultaneous accepts can significantly improve the rate of accepting - connections (which is why it is enabled by default) but may lead to uneven - load distribution in multi-process setups. - -.. c:function:: int uv_tcp_bind(uv_tcp_t* handle, const struct sockaddr* addr, unsigned int flags) - - Bind the handle to an address and port. `addr` should point to an - initialized ``struct sockaddr_in`` or ``struct sockaddr_in6``. - - When the port is already taken, you can expect to see an ``UV_EADDRINUSE`` - error from either :c:func:`uv_tcp_bind`, :c:func:`uv_listen` or - :c:func:`uv_tcp_connect`. That is, a successful call to this function does - not guarantee that the call to :c:func:`uv_listen` or :c:func:`uv_tcp_connect` - will succeed as well. - - `flags` con contain ``UV_TCP_IPV6ONLY``, in which case dual-stack support - is disabled and only IPv6 is used. - -.. c:function:: int uv_tcp_getsockname(const uv_tcp_t* handle, struct sockaddr* name, int* namelen) - - Get the current address to which the handle is bound. `addr` must point to - a valid and big enough chunk of memory, ``struct sockaddr_storage`` is - recommended for IPv4 and IPv6 support. - -.. c:function:: int uv_tcp_getpeername(const uv_tcp_t* handle, struct sockaddr* name, int* namelen) - - Get the address of the peer connected to the handle. `addr` must point to - a valid and big enough chunk of memory, ``struct sockaddr_storage`` is - recommended for IPv4 and IPv6 support. - -.. c:function:: int uv_tcp_connect(uv_connect_t* req, uv_tcp_t* handle, const struct sockaddr* addr, uv_connect_cb cb) - - Establish an IPv4 or IPv6 TCP connection. Provide an initialized TCP handle - and an uninitialized :c:type:`uv_connect_t`. `addr` should point to an - initialized ``struct sockaddr_in`` or ``struct sockaddr_in6``. - - The callback is made when the connection has been established or when a - connection error happened. - -.. seealso:: The :c:type:`uv_stream_t` API functions also apply. diff --git a/libuv/docs/src/threading.rst b/libuv/docs/src/threading.rst deleted file mode 100644 index aab13f8..0000000 --- a/libuv/docs/src/threading.rst +++ /dev/null @@ -1,157 +0,0 @@ - -.. _threading: - -Threading and synchronization utilities -======================================= - -libuv provides cross-platform implementations for multiple threading and -synchronization primitives. The API largely follows the pthreads API. - - -Data types ----------- - -.. c:type:: uv_thread_t - - Thread data type. - -.. c:type:: void (*uv_thread_cb)(void* arg) - - Callback that is invoked to initialize thread execution. `arg` is the same - value that was passed to :c:func:`uv_thread_create`. - -.. c:type:: uv_key_t - - Thread-local key data type. - -.. c:type:: uv_once_t - - Once-only initializer data type. - -.. c:type:: uv_mutex_t - - Mutex data type. - -.. c:type:: uv_rwlock_t - - Read-write lock data type. - -.. c:type:: uv_sem_t - - Semaphore data type. - -.. c:type:: uv_cond_t - - Condition data type. - -.. c:type:: uv_barrier_t - - Barrier data type. - - -API ---- - -Threads -^^^^^^^ - -.. c:function:: int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg) -.. c:function:: uv_thread_t uv_thread_self(void) -.. c:function:: int uv_thread_join(uv_thread_t *tid) -.. c:function:: int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) - -Thread-local storage -^^^^^^^^^^^^^^^^^^^^ - -.. note:: - The total thread-local storage size may be limited. That is, it may not be possible to - create many TLS keys. - -.. c:function:: int uv_key_create(uv_key_t* key) -.. c:function:: void uv_key_delete(uv_key_t* key) -.. c:function:: void* uv_key_get(uv_key_t* key) -.. c:function:: void uv_key_set(uv_key_t* key, void* value) - -Once-only initialization -^^^^^^^^^^^^^^^^^^^^^^^^ - -Runs a function once and only once. Concurrent calls to :c:func:`uv_once` with the -same guard will block all callers except one (it's unspecified which one). -The guard should be initialized statically with the UV_ONCE_INIT macro. - -.. c:function:: void uv_once(uv_once_t* guard, void (*callback)(void)) - -Mutex locks -^^^^^^^^^^^ - -Functions return 0 on success or an error code < 0 (unless the -return type is void, of course). - -.. c:function:: int uv_mutex_init(uv_mutex_t* handle) -.. c:function:: void uv_mutex_destroy(uv_mutex_t* handle) -.. c:function:: void uv_mutex_lock(uv_mutex_t* handle) -.. c:function:: int uv_mutex_trylock(uv_mutex_t* handle) -.. c:function:: void uv_mutex_unlock(uv_mutex_t* handle) - -Read-write locks -^^^^^^^^^^^^^^^^ - -Functions return 0 on success or an error code < 0 (unless the -return type is void, of course). - -.. c:function:: int uv_rwlock_init(uv_rwlock_t* rwlock) -.. c:function:: void uv_rwlock_destroy(uv_rwlock_t* rwlock) -.. c:function:: void uv_rwlock_rdlock(uv_rwlock_t* rwlock) -.. c:function:: int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock) -.. c:function:: void uv_rwlock_rdunlock(uv_rwlock_t* rwlock) -.. c:function:: void uv_rwlock_wrlock(uv_rwlock_t* rwlock) -.. c:function:: int uv_rwlock_trywrlock(uv_rwlock_t* rwlock) -.. c:function:: void uv_rwlock_wrunlock(uv_rwlock_t* rwlock) - -Semaphores -^^^^^^^^^^ - -Functions return 0 on success or an error code < 0 (unless the -return type is void, of course). - -.. c:function:: int uv_sem_init(uv_sem_t* sem, unsigned int value) -.. c:function:: void uv_sem_destroy(uv_sem_t* sem) -.. c:function:: void uv_sem_post(uv_sem_t* sem) -.. c:function:: void uv_sem_wait(uv_sem_t* sem) -.. c:function:: int uv_sem_trywait(uv_sem_t* sem) - -Conditions -^^^^^^^^^^ - -Functions return 0 on success or an error code < 0 (unless the -return type is void, of course). - -.. note:: - Callers should be prepared to deal with spurious wakeups on :c:func:`uv_cond_wait` and - :c:func:`uv_cond_timedwait`. - -.. c:function:: int uv_cond_init(uv_cond_t* cond) -.. c:function:: void uv_cond_destroy(uv_cond_t* cond) -.. c:function:: void uv_cond_signal(uv_cond_t* cond) -.. c:function:: void uv_cond_broadcast(uv_cond_t* cond) -.. c:function:: void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) -.. c:function:: int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) - -Barriers -^^^^^^^^ - -Functions return 0 on success or an error code < 0 (unless the -return type is void, of course). - -.. note:: - :c:func:`uv_barrier_wait` returns a value > 0 to an arbitrarily chosen "serializer" thread - to facilitate cleanup, i.e. - - :: - - if (uv_barrier_wait(&barrier) > 0) - uv_barrier_destroy(&barrier); - -.. c:function:: int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) -.. c:function:: void uv_barrier_destroy(uv_barrier_t* barrier) -.. c:function:: int uv_barrier_wait(uv_barrier_t* barrier) diff --git a/libuv/docs/src/threadpool.rst b/libuv/docs/src/threadpool.rst deleted file mode 100644 index 89f0084..0000000 --- a/libuv/docs/src/threadpool.rst +++ /dev/null @@ -1,63 +0,0 @@ - -.. _threadpool: - -Thread pool work scheduling -=========================== - -libuv provides a threadpool which can be used to run user code and get notified -in the loop thread. This thread pool is internally used to run all filesystem -operations, as well as getaddrinfo and getnameinfo requests. - -Its default size is 4, but it can be changed at startup time by setting the -``UV_THREADPOOL_SIZE`` environment variable to any value (the absolute maximum -is 128). - -The threadpool is global and shared across all event loops. When a particular -function makes use of the threadpool (i.e. when using :c:func:`uv_queue_work`) -libuv preallocates and initializes the maximum number of threads allowed by -``UV_THREADPOOL_SIZE``. This causes a relatively minor memory overhead -(~1MB for 128 threads) but increases the performance of threading at runtime. - - -Data types ----------- - -.. c:type:: uv_work_t - - Work request type. - -.. c:type:: void (*uv_work_cb)(uv_work_t* req) - - Callback passed to :c:func:`uv_queue_work` which will be run on the thread - pool. - -.. c:type:: void (*uv_after_work_cb)(uv_work_t* req, int status) - - Callback passed to :c:func:`uv_queue_work` which will be called on the loop - thread after the work on the threadpool has been completed. If the work - was cancelled using :c:func:`uv_cancel` `status` will be ``UV_ECANCELED``. - - -Public members -^^^^^^^^^^^^^^ - -.. c:member:: uv_loop_t* uv_work_t.loop - - Loop that started this request and where completion will be reported. - Readonly. - -.. seealso:: The :c:type:`uv_req_t` members also apply. - - -API ---- - -.. c:function:: int uv_queue_work(uv_loop_t* loop, uv_work_t* req, uv_work_cb work_cb, uv_after_work_cb after_work_cb) - - Initializes a work request which will run the given `work_cb` in a thread - from the threadpool. Once `work_cb` is completed, `after_work_cb` will be - called on the loop thread. - - This request can be cancelled with :c:func:`uv_cancel`. - -.. seealso:: The :c:type:`uv_req_t` API functions also apply. diff --git a/libuv/docs/src/timer.rst b/libuv/docs/src/timer.rst deleted file mode 100644 index e558704..0000000 --- a/libuv/docs/src/timer.rst +++ /dev/null @@ -1,68 +0,0 @@ - -.. _timer: - -:c:type:`uv_timer_t` --- Timer handle -===================================== - -Timer handles are used to schedule callbacks to be called in the future. - - -Data types ----------- - -.. c:type:: uv_timer_t - - Timer handle type. - -.. c:type:: void (*uv_timer_cb)(uv_timer_t* handle) - - Type definition for callback passed to :c:func:`uv_timer_start`. - - -Public members -^^^^^^^^^^^^^^ - -N/A - -.. seealso:: The :c:type:`uv_handle_t` members also apply. - - -API ---- - -.. c:function:: int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) - - Initialize the handle. - -.. c:function:: int uv_timer_start(uv_timer_t* handle, uv_timer_cb cb, uint64_t timeout, uint64_t repeat) - - Start the timer. `timeout` and `repeat` are in milliseconds. - - If `timeout` is zero, the callback fires on the next event loop iteration. - If `repeat` is non-zero, the callback fires first after `timeout` - milliseconds and then repeatedly after `repeat` milliseconds. - -.. c:function:: int uv_timer_stop(uv_timer_t* handle) - - Stop the timer, the callback will not be called anymore. - -.. c:function:: int uv_timer_again(uv_timer_t* handle) - - Stop the timer, and if it is repeating restart it using the repeat value - as the timeout. If the timer has never been started before it returns - UV_EINVAL. - -.. c:function:: void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat) - - Set the repeat value in milliseconds. - - .. note:: - If the repeat value is set from a timer callback it does not immediately take effect. - If the timer was non-repeating before, it will have been stopped. If it was repeating, - then the old repeat value will have been used to schedule the next timeout. - -.. c:function:: uint64_t uv_timer_get_repeat(const uv_timer_t* handle) - - Get the timer repeat value. - -.. seealso:: The :c:type:`uv_handle_t` API functions also apply. diff --git a/libuv/docs/src/tty.rst b/libuv/docs/src/tty.rst deleted file mode 100644 index 6c20c84..0000000 --- a/libuv/docs/src/tty.rst +++ /dev/null @@ -1,89 +0,0 @@ - -.. _tty: - -:c:type:`uv_tty_t` --- TTY handle -================================= - -TTY handles represent a stream for the console. - -:c:type:`uv_tty_t` is a 'subclass' of :c:type:`uv_stream_t`. - - -Data types ----------- - -.. c:type:: uv_tty_t - - TTY handle type. - -.. c:type:: uv_tty_mode_t - - .. versionadded:: 1.2.0 - - TTY mode type: - - :: - - typedef enum { - /* Initial/normal terminal mode */ - UV_TTY_MODE_NORMAL, - /* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled) */ - UV_TTY_MODE_RAW, - /* Binary-safe I/O mode for IPC (Unix-only) */ - UV_TTY_MODE_IO - } uv_tty_mode_t; - - - -Public members -^^^^^^^^^^^^^^ - -N/A - -.. seealso:: The :c:type:`uv_stream_t` members also apply. - - -API ---- - -.. c:function:: int uv_tty_init(uv_loop_t*, uv_tty_t*, uv_file fd, int readable) - - Initialize a new TTY stream with the given file descriptor. Usually the - file descriptor will be: - - * 0 = stdin - * 1 = stdout - * 2 = stderr - - `readable`, specifies if you plan on calling :c:func:`uv_read_start` with - this stream. stdin is readable, stdout is not. - - On Unix this function will try to open ``/dev/tty`` and use it if the passed file - descriptor refers to a TTY. This lets libuv put the tty in non-blocking mode - without affecting other processes that share the tty. - - .. note:: - If opening ``/dev/tty`` fails, libuv falls back to blocking writes for non-readable - TTY streams. - -.. c:function:: int uv_tty_set_mode(uv_tty_t*, uv_tty_mode_t mode) - - .. versionchanged:: 1.2.0: the mode is specified as a :c:type:`uv_tty_mode_t` - value. - - Set the TTY using the specified terminal mode. - -.. c:function:: int uv_tty_reset_mode(void) - - To be called when the program exits. Resets TTY settings to default - values for the next process to take over. - - This function is async signal-safe on Unix platforms but can fail with error - code ``UV_EBUSY`` if you call it when execution is inside - :c:func:`uv_tty_set_mode`. - -.. c:function:: int uv_tty_get_winsize(uv_tty_t*, int* width, int* height) - - Gets the current Window size. On success it returns 0. - -.. seealso:: The :c:type:`uv_stream_t` API functions also apply. diff --git a/libuv/docs/src/udp.rst b/libuv/docs/src/udp.rst deleted file mode 100644 index 9c4aa21..0000000 --- a/libuv/docs/src/udp.rst +++ /dev/null @@ -1,282 +0,0 @@ - -.. _udp: - -:c:type:`uv_udp_t` --- UDP handle -================================= - -UDP handles encapsulate UDP communication for both clients and servers. - - -Data types ----------- - -.. c:type:: uv_udp_t - - UDP handle type. - -.. c:type:: uv_udp_send_t - - UDP send request type. - -.. c:type:: uv_udp_flags - - Flags used in :c:func:`uv_udp_bind` and :c:type:`uv_udp_recv_cb`.. - - :: - - enum uv_udp_flags { - /* Disables dual stack mode. */ - UV_UDP_IPV6ONLY = 1, - /* - * Indicates message was truncated because read buffer was too small. The - * remainder was discarded by the OS. Used in uv_udp_recv_cb. - */ - UV_UDP_PARTIAL = 2, - /* - * Indicates if SO_REUSEADDR will be set when binding the handle in - * uv_udp_bind. - * This sets the SO_REUSEPORT socket flag on the BSDs and OS X. On other - * Unix platforms, it sets the SO_REUSEADDR flag. What that means is that - * multiple threads or processes can bind to the same address without error - * (provided they all set the flag) but only the last one to bind will receive - * any traffic, in effect "stealing" the port from the previous listener. - */ - UV_UDP_REUSEADDR = 4 - }; - -.. c:type:: void (*uv_udp_send_cb)(uv_udp_send_t* req, int status) - - Type definition for callback passed to :c:func:`uv_udp_send`, which is - called after the data was sent. - -.. c:type:: void (*uv_udp_recv_cb)(uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned flags) - - Type definition for callback passed to :c:func:`uv_udp_recv_start`, which - is called when the endpoint receives data. - - * `handle`: UDP handle - * `nread`: Number of bytes that have been received. - 0 if there is no more data to read. You may discard or repurpose - the read buffer. Note that 0 may also mean that an empty datagram - was received (in this case `addr` is not NULL). < 0 if a transmission - error was detected. - * `buf`: :c:type:`uv_buf_t` with the received data. - * `addr`: ``struct sockaddr*`` containing the address of the sender. - Can be NULL. Valid for the duration of the callback only. - * `flags`: One or more or'ed UV_UDP_* constants. Right now only - ``UV_UDP_PARTIAL`` is used. - - .. note:: - The receive callback will be called with `nread` == 0 and `addr` == NULL when there is - nothing to read, and with `nread` == 0 and `addr` != NULL when an empty UDP packet is - received. - -.. c:type:: uv_membership - - Membership type for a multicast address. - - :: - - typedef enum { - UV_LEAVE_GROUP = 0, - UV_JOIN_GROUP - } uv_membership; - - -Public members -^^^^^^^^^^^^^^ - -.. c:member:: size_t uv_udp_t.send_queue_size - - Number of bytes queued for sending. This field strictly shows how much - information is currently queued. - -.. c:member:: size_t uv_udp_t.send_queue_count - - Number of send requests currently in the queue awaiting to be processed. - -.. c:member:: uv_udp_t* uv_udp_send_t.handle - - UDP handle where this send request is taking place. - -.. seealso:: The :c:type:`uv_handle_t` members also apply. - - -API ---- - -.. c:function:: int uv_udp_init(uv_loop_t*, uv_udp_t* handle) - - Initialize a new UDP handle. The actual socket is created lazily. - Returns 0 on success. - -.. c:function:: int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) - - Opens an existing file descriptor or Windows SOCKET as a UDP handle. - - Unix only: - The only requirement of the `sock` argument is that it follows the datagram - contract (works in unconnected mode, supports sendmsg()/recvmsg(), etc). - In other words, other datagram-type sockets like raw sockets or netlink - sockets can also be passed to this function. - - .. versionchanged:: 1.2.1 the file descriptor is set to non-blocking mode. - -.. c:function:: int uv_udp_bind(uv_udp_t* handle, const struct sockaddr* addr, unsigned int flags) - - Bind the UDP handle to an IP address and port. - - :param handle: UDP handle. Should have been initialized with - :c:func:`uv_udp_init`. - - :param addr: `struct sockaddr_in` or `struct sockaddr_in6` - with the address and port to bind to. - - :param flags: Indicate how the socket will be bound, - ``UV_UDP_IPV6ONLY`` and ``UV_UDP_REUSEADDR`` are supported. - - :returns: 0 on success, or an error code < 0 on failure. - -.. c:function:: int uv_udp_getsockname(const uv_udp_t* handle, struct sockaddr* name, int* namelen) - - Get the local IP and port of the UDP handle. - - :param handle: UDP handle. Should have been initialized with - :c:func:`uv_udp_init` and bound. - - :param name: Pointer to the structure to be filled with the address data. - In order to support IPv4 and IPv6 `struct sockaddr_storage` should be - used. - - :param namelen: On input it indicates the data of the `name` field. On - output it indicates how much of it was filled. - - :returns: 0 on success, or an error code < 0 on failure. - -.. c:function:: int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr, const char* interface_addr, uv_membership membership) - - Set membership for a multicast address - - :param handle: UDP handle. Should have been initialized with - :c:func:`uv_udp_init`. - - :param multicast_addr: Multicast address to set membership for. - - :param interface_addr: Interface address. - - :param membership: Should be ``UV_JOIN_GROUP`` or ``UV_LEAVE_GROUP``. - - :returns: 0 on success, or an error code < 0 on failure. - -.. c:function:: int uv_udp_set_multicast_loop(uv_udp_t* handle, int on) - - Set IP multicast loop flag. Makes multicast packets loop back to - local sockets. - - :param handle: UDP handle. Should have been initialized with - :c:func:`uv_udp_init`. - - :param on: 1 for on, 0 for off. - - :returns: 0 on success, or an error code < 0 on failure. - -.. c:function:: int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl) - - Set the multicast ttl. - - :param handle: UDP handle. Should have been initialized with - :c:func:`uv_udp_init`. - - :param ttl: 1 through 255. - - :returns: 0 on success, or an error code < 0 on failure. - -.. c:function:: int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) - - Set the multicast interface to send or receive data on. - - :param handle: UDP handle. Should have been initialized with - :c:func:`uv_udp_init`. - - :param interface_addr: interface address. - - :returns: 0 on success, or an error code < 0 on failure. - -.. c:function:: int uv_udp_set_broadcast(uv_udp_t* handle, int on) - - Set broadcast on or off. - - :param handle: UDP handle. Should have been initialized with - :c:func:`uv_udp_init`. - - :param on: 1 for on, 0 for off. - - :returns: 0 on success, or an error code < 0 on failure. - -.. c:function:: int uv_udp_set_ttl(uv_udp_t* handle, int ttl) - - Set the time to live. - - :param handle: UDP handle. Should have been initialized with - :c:func:`uv_udp_init`. - - :param ttl: 1 through 255. - - :returns: 0 on success, or an error code < 0 on failure. - -.. c:function:: int uv_udp_send(uv_udp_send_t* req, uv_udp_t* handle, const uv_buf_t bufs[], unsigned int nbufs, const struct sockaddr* addr, uv_udp_send_cb send_cb) - - Send data over the UDP socket. If the socket has not previously been bound - with :c:func:`uv_udp_bind` it will be bound to 0.0.0.0 - (the "all interfaces" IPv4 address) and a random port number. - - :param req: UDP request handle. Need not be initialized. - - :param handle: UDP handle. Should have been initialized with - :c:func:`uv_udp_init`. - - :param bufs: List of buffers to send. - - :param nbufs: Number of buffers in `bufs`. - - :param addr: `struct sockaddr_in` or `struct sockaddr_in6` with the - address and port of the remote peer. - - :param send_cb: Callback to invoke when the data has been sent out. - - :returns: 0 on success, or an error code < 0 on failure. - -.. c:function:: int uv_udp_try_send(uv_udp_t* handle, const uv_buf_t bufs[], unsigned int nbufs, const struct sockaddr* addr) - - Same as :c:func:`uv_udp_send`, but won't queue a send request if it can't - be completed immediately. - - :returns: >= 0: number of bytes sent (it matches the given buffer size). - < 0: negative error code (``UV_EAGAIN`` is returned when the message - can't be sent immediately). - -.. c:function:: int uv_udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb, uv_udp_recv_cb recv_cb) - - Prepare for receiving data. If the socket has not previously been bound - with :c:func:`uv_udp_bind` it is bound to 0.0.0.0 (the "all interfaces" - IPv4 address) and a random port number. - - :param handle: UDP handle. Should have been initialized with - :c:func:`uv_udp_init`. - - :param alloc_cb: Callback to invoke when temporary storage is needed. - - :param recv_cb: Callback to invoke with received data. - - :returns: 0 on success, or an error code < 0 on failure. - -.. c:function:: int uv_udp_recv_stop(uv_udp_t* handle) - - Stop listening for incoming datagrams. - - :param handle: UDP handle. Should have been initialized with - :c:func:`uv_udp_init`. - - :returns: 0 on success, or an error code < 0 on failure. - -.. seealso:: The :c:type:`uv_handle_t` API functions also apply. diff --git a/libuv/gyp_uv.py b/libuv/gyp_uv.py deleted file mode 100755 index 0491ff8..0000000 --- a/libuv/gyp_uv.py +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env python - -import os -import platform -import sys - -try: - import multiprocessing.synchronize - gyp_parallel_support = True -except ImportError: - gyp_parallel_support = False - - -CC = os.environ.get('CC', 'cc') -script_dir = os.path.dirname(__file__) -uv_root = os.path.normpath(script_dir) -output_dir = os.path.join(os.path.abspath(uv_root), 'out') - -sys.path.insert(0, os.path.join(uv_root, 'build', 'gyp', 'pylib')) -try: - import gyp -except ImportError: - print('You need to install gyp in build/gyp first. See the README.') - sys.exit(42) - - -def host_arch(): - machine = platform.machine() - if machine == 'i386': return 'ia32' - if machine == 'x86_64': return 'x64' - if machine.startswith('arm'): return 'arm' - if machine.startswith('mips'): return 'mips' - return machine # Return as-is and hope for the best. - - -def run_gyp(args): - rc = gyp.main(args) - if rc != 0: - print 'Error running GYP' - sys.exit(rc) - - -if __name__ == '__main__': - args = sys.argv[1:] - - # GYP bug. - # On msvs it will crash if it gets an absolute path. - # On Mac/make it will crash if it doesn't get an absolute path. - if sys.platform == 'win32': - args.append(os.path.join(uv_root, 'uv.gyp')) - common_fn = os.path.join(uv_root, 'common.gypi') - options_fn = os.path.join(uv_root, 'options.gypi') - # we force vs 2010 over 2008 which would otherwise be the default for gyp - if not os.environ.get('GYP_MSVS_VERSION'): - os.environ['GYP_MSVS_VERSION'] = '2010' - else: - args.append(os.path.join(os.path.abspath(uv_root), 'uv.gyp')) - common_fn = os.path.join(os.path.abspath(uv_root), 'common.gypi') - options_fn = os.path.join(os.path.abspath(uv_root), 'options.gypi') - - if os.path.exists(common_fn): - args.extend(['-I', common_fn]) - - if os.path.exists(options_fn): - args.extend(['-I', options_fn]) - - args.append('--depth=' + uv_root) - - # There's a bug with windows which doesn't allow this feature. - if sys.platform != 'win32': - if '-f' not in args: - args.extend('-f make'.split()) - if 'eclipse' not in args and 'ninja' not in args: - args.extend(['-Goutput_dir=' + output_dir]) - args.extend(['--generator-output', output_dir]) - - if not any(a.startswith('-Dhost_arch=') for a in args): - args.append('-Dhost_arch=%s' % host_arch()) - - if not any(a.startswith('-Dtarget_arch=') for a in args): - args.append('-Dtarget_arch=%s' % host_arch()) - - if not any(a.startswith('-Duv_library=') for a in args): - args.append('-Duv_library=static_library') - - if not any(a.startswith('-Dcomponent=') for a in args): - args.append('-Dcomponent=static_library') - - # Some platforms (OpenBSD for example) don't have multiprocessing.synchronize - # so gyp must be run with --no-parallel - if not gyp_parallel_support: - args.append('--no-parallel') - - gyp_args = list(args) - print gyp_args - run_gyp(gyp_args) diff --git a/libuv/img/banner.png b/libuv/img/banner.png deleted file mode 100644 index 7187daa..0000000 Binary files a/libuv/img/banner.png and /dev/null differ diff --git a/libuv/img/logos.svg b/libuv/img/logos.svg deleted file mode 100644 index d6185f8..0000000 --- a/libuv/img/logos.svg +++ /dev/null @@ -1,152 +0,0 @@ - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libuv/include/android-ifaddrs.h b/libuv/include/android-ifaddrs.h deleted file mode 100644 index 9cd19fe..0000000 --- a/libuv/include/android-ifaddrs.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 1995, 1999 - * Berkeley Software Design, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp - */ - -#ifndef _IFADDRS_H_ -#define _IFADDRS_H_ - -struct ifaddrs { - struct ifaddrs *ifa_next; - char *ifa_name; - unsigned int ifa_flags; - struct sockaddr *ifa_addr; - struct sockaddr *ifa_netmask; - struct sockaddr *ifa_dstaddr; - void *ifa_data; -}; - -/* - * This may have been defined in . Note that if is - * to be included it must be included before this header file. - */ -#ifndef ifa_broadaddr -#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */ -#endif - -#include - -__BEGIN_DECLS -extern int getifaddrs(struct ifaddrs **ifap); -extern void freeifaddrs(struct ifaddrs *ifa); -__END_DECLS - -#endif diff --git a/libuv/include/pthread-fixes.h b/libuv/include/pthread-fixes.h deleted file mode 100644 index 88c6b66..0000000 --- a/libuv/include/pthread-fixes.h +++ /dev/null @@ -1,72 +0,0 @@ -/* Copyright (c) 2013, Sony Mobile Communications AB - * Copyright (c) 2012, Google Inc. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef GOOGLE_BREAKPAD_COMMON_ANDROID_TESTING_PTHREAD_FIXES_H -#define GOOGLE_BREAKPAD_COMMON_ANDROID_TESTING_PTHREAD_FIXES_H - -#include - - -/*Android doesn't provide pthread_barrier_t for now.*/ -#ifndef PTHREAD_BARRIER_SERIAL_THREAD - -/* Anything except 0 will do here.*/ -#define PTHREAD_BARRIER_SERIAL_THREAD 0x12345 - -typedef struct { - pthread_mutex_t mutex; - pthread_cond_t cond; - unsigned count; -} pthread_barrier_t; - -int pthread_barrier_init(pthread_barrier_t* barrier, - const void* barrier_attr, - unsigned count); - -int pthread_barrier_wait(pthread_barrier_t* barrier); -int pthread_barrier_destroy(pthread_barrier_t *barrier); -#endif /* defined(PTHREAD_BARRIER_SERIAL_THREAD) */ - -int pthread_yield(void); - -/* Workaround pthread_sigmask() returning EINVAL on versions < 4.1 by - * replacing all calls to pthread_sigmask with sigprocmask. See: - * https://android.googlesource.com/platform/bionic/+/9bf330b5 - * https://code.google.com/p/android/issues/detail?id=15337 - */ -int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset); - -#ifdef pthread_sigmask -#undef pthread_sigmask -#endif -#define pthread_sigmask(how, set, oldset) uv__pthread_sigmask(how, set, oldset) - -#endif /* GOOGLE_BREAKPAD_COMMON_ANDROID_TESTING_PTHREAD_FIXES_H */ diff --git a/libuv/include/stdint-msvc2008.h b/libuv/include/stdint-msvc2008.h deleted file mode 100644 index d02608a..0000000 --- a/libuv/include/stdint-msvc2008.h +++ /dev/null @@ -1,247 +0,0 @@ -// ISO C9x compliant stdint.h for Microsoft Visual Studio -// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 -// -// Copyright (c) 2006-2008 Alexander Chemeris -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 3. The name of the author may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef _MSC_VER // [ -#error "Use this header only with Microsoft Visual C++ compilers!" -#endif // _MSC_VER ] - -#ifndef _MSC_STDINT_H_ // [ -#define _MSC_STDINT_H_ - -#if _MSC_VER > 1000 -#pragma once -#endif - -#include - -// For Visual Studio 6 in C++ mode and for many Visual Studio versions when -// compiling for ARM we should wrap include with 'extern "C++" {}' -// or compiler give many errors like this: -// error C2733: second C linkage of overloaded function 'wmemchr' not allowed -#ifdef __cplusplus -extern "C" { -#endif -# include -#ifdef __cplusplus -} -#endif - -// Define _W64 macros to mark types changing their size, like intptr_t. -#ifndef _W64 -# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 -# define _W64 __w64 -# else -# define _W64 -# endif -#endif - - -// 7.18.1 Integer types - -// 7.18.1.1 Exact-width integer types - -// Visual Studio 6 and Embedded Visual C++ 4 doesn't -// realize that, e.g. char has the same size as __int8 -// so we give up on __intX for them. -#if (_MSC_VER < 1300) - typedef signed char int8_t; - typedef signed short int16_t; - typedef signed int int32_t; - typedef unsigned char uint8_t; - typedef unsigned short uint16_t; - typedef unsigned int uint32_t; -#else - typedef signed __int8 int8_t; - typedef signed __int16 int16_t; - typedef signed __int32 int32_t; - typedef unsigned __int8 uint8_t; - typedef unsigned __int16 uint16_t; - typedef unsigned __int32 uint32_t; -#endif -typedef signed __int64 int64_t; -typedef unsigned __int64 uint64_t; - - -// 7.18.1.2 Minimum-width integer types -typedef int8_t int_least8_t; -typedef int16_t int_least16_t; -typedef int32_t int_least32_t; -typedef int64_t int_least64_t; -typedef uint8_t uint_least8_t; -typedef uint16_t uint_least16_t; -typedef uint32_t uint_least32_t; -typedef uint64_t uint_least64_t; - -// 7.18.1.3 Fastest minimum-width integer types -typedef int8_t int_fast8_t; -typedef int16_t int_fast16_t; -typedef int32_t int_fast32_t; -typedef int64_t int_fast64_t; -typedef uint8_t uint_fast8_t; -typedef uint16_t uint_fast16_t; -typedef uint32_t uint_fast32_t; -typedef uint64_t uint_fast64_t; - -// 7.18.1.4 Integer types capable of holding object pointers -#ifdef _WIN64 // [ - typedef signed __int64 intptr_t; - typedef unsigned __int64 uintptr_t; -#else // _WIN64 ][ - typedef _W64 signed int intptr_t; - typedef _W64 unsigned int uintptr_t; -#endif // _WIN64 ] - -// 7.18.1.5 Greatest-width integer types -typedef int64_t intmax_t; -typedef uint64_t uintmax_t; - - -// 7.18.2 Limits of specified-width integer types - -#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 - -// 7.18.2.1 Limits of exact-width integer types -#define INT8_MIN ((int8_t)_I8_MIN) -#define INT8_MAX _I8_MAX -#define INT16_MIN ((int16_t)_I16_MIN) -#define INT16_MAX _I16_MAX -#define INT32_MIN ((int32_t)_I32_MIN) -#define INT32_MAX _I32_MAX -#define INT64_MIN ((int64_t)_I64_MIN) -#define INT64_MAX _I64_MAX -#define UINT8_MAX _UI8_MAX -#define UINT16_MAX _UI16_MAX -#define UINT32_MAX _UI32_MAX -#define UINT64_MAX _UI64_MAX - -// 7.18.2.2 Limits of minimum-width integer types -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST8_MAX INT8_MAX -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST16_MAX INT16_MAX -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST32_MAX INT32_MAX -#define INT_LEAST64_MIN INT64_MIN -#define INT_LEAST64_MAX INT64_MAX -#define UINT_LEAST8_MAX UINT8_MAX -#define UINT_LEAST16_MAX UINT16_MAX -#define UINT_LEAST32_MAX UINT32_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -// 7.18.2.3 Limits of fastest minimum-width integer types -#define INT_FAST8_MIN INT8_MIN -#define INT_FAST8_MAX INT8_MAX -#define INT_FAST16_MIN INT16_MIN -#define INT_FAST16_MAX INT16_MAX -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST32_MAX INT32_MAX -#define INT_FAST64_MIN INT64_MIN -#define INT_FAST64_MAX INT64_MAX -#define UINT_FAST8_MAX UINT8_MAX -#define UINT_FAST16_MAX UINT16_MAX -#define UINT_FAST32_MAX UINT32_MAX -#define UINT_FAST64_MAX UINT64_MAX - -// 7.18.2.4 Limits of integer types capable of holding object pointers -#ifdef _WIN64 // [ -# define INTPTR_MIN INT64_MIN -# define INTPTR_MAX INT64_MAX -# define UINTPTR_MAX UINT64_MAX -#else // _WIN64 ][ -# define INTPTR_MIN INT32_MIN -# define INTPTR_MAX INT32_MAX -# define UINTPTR_MAX UINT32_MAX -#endif // _WIN64 ] - -// 7.18.2.5 Limits of greatest-width integer types -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -// 7.18.3 Limits of other integer types - -#ifdef _WIN64 // [ -# define PTRDIFF_MIN _I64_MIN -# define PTRDIFF_MAX _I64_MAX -#else // _WIN64 ][ -# define PTRDIFF_MIN _I32_MIN -# define PTRDIFF_MAX _I32_MAX -#endif // _WIN64 ] - -#define SIG_ATOMIC_MIN INT_MIN -#define SIG_ATOMIC_MAX INT_MAX - -#ifndef SIZE_MAX // [ -# ifdef _WIN64 // [ -# define SIZE_MAX _UI64_MAX -# else // _WIN64 ][ -# define SIZE_MAX _UI32_MAX -# endif // _WIN64 ] -#endif // SIZE_MAX ] - -// WCHAR_MIN and WCHAR_MAX are also defined in -#ifndef WCHAR_MIN // [ -# define WCHAR_MIN 0 -#endif // WCHAR_MIN ] -#ifndef WCHAR_MAX // [ -# define WCHAR_MAX _UI16_MAX -#endif // WCHAR_MAX ] - -#define WINT_MIN 0 -#define WINT_MAX _UI16_MAX - -#endif // __STDC_LIMIT_MACROS ] - - -// 7.18.4 Limits of other integer types - -#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 - -// 7.18.4.1 Macros for minimum-width integer constants - -#define INT8_C(val) val##i8 -#define INT16_C(val) val##i16 -#define INT32_C(val) val##i32 -#define INT64_C(val) val##i64 - -#define UINT8_C(val) val##ui8 -#define UINT16_C(val) val##ui16 -#define UINT32_C(val) val##ui32 -#define UINT64_C(val) val##ui64 - -// 7.18.4.2 Macros for greatest-width integer constants -#define INTMAX_C INT64_C -#define UINTMAX_C UINT64_C - -#endif // __STDC_CONSTANT_MACROS ] - - -#endif // _MSC_STDINT_H_ ] diff --git a/libuv/include/tree.h b/libuv/include/tree.h deleted file mode 100644 index f936416..0000000 --- a/libuv/include/tree.h +++ /dev/null @@ -1,768 +0,0 @@ -/*- - * Copyright 2002 Niels Provos - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef UV_TREE_H_ -#define UV_TREE_H_ - -#ifndef UV__UNUSED -# if __GNUC__ -# define UV__UNUSED __attribute__((unused)) -# else -# define UV__UNUSED -# endif -#endif - -/* - * This file defines data structures for different types of trees: - * splay trees and red-black trees. - * - * A splay tree is a self-organizing data structure. Every operation - * on the tree causes a splay to happen. The splay moves the requested - * node to the root of the tree and partly rebalances it. - * - * This has the benefit that request locality causes faster lookups as - * the requested nodes move to the top of the tree. On the other hand, - * every lookup causes memory writes. - * - * The Balance Theorem bounds the total access time for m operations - * and n inserts on an initially empty tree as O((m + n)lg n). The - * amortized cost for a sequence of m accesses to a splay tree is O(lg n); - * - * A red-black tree is a binary search tree with the node color as an - * extra attribute. It fulfills a set of conditions: - * - every search path from the root to a leaf consists of the - * same number of black nodes, - * - each red node (except for the root) has a black parent, - * - each leaf node is black. - * - * Every operation on a red-black tree is bounded as O(lg n). - * The maximum height of a red-black tree is 2lg (n+1). - */ - -#define SPLAY_HEAD(name, type) \ -struct name { \ - struct type *sph_root; /* root of the tree */ \ -} - -#define SPLAY_INITIALIZER(root) \ - { NULL } - -#define SPLAY_INIT(root) do { \ - (root)->sph_root = NULL; \ -} while (/*CONSTCOND*/ 0) - -#define SPLAY_ENTRY(type) \ -struct { \ - struct type *spe_left; /* left element */ \ - struct type *spe_right; /* right element */ \ -} - -#define SPLAY_LEFT(elm, field) (elm)->field.spe_left -#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right -#define SPLAY_ROOT(head) (head)->sph_root -#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL) - -/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */ -#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \ - SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \ - SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ - (head)->sph_root = tmp; \ -} while (/*CONSTCOND*/ 0) - -#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \ - SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \ - SPLAY_LEFT(tmp, field) = (head)->sph_root; \ - (head)->sph_root = tmp; \ -} while (/*CONSTCOND*/ 0) - -#define SPLAY_LINKLEFT(head, tmp, field) do { \ - SPLAY_LEFT(tmp, field) = (head)->sph_root; \ - tmp = (head)->sph_root; \ - (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ -} while (/*CONSTCOND*/ 0) - -#define SPLAY_LINKRIGHT(head, tmp, field) do { \ - SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ - tmp = (head)->sph_root; \ - (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \ -} while (/*CONSTCOND*/ 0) - -#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \ - SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \ - SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field); \ - SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \ - SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \ -} while (/*CONSTCOND*/ 0) - -/* Generates prototypes and inline functions */ - -#define SPLAY_PROTOTYPE(name, type, field, cmp) \ -void name##_SPLAY(struct name *, struct type *); \ -void name##_SPLAY_MINMAX(struct name *, int); \ -struct type *name##_SPLAY_INSERT(struct name *, struct type *); \ -struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \ - \ -/* Finds the node with the same key as elm */ \ -static __inline struct type * \ -name##_SPLAY_FIND(struct name *head, struct type *elm) \ -{ \ - if (SPLAY_EMPTY(head)) \ - return(NULL); \ - name##_SPLAY(head, elm); \ - if ((cmp)(elm, (head)->sph_root) == 0) \ - return (head->sph_root); \ - return (NULL); \ -} \ - \ -static __inline struct type * \ -name##_SPLAY_NEXT(struct name *head, struct type *elm) \ -{ \ - name##_SPLAY(head, elm); \ - if (SPLAY_RIGHT(elm, field) != NULL) { \ - elm = SPLAY_RIGHT(elm, field); \ - while (SPLAY_LEFT(elm, field) != NULL) { \ - elm = SPLAY_LEFT(elm, field); \ - } \ - } else \ - elm = NULL; \ - return (elm); \ -} \ - \ -static __inline struct type * \ -name##_SPLAY_MIN_MAX(struct name *head, int val) \ -{ \ - name##_SPLAY_MINMAX(head, val); \ - return (SPLAY_ROOT(head)); \ -} - -/* Main splay operation. - * Moves node close to the key of elm to top - */ -#define SPLAY_GENERATE(name, type, field, cmp) \ -struct type * \ -name##_SPLAY_INSERT(struct name *head, struct type *elm) \ -{ \ - if (SPLAY_EMPTY(head)) { \ - SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \ - } else { \ - int __comp; \ - name##_SPLAY(head, elm); \ - __comp = (cmp)(elm, (head)->sph_root); \ - if(__comp < 0) { \ - SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field); \ - SPLAY_RIGHT(elm, field) = (head)->sph_root; \ - SPLAY_LEFT((head)->sph_root, field) = NULL; \ - } else if (__comp > 0) { \ - SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field); \ - SPLAY_LEFT(elm, field) = (head)->sph_root; \ - SPLAY_RIGHT((head)->sph_root, field) = NULL; \ - } else \ - return ((head)->sph_root); \ - } \ - (head)->sph_root = (elm); \ - return (NULL); \ -} \ - \ -struct type * \ -name##_SPLAY_REMOVE(struct name *head, struct type *elm) \ -{ \ - struct type *__tmp; \ - if (SPLAY_EMPTY(head)) \ - return (NULL); \ - name##_SPLAY(head, elm); \ - if ((cmp)(elm, (head)->sph_root) == 0) { \ - if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \ - (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \ - } else { \ - __tmp = SPLAY_RIGHT((head)->sph_root, field); \ - (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ - name##_SPLAY(head, elm); \ - SPLAY_RIGHT((head)->sph_root, field) = __tmp; \ - } \ - return (elm); \ - } \ - return (NULL); \ -} \ - \ -void \ -name##_SPLAY(struct name *head, struct type *elm) \ -{ \ - struct type __node, *__left, *__right, *__tmp; \ - int __comp; \ - \ - SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL; \ - __left = __right = &__node; \ - \ - while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \ - if (__comp < 0) { \ - __tmp = SPLAY_LEFT((head)->sph_root, field); \ - if (__tmp == NULL) \ - break; \ - if ((cmp)(elm, __tmp) < 0){ \ - SPLAY_ROTATE_RIGHT(head, __tmp, field); \ - if (SPLAY_LEFT((head)->sph_root, field) == NULL) \ - break; \ - } \ - SPLAY_LINKLEFT(head, __right, field); \ - } else if (__comp > 0) { \ - __tmp = SPLAY_RIGHT((head)->sph_root, field); \ - if (__tmp == NULL) \ - break; \ - if ((cmp)(elm, __tmp) > 0){ \ - SPLAY_ROTATE_LEFT(head, __tmp, field); \ - if (SPLAY_RIGHT((head)->sph_root, field) == NULL) \ - break; \ - } \ - SPLAY_LINKRIGHT(head, __left, field); \ - } \ - } \ - SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ -} \ - \ -/* Splay with either the minimum or the maximum element \ - * Used to find minimum or maximum element in tree. \ - */ \ -void name##_SPLAY_MINMAX(struct name *head, int __comp) \ -{ \ - struct type __node, *__left, *__right, *__tmp; \ - \ - SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL; \ - __left = __right = &__node; \ - \ - while (1) { \ - if (__comp < 0) { \ - __tmp = SPLAY_LEFT((head)->sph_root, field); \ - if (__tmp == NULL) \ - break; \ - if (__comp < 0){ \ - SPLAY_ROTATE_RIGHT(head, __tmp, field); \ - if (SPLAY_LEFT((head)->sph_root, field) == NULL) \ - break; \ - } \ - SPLAY_LINKLEFT(head, __right, field); \ - } else if (__comp > 0) { \ - __tmp = SPLAY_RIGHT((head)->sph_root, field); \ - if (__tmp == NULL) \ - break; \ - if (__comp > 0) { \ - SPLAY_ROTATE_LEFT(head, __tmp, field); \ - if (SPLAY_RIGHT((head)->sph_root, field) == NULL) \ - break; \ - } \ - SPLAY_LINKRIGHT(head, __left, field); \ - } \ - } \ - SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ -} - -#define SPLAY_NEGINF -1 -#define SPLAY_INF 1 - -#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y) -#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y) -#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y) -#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y) -#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \ - : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) -#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \ - : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) - -#define SPLAY_FOREACH(x, name, head) \ - for ((x) = SPLAY_MIN(name, head); \ - (x) != NULL; \ - (x) = SPLAY_NEXT(name, head, x)) - -/* Macros that define a red-black tree */ -#define RB_HEAD(name, type) \ -struct name { \ - struct type *rbh_root; /* root of the tree */ \ -} - -#define RB_INITIALIZER(root) \ - { NULL } - -#define RB_INIT(root) do { \ - (root)->rbh_root = NULL; \ -} while (/*CONSTCOND*/ 0) - -#define RB_BLACK 0 -#define RB_RED 1 -#define RB_ENTRY(type) \ -struct { \ - struct type *rbe_left; /* left element */ \ - struct type *rbe_right; /* right element */ \ - struct type *rbe_parent; /* parent element */ \ - int rbe_color; /* node color */ \ -} - -#define RB_LEFT(elm, field) (elm)->field.rbe_left -#define RB_RIGHT(elm, field) (elm)->field.rbe_right -#define RB_PARENT(elm, field) (elm)->field.rbe_parent -#define RB_COLOR(elm, field) (elm)->field.rbe_color -#define RB_ROOT(head) (head)->rbh_root -#define RB_EMPTY(head) (RB_ROOT(head) == NULL) - -#define RB_SET(elm, parent, field) do { \ - RB_PARENT(elm, field) = parent; \ - RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \ - RB_COLOR(elm, field) = RB_RED; \ -} while (/*CONSTCOND*/ 0) - -#define RB_SET_BLACKRED(black, red, field) do { \ - RB_COLOR(black, field) = RB_BLACK; \ - RB_COLOR(red, field) = RB_RED; \ -} while (/*CONSTCOND*/ 0) - -#ifndef RB_AUGMENT -#define RB_AUGMENT(x) do {} while (0) -#endif - -#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \ - (tmp) = RB_RIGHT(elm, field); \ - if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \ - RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \ - } \ - RB_AUGMENT(elm); \ - if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \ - if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ - RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ - else \ - RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ - } else \ - (head)->rbh_root = (tmp); \ - RB_LEFT(tmp, field) = (elm); \ - RB_PARENT(elm, field) = (tmp); \ - RB_AUGMENT(tmp); \ - if ((RB_PARENT(tmp, field))) \ - RB_AUGMENT(RB_PARENT(tmp, field)); \ -} while (/*CONSTCOND*/ 0) - -#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \ - (tmp) = RB_LEFT(elm, field); \ - if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \ - RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \ - } \ - RB_AUGMENT(elm); \ - if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \ - if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ - RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ - else \ - RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ - } else \ - (head)->rbh_root = (tmp); \ - RB_RIGHT(tmp, field) = (elm); \ - RB_PARENT(elm, field) = (tmp); \ - RB_AUGMENT(tmp); \ - if ((RB_PARENT(tmp, field))) \ - RB_AUGMENT(RB_PARENT(tmp, field)); \ -} while (/*CONSTCOND*/ 0) - -/* Generates prototypes and inline functions */ -#define RB_PROTOTYPE(name, type, field, cmp) \ - RB_PROTOTYPE_INTERNAL(name, type, field, cmp,) -#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \ - RB_PROTOTYPE_INTERNAL(name, type, field, cmp, UV__UNUSED static) -#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \ -attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \ -attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\ -attr struct type *name##_RB_REMOVE(struct name *, struct type *); \ -attr struct type *name##_RB_INSERT(struct name *, struct type *); \ -attr struct type *name##_RB_FIND(struct name *, struct type *); \ -attr struct type *name##_RB_NFIND(struct name *, struct type *); \ -attr struct type *name##_RB_NEXT(struct type *); \ -attr struct type *name##_RB_PREV(struct type *); \ -attr struct type *name##_RB_MINMAX(struct name *, int); \ - \ - -/* Main rb operation. - * Moves node close to the key of elm to top - */ -#define RB_GENERATE(name, type, field, cmp) \ - RB_GENERATE_INTERNAL(name, type, field, cmp,) -#define RB_GENERATE_STATIC(name, type, field, cmp) \ - RB_GENERATE_INTERNAL(name, type, field, cmp, UV__UNUSED static) -#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \ -attr void \ -name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \ -{ \ - struct type *parent, *gparent, *tmp; \ - while ((parent = RB_PARENT(elm, field)) != NULL && \ - RB_COLOR(parent, field) == RB_RED) { \ - gparent = RB_PARENT(parent, field); \ - if (parent == RB_LEFT(gparent, field)) { \ - tmp = RB_RIGHT(gparent, field); \ - if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ - RB_COLOR(tmp, field) = RB_BLACK; \ - RB_SET_BLACKRED(parent, gparent, field); \ - elm = gparent; \ - continue; \ - } \ - if (RB_RIGHT(parent, field) == elm) { \ - RB_ROTATE_LEFT(head, parent, tmp, field); \ - tmp = parent; \ - parent = elm; \ - elm = tmp; \ - } \ - RB_SET_BLACKRED(parent, gparent, field); \ - RB_ROTATE_RIGHT(head, gparent, tmp, field); \ - } else { \ - tmp = RB_LEFT(gparent, field); \ - if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ - RB_COLOR(tmp, field) = RB_BLACK; \ - RB_SET_BLACKRED(parent, gparent, field); \ - elm = gparent; \ - continue; \ - } \ - if (RB_LEFT(parent, field) == elm) { \ - RB_ROTATE_RIGHT(head, parent, tmp, field); \ - tmp = parent; \ - parent = elm; \ - elm = tmp; \ - } \ - RB_SET_BLACKRED(parent, gparent, field); \ - RB_ROTATE_LEFT(head, gparent, tmp, field); \ - } \ - } \ - RB_COLOR(head->rbh_root, field) = RB_BLACK; \ -} \ - \ -attr void \ -name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, \ - struct type *elm) \ -{ \ - struct type *tmp; \ - while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \ - elm != RB_ROOT(head)) { \ - if (RB_LEFT(parent, field) == elm) { \ - tmp = RB_RIGHT(parent, field); \ - if (RB_COLOR(tmp, field) == RB_RED) { \ - RB_SET_BLACKRED(tmp, parent, field); \ - RB_ROTATE_LEFT(head, parent, tmp, field); \ - tmp = RB_RIGHT(parent, field); \ - } \ - if ((RB_LEFT(tmp, field) == NULL || \ - RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) && \ - (RB_RIGHT(tmp, field) == NULL || \ - RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) { \ - RB_COLOR(tmp, field) = RB_RED; \ - elm = parent; \ - parent = RB_PARENT(elm, field); \ - } else { \ - if (RB_RIGHT(tmp, field) == NULL || \ - RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) { \ - struct type *oleft; \ - if ((oleft = RB_LEFT(tmp, field)) \ - != NULL) \ - RB_COLOR(oleft, field) = RB_BLACK; \ - RB_COLOR(tmp, field) = RB_RED; \ - RB_ROTATE_RIGHT(head, tmp, oleft, field); \ - tmp = RB_RIGHT(parent, field); \ - } \ - RB_COLOR(tmp, field) = RB_COLOR(parent, field); \ - RB_COLOR(parent, field) = RB_BLACK; \ - if (RB_RIGHT(tmp, field)) \ - RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK; \ - RB_ROTATE_LEFT(head, parent, tmp, field); \ - elm = RB_ROOT(head); \ - break; \ - } \ - } else { \ - tmp = RB_LEFT(parent, field); \ - if (RB_COLOR(tmp, field) == RB_RED) { \ - RB_SET_BLACKRED(tmp, parent, field); \ - RB_ROTATE_RIGHT(head, parent, tmp, field); \ - tmp = RB_LEFT(parent, field); \ - } \ - if ((RB_LEFT(tmp, field) == NULL || \ - RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) && \ - (RB_RIGHT(tmp, field) == NULL || \ - RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) { \ - RB_COLOR(tmp, field) = RB_RED; \ - elm = parent; \ - parent = RB_PARENT(elm, field); \ - } else { \ - if (RB_LEFT(tmp, field) == NULL || \ - RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) { \ - struct type *oright; \ - if ((oright = RB_RIGHT(tmp, field)) \ - != NULL) \ - RB_COLOR(oright, field) = RB_BLACK; \ - RB_COLOR(tmp, field) = RB_RED; \ - RB_ROTATE_LEFT(head, tmp, oright, field); \ - tmp = RB_LEFT(parent, field); \ - } \ - RB_COLOR(tmp, field) = RB_COLOR(parent, field); \ - RB_COLOR(parent, field) = RB_BLACK; \ - if (RB_LEFT(tmp, field)) \ - RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK; \ - RB_ROTATE_RIGHT(head, parent, tmp, field); \ - elm = RB_ROOT(head); \ - break; \ - } \ - } \ - } \ - if (elm) \ - RB_COLOR(elm, field) = RB_BLACK; \ -} \ - \ -attr struct type * \ -name##_RB_REMOVE(struct name *head, struct type *elm) \ -{ \ - struct type *child, *parent, *old = elm; \ - int color; \ - if (RB_LEFT(elm, field) == NULL) \ - child = RB_RIGHT(elm, field); \ - else if (RB_RIGHT(elm, field) == NULL) \ - child = RB_LEFT(elm, field); \ - else { \ - struct type *left; \ - elm = RB_RIGHT(elm, field); \ - while ((left = RB_LEFT(elm, field)) != NULL) \ - elm = left; \ - child = RB_RIGHT(elm, field); \ - parent = RB_PARENT(elm, field); \ - color = RB_COLOR(elm, field); \ - if (child) \ - RB_PARENT(child, field) = parent; \ - if (parent) { \ - if (RB_LEFT(parent, field) == elm) \ - RB_LEFT(parent, field) = child; \ - else \ - RB_RIGHT(parent, field) = child; \ - RB_AUGMENT(parent); \ - } else \ - RB_ROOT(head) = child; \ - if (RB_PARENT(elm, field) == old) \ - parent = elm; \ - (elm)->field = (old)->field; \ - if (RB_PARENT(old, field)) { \ - if (RB_LEFT(RB_PARENT(old, field), field) == old) \ - RB_LEFT(RB_PARENT(old, field), field) = elm; \ - else \ - RB_RIGHT(RB_PARENT(old, field), field) = elm; \ - RB_AUGMENT(RB_PARENT(old, field)); \ - } else \ - RB_ROOT(head) = elm; \ - RB_PARENT(RB_LEFT(old, field), field) = elm; \ - if (RB_RIGHT(old, field)) \ - RB_PARENT(RB_RIGHT(old, field), field) = elm; \ - if (parent) { \ - left = parent; \ - do { \ - RB_AUGMENT(left); \ - } while ((left = RB_PARENT(left, field)) != NULL); \ - } \ - goto color; \ - } \ - parent = RB_PARENT(elm, field); \ - color = RB_COLOR(elm, field); \ - if (child) \ - RB_PARENT(child, field) = parent; \ - if (parent) { \ - if (RB_LEFT(parent, field) == elm) \ - RB_LEFT(parent, field) = child; \ - else \ - RB_RIGHT(parent, field) = child; \ - RB_AUGMENT(parent); \ - } else \ - RB_ROOT(head) = child; \ -color: \ - if (color == RB_BLACK) \ - name##_RB_REMOVE_COLOR(head, parent, child); \ - return (old); \ -} \ - \ -/* Inserts a node into the RB tree */ \ -attr struct type * \ -name##_RB_INSERT(struct name *head, struct type *elm) \ -{ \ - struct type *tmp; \ - struct type *parent = NULL; \ - int comp = 0; \ - tmp = RB_ROOT(head); \ - while (tmp) { \ - parent = tmp; \ - comp = (cmp)(elm, parent); \ - if (comp < 0) \ - tmp = RB_LEFT(tmp, field); \ - else if (comp > 0) \ - tmp = RB_RIGHT(tmp, field); \ - else \ - return (tmp); \ - } \ - RB_SET(elm, parent, field); \ - if (parent != NULL) { \ - if (comp < 0) \ - RB_LEFT(parent, field) = elm; \ - else \ - RB_RIGHT(parent, field) = elm; \ - RB_AUGMENT(parent); \ - } else \ - RB_ROOT(head) = elm; \ - name##_RB_INSERT_COLOR(head, elm); \ - return (NULL); \ -} \ - \ -/* Finds the node with the same key as elm */ \ -attr struct type * \ -name##_RB_FIND(struct name *head, struct type *elm) \ -{ \ - struct type *tmp = RB_ROOT(head); \ - int comp; \ - while (tmp) { \ - comp = cmp(elm, tmp); \ - if (comp < 0) \ - tmp = RB_LEFT(tmp, field); \ - else if (comp > 0) \ - tmp = RB_RIGHT(tmp, field); \ - else \ - return (tmp); \ - } \ - return (NULL); \ -} \ - \ -/* Finds the first node greater than or equal to the search key */ \ -attr struct type * \ -name##_RB_NFIND(struct name *head, struct type *elm) \ -{ \ - struct type *tmp = RB_ROOT(head); \ - struct type *res = NULL; \ - int comp; \ - while (tmp) { \ - comp = cmp(elm, tmp); \ - if (comp < 0) { \ - res = tmp; \ - tmp = RB_LEFT(tmp, field); \ - } \ - else if (comp > 0) \ - tmp = RB_RIGHT(tmp, field); \ - else \ - return (tmp); \ - } \ - return (res); \ -} \ - \ -/* ARGSUSED */ \ -attr struct type * \ -name##_RB_NEXT(struct type *elm) \ -{ \ - if (RB_RIGHT(elm, field)) { \ - elm = RB_RIGHT(elm, field); \ - while (RB_LEFT(elm, field)) \ - elm = RB_LEFT(elm, field); \ - } else { \ - if (RB_PARENT(elm, field) && \ - (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ - elm = RB_PARENT(elm, field); \ - else { \ - while (RB_PARENT(elm, field) && \ - (elm == RB_RIGHT(RB_PARENT(elm, field), field))) \ - elm = RB_PARENT(elm, field); \ - elm = RB_PARENT(elm, field); \ - } \ - } \ - return (elm); \ -} \ - \ -/* ARGSUSED */ \ -attr struct type * \ -name##_RB_PREV(struct type *elm) \ -{ \ - if (RB_LEFT(elm, field)) { \ - elm = RB_LEFT(elm, field); \ - while (RB_RIGHT(elm, field)) \ - elm = RB_RIGHT(elm, field); \ - } else { \ - if (RB_PARENT(elm, field) && \ - (elm == RB_RIGHT(RB_PARENT(elm, field), field))) \ - elm = RB_PARENT(elm, field); \ - else { \ - while (RB_PARENT(elm, field) && \ - (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ - elm = RB_PARENT(elm, field); \ - elm = RB_PARENT(elm, field); \ - } \ - } \ - return (elm); \ -} \ - \ -attr struct type * \ -name##_RB_MINMAX(struct name *head, int val) \ -{ \ - struct type *tmp = RB_ROOT(head); \ - struct type *parent = NULL; \ - while (tmp) { \ - parent = tmp; \ - if (val < 0) \ - tmp = RB_LEFT(tmp, field); \ - else \ - tmp = RB_RIGHT(tmp, field); \ - } \ - return (parent); \ -} - -#define RB_NEGINF -1 -#define RB_INF 1 - -#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y) -#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y) -#define RB_FIND(name, x, y) name##_RB_FIND(x, y) -#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y) -#define RB_NEXT(name, x, y) name##_RB_NEXT(y) -#define RB_PREV(name, x, y) name##_RB_PREV(y) -#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF) -#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF) - -#define RB_FOREACH(x, name, head) \ - for ((x) = RB_MIN(name, head); \ - (x) != NULL; \ - (x) = name##_RB_NEXT(x)) - -#define RB_FOREACH_FROM(x, name, y) \ - for ((x) = (y); \ - ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \ - (x) = (y)) - -#define RB_FOREACH_SAFE(x, name, head, y) \ - for ((x) = RB_MIN(name, head); \ - ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \ - (x) = (y)) - -#define RB_FOREACH_REVERSE(x, name, head) \ - for ((x) = RB_MAX(name, head); \ - (x) != NULL; \ - (x) = name##_RB_PREV(x)) - -#define RB_FOREACH_REVERSE_FROM(x, name, y) \ - for ((x) = (y); \ - ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \ - (x) = (y)) - -#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \ - for ((x) = RB_MAX(name, head); \ - ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \ - (x) = (y)) - -#endif /* UV_TREE_H_ */ diff --git a/libuv/include/uv-aix.h b/libuv/include/uv-aix.h deleted file mode 100644 index 7dc992f..0000000 --- a/libuv/include/uv-aix.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_AIX_H -#define UV_AIX_H - -#define UV_PLATFORM_LOOP_FIELDS \ - int fs_fd; \ - -#define UV_PLATFORM_FS_EVENT_FIELDS \ - uv__io_t event_watcher; \ - char *dir_filename; \ - -#endif /* UV_AIX_H */ diff --git a/libuv/include/uv-bsd.h b/libuv/include/uv-bsd.h deleted file mode 100644 index 2d72b3d..0000000 --- a/libuv/include/uv-bsd.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_BSD_H -#define UV_BSD_H - -#define UV_PLATFORM_FS_EVENT_FIELDS \ - uv__io_t event_watcher; \ - -#define UV_IO_PRIVATE_PLATFORM_FIELDS \ - int rcount; \ - int wcount; \ - -#define UV_HAVE_KQUEUE 1 - -#endif /* UV_BSD_H */ diff --git a/libuv/include/uv-darwin.h b/libuv/include/uv-darwin.h deleted file mode 100644 index d226415..0000000 --- a/libuv/include/uv-darwin.h +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_DARWIN_H -#define UV_DARWIN_H - -#if defined(__APPLE__) && defined(__MACH__) -# include -# include -# include -# include -# define UV_PLATFORM_SEM_T semaphore_t -#endif - -#define UV_IO_PRIVATE_PLATFORM_FIELDS \ - int rcount; \ - int wcount; \ - -#define UV_PLATFORM_LOOP_FIELDS \ - uv_thread_t cf_thread; \ - void* _cf_reserved; \ - void* cf_state; \ - uv_mutex_t cf_mutex; \ - uv_sem_t cf_sem; \ - void* cf_signals[2]; \ - -#define UV_PLATFORM_FS_EVENT_FIELDS \ - uv__io_t event_watcher; \ - char* realpath; \ - int realpath_len; \ - int cf_flags; \ - uv_async_t* cf_cb; \ - void* cf_events[2]; \ - void* cf_member[2]; \ - int cf_error; \ - uv_mutex_t cf_mutex; \ - -#define UV_STREAM_PRIVATE_PLATFORM_FIELDS \ - void* select; \ - -#define UV_HAVE_KQUEUE 1 - -#endif /* UV_DARWIN_H */ diff --git a/libuv/include/uv-errno.h b/libuv/include/uv-errno.h deleted file mode 100644 index c341327..0000000 --- a/libuv/include/uv-errno.h +++ /dev/null @@ -1,402 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_ERRNO_H_ -#define UV_ERRNO_H_ - -#include - -#define UV__EOF (-4095) -#define UV__UNKNOWN (-4094) - -#define UV__EAI_ADDRFAMILY (-3000) -#define UV__EAI_AGAIN (-3001) -#define UV__EAI_BADFLAGS (-3002) -#define UV__EAI_CANCELED (-3003) -#define UV__EAI_FAIL (-3004) -#define UV__EAI_FAMILY (-3005) -#define UV__EAI_MEMORY (-3006) -#define UV__EAI_NODATA (-3007) -#define UV__EAI_NONAME (-3008) -#define UV__EAI_OVERFLOW (-3009) -#define UV__EAI_SERVICE (-3010) -#define UV__EAI_SOCKTYPE (-3011) -#define UV__EAI_BADHINTS (-3013) -#define UV__EAI_PROTOCOL (-3014) - -/* Only map to the system errno on non-Windows platforms. It's apparently - * a fairly common practice for Windows programmers to redefine errno codes. - */ -#if defined(E2BIG) && !defined(_WIN32) -# define UV__E2BIG (-E2BIG) -#else -# define UV__E2BIG (-4093) -#endif - -#if defined(EACCES) && !defined(_WIN32) -# define UV__EACCES (-EACCES) -#else -# define UV__EACCES (-4092) -#endif - -#if defined(EADDRINUSE) && !defined(_WIN32) -# define UV__EADDRINUSE (-EADDRINUSE) -#else -# define UV__EADDRINUSE (-4091) -#endif - -#if defined(EADDRNOTAVAIL) && !defined(_WIN32) -# define UV__EADDRNOTAVAIL (-EADDRNOTAVAIL) -#else -# define UV__EADDRNOTAVAIL (-4090) -#endif - -#if defined(EAFNOSUPPORT) && !defined(_WIN32) -# define UV__EAFNOSUPPORT (-EAFNOSUPPORT) -#else -# define UV__EAFNOSUPPORT (-4089) -#endif - -#if defined(EAGAIN) && !defined(_WIN32) -# define UV__EAGAIN (-EAGAIN) -#else -# define UV__EAGAIN (-4088) -#endif - -#if defined(EALREADY) && !defined(_WIN32) -# define UV__EALREADY (-EALREADY) -#else -# define UV__EALREADY (-4084) -#endif - -#if defined(EBADF) && !defined(_WIN32) -# define UV__EBADF (-EBADF) -#else -# define UV__EBADF (-4083) -#endif - -#if defined(EBUSY) && !defined(_WIN32) -# define UV__EBUSY (-EBUSY) -#else -# define UV__EBUSY (-4082) -#endif - -#if defined(ECANCELED) && !defined(_WIN32) -# define UV__ECANCELED (-ECANCELED) -#else -# define UV__ECANCELED (-4081) -#endif - -#if defined(ECHARSET) && !defined(_WIN32) -# define UV__ECHARSET (-ECHARSET) -#else -# define UV__ECHARSET (-4080) -#endif - -#if defined(ECONNABORTED) && !defined(_WIN32) -# define UV__ECONNABORTED (-ECONNABORTED) -#else -# define UV__ECONNABORTED (-4079) -#endif - -#if defined(ECONNREFUSED) && !defined(_WIN32) -# define UV__ECONNREFUSED (-ECONNREFUSED) -#else -# define UV__ECONNREFUSED (-4078) -#endif - -#if defined(ECONNRESET) && !defined(_WIN32) -# define UV__ECONNRESET (-ECONNRESET) -#else -# define UV__ECONNRESET (-4077) -#endif - -#if defined(EDESTADDRREQ) && !defined(_WIN32) -# define UV__EDESTADDRREQ (-EDESTADDRREQ) -#else -# define UV__EDESTADDRREQ (-4076) -#endif - -#if defined(EEXIST) && !defined(_WIN32) -# define UV__EEXIST (-EEXIST) -#else -# define UV__EEXIST (-4075) -#endif - -#if defined(EFAULT) && !defined(_WIN32) -# define UV__EFAULT (-EFAULT) -#else -# define UV__EFAULT (-4074) -#endif - -#if defined(EHOSTUNREACH) && !defined(_WIN32) -# define UV__EHOSTUNREACH (-EHOSTUNREACH) -#else -# define UV__EHOSTUNREACH (-4073) -#endif - -#if defined(EINTR) && !defined(_WIN32) -# define UV__EINTR (-EINTR) -#else -# define UV__EINTR (-4072) -#endif - -#if defined(EINVAL) && !defined(_WIN32) -# define UV__EINVAL (-EINVAL) -#else -# define UV__EINVAL (-4071) -#endif - -#if defined(EIO) && !defined(_WIN32) -# define UV__EIO (-EIO) -#else -# define UV__EIO (-4070) -#endif - -#if defined(EISCONN) && !defined(_WIN32) -# define UV__EISCONN (-EISCONN) -#else -# define UV__EISCONN (-4069) -#endif - -#if defined(EISDIR) && !defined(_WIN32) -# define UV__EISDIR (-EISDIR) -#else -# define UV__EISDIR (-4068) -#endif - -#if defined(ELOOP) && !defined(_WIN32) -# define UV__ELOOP (-ELOOP) -#else -# define UV__ELOOP (-4067) -#endif - -#if defined(EMFILE) && !defined(_WIN32) -# define UV__EMFILE (-EMFILE) -#else -# define UV__EMFILE (-4066) -#endif - -#if defined(EMSGSIZE) && !defined(_WIN32) -# define UV__EMSGSIZE (-EMSGSIZE) -#else -# define UV__EMSGSIZE (-4065) -#endif - -#if defined(ENAMETOOLONG) && !defined(_WIN32) -# define UV__ENAMETOOLONG (-ENAMETOOLONG) -#else -# define UV__ENAMETOOLONG (-4064) -#endif - -#if defined(ENETDOWN) && !defined(_WIN32) -# define UV__ENETDOWN (-ENETDOWN) -#else -# define UV__ENETDOWN (-4063) -#endif - -#if defined(ENETUNREACH) && !defined(_WIN32) -# define UV__ENETUNREACH (-ENETUNREACH) -#else -# define UV__ENETUNREACH (-4062) -#endif - -#if defined(ENFILE) && !defined(_WIN32) -# define UV__ENFILE (-ENFILE) -#else -# define UV__ENFILE (-4061) -#endif - -#if defined(ENOBUFS) && !defined(_WIN32) -# define UV__ENOBUFS (-ENOBUFS) -#else -# define UV__ENOBUFS (-4060) -#endif - -#if defined(ENODEV) && !defined(_WIN32) -# define UV__ENODEV (-ENODEV) -#else -# define UV__ENODEV (-4059) -#endif - -#if defined(ENOENT) && !defined(_WIN32) -# define UV__ENOENT (-ENOENT) -#else -# define UV__ENOENT (-4058) -#endif - -#if defined(ENOMEM) && !defined(_WIN32) -# define UV__ENOMEM (-ENOMEM) -#else -# define UV__ENOMEM (-4057) -#endif - -#if defined(ENONET) && !defined(_WIN32) -# define UV__ENONET (-ENONET) -#else -# define UV__ENONET (-4056) -#endif - -#if defined(ENOSPC) && !defined(_WIN32) -# define UV__ENOSPC (-ENOSPC) -#else -# define UV__ENOSPC (-4055) -#endif - -#if defined(ENOSYS) && !defined(_WIN32) -# define UV__ENOSYS (-ENOSYS) -#else -# define UV__ENOSYS (-4054) -#endif - -#if defined(ENOTCONN) && !defined(_WIN32) -# define UV__ENOTCONN (-ENOTCONN) -#else -# define UV__ENOTCONN (-4053) -#endif - -#if defined(ENOTDIR) && !defined(_WIN32) -# define UV__ENOTDIR (-ENOTDIR) -#else -# define UV__ENOTDIR (-4052) -#endif - -#if defined(ENOTEMPTY) && !defined(_WIN32) -# define UV__ENOTEMPTY (-ENOTEMPTY) -#else -# define UV__ENOTEMPTY (-4051) -#endif - -#if defined(ENOTSOCK) && !defined(_WIN32) -# define UV__ENOTSOCK (-ENOTSOCK) -#else -# define UV__ENOTSOCK (-4050) -#endif - -#if defined(ENOTSUP) && !defined(_WIN32) -# define UV__ENOTSUP (-ENOTSUP) -#else -# define UV__ENOTSUP (-4049) -#endif - -#if defined(EPERM) && !defined(_WIN32) -# define UV__EPERM (-EPERM) -#else -# define UV__EPERM (-4048) -#endif - -#if defined(EPIPE) && !defined(_WIN32) -# define UV__EPIPE (-EPIPE) -#else -# define UV__EPIPE (-4047) -#endif - -#if defined(EPROTO) && !defined(_WIN32) -# define UV__EPROTO (-EPROTO) -#else -# define UV__EPROTO (-4046) -#endif - -#if defined(EPROTONOSUPPORT) && !defined(_WIN32) -# define UV__EPROTONOSUPPORT (-EPROTONOSUPPORT) -#else -# define UV__EPROTONOSUPPORT (-4045) -#endif - -#if defined(EPROTOTYPE) && !defined(_WIN32) -# define UV__EPROTOTYPE (-EPROTOTYPE) -#else -# define UV__EPROTOTYPE (-4044) -#endif - -#if defined(EROFS) && !defined(_WIN32) -# define UV__EROFS (-EROFS) -#else -# define UV__EROFS (-4043) -#endif - -#if defined(ESHUTDOWN) && !defined(_WIN32) -# define UV__ESHUTDOWN (-ESHUTDOWN) -#else -# define UV__ESHUTDOWN (-4042) -#endif - -#if defined(ESPIPE) && !defined(_WIN32) -# define UV__ESPIPE (-ESPIPE) -#else -# define UV__ESPIPE (-4041) -#endif - -#if defined(ESRCH) && !defined(_WIN32) -# define UV__ESRCH (-ESRCH) -#else -# define UV__ESRCH (-4040) -#endif - -#if defined(ETIMEDOUT) && !defined(_WIN32) -# define UV__ETIMEDOUT (-ETIMEDOUT) -#else -# define UV__ETIMEDOUT (-4039) -#endif - -#if defined(ETXTBSY) && !defined(_WIN32) -# define UV__ETXTBSY (-ETXTBSY) -#else -# define UV__ETXTBSY (-4038) -#endif - -#if defined(EXDEV) && !defined(_WIN32) -# define UV__EXDEV (-EXDEV) -#else -# define UV__EXDEV (-4037) -#endif - -#if defined(EFBIG) && !defined(_WIN32) -# define UV__EFBIG (-EFBIG) -#else -# define UV__EFBIG (-4036) -#endif - -#if defined(ENOPROTOOPT) && !defined(_WIN32) -# define UV__ENOPROTOOPT (-ENOPROTOOPT) -#else -# define UV__ENOPROTOOPT (-4035) -#endif - -#if defined(ERANGE) && !defined(_WIN32) -# define UV__ERANGE (-ERANGE) -#else -# define UV__ERANGE (-4034) -#endif - -#if defined(ENXIO) && !defined(_WIN32) -# define UV__ENXIO (-ENXIO) -#else -# define UV__ENXIO (-4033) -#endif - -#if defined(EMLINK) && !defined(_WIN32) -# define UV__EMLINK (-EMLINK) -#else -# define UV__EMLINK (-4032) -#endif - -#endif /* UV_ERRNO_H_ */ diff --git a/libuv/include/uv-linux.h b/libuv/include/uv-linux.h deleted file mode 100644 index 9b38405..0000000 --- a/libuv/include/uv-linux.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_LINUX_H -#define UV_LINUX_H - -#define UV_PLATFORM_LOOP_FIELDS \ - uv__io_t inotify_read_watcher; \ - void* inotify_watchers; \ - int inotify_fd; \ - -#define UV_PLATFORM_FS_EVENT_FIELDS \ - void* watchers[2]; \ - int wd; \ - -#endif /* UV_LINUX_H */ diff --git a/libuv/include/uv-sunos.h b/libuv/include/uv-sunos.h deleted file mode 100644 index 0421664..0000000 --- a/libuv/include/uv-sunos.h +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_SUNOS_H -#define UV_SUNOS_H - -#include -#include - -/* For the sake of convenience and reduced #ifdef-ery in src/unix/sunos.c, - * add the fs_event fields even when this version of SunOS doesn't support - * file watching. - */ -#define UV_PLATFORM_LOOP_FIELDS \ - uv__io_t fs_event_watcher; \ - int fs_fd; \ - -#if defined(PORT_SOURCE_FILE) - -# define UV_PLATFORM_FS_EVENT_FIELDS \ - file_obj_t fo; \ - int fd; \ - -#endif /* defined(PORT_SOURCE_FILE) */ - -#endif /* UV_SUNOS_H */ diff --git a/libuv/include/uv-threadpool.h b/libuv/include/uv-threadpool.h deleted file mode 100644 index 9708ebd..0000000 --- a/libuv/include/uv-threadpool.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* - * This file is private to libuv. It provides common functionality to both - * Windows and Unix backends. - */ - -#ifndef UV_THREADPOOL_H_ -#define UV_THREADPOOL_H_ - -struct uv__work { - void (*work)(struct uv__work *w); - void (*done)(struct uv__work *w, int status); - struct uv_loop_s* loop; - void* wq[2]; -}; - -#endif /* UV_THREADPOOL_H_ */ diff --git a/libuv/include/uv-unix.h b/libuv/include/uv-unix.h deleted file mode 100644 index 82d193b..0000000 --- a/libuv/include/uv-unix.h +++ /dev/null @@ -1,383 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_UNIX_H -#define UV_UNIX_H - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#ifdef __ANDROID__ -#include "pthread-fixes.h" -#endif -#include - -#include "uv-threadpool.h" - -#if defined(__linux__) -# include "uv-linux.h" -#elif defined(_AIX) -# include "uv-aix.h" -#elif defined(__sun) -# include "uv-sunos.h" -#elif defined(__APPLE__) -# include "uv-darwin.h" -#elif defined(__DragonFly__) || \ - defined(__FreeBSD__) || \ - defined(__OpenBSD__) || \ - defined(__NetBSD__) -# include "uv-bsd.h" -#endif - -#ifndef NI_MAXHOST -# define NI_MAXHOST 1025 -#endif - -#ifndef NI_MAXSERV -# define NI_MAXSERV 32 -#endif - -#ifndef UV_IO_PRIVATE_PLATFORM_FIELDS -# define UV_IO_PRIVATE_PLATFORM_FIELDS /* empty */ -#endif - -struct uv__io_s; -struct uv__async; -struct uv_loop_s; - -typedef void (*uv__io_cb)(struct uv_loop_s* loop, - struct uv__io_s* w, - unsigned int events); -typedef struct uv__io_s uv__io_t; - -struct uv__io_s { - uv__io_cb cb; - void* pending_queue[2]; - void* watcher_queue[2]; - unsigned int pevents; /* Pending event mask i.e. mask at next tick. */ - unsigned int events; /* Current event mask. */ - int fd; - UV_IO_PRIVATE_PLATFORM_FIELDS -}; - -typedef void (*uv__async_cb)(struct uv_loop_s* loop, - struct uv__async* w, - unsigned int nevents); - -struct uv__async { - uv__async_cb cb; - uv__io_t io_watcher; - int wfd; -}; - -#ifndef UV_PLATFORM_SEM_T -# define UV_PLATFORM_SEM_T sem_t -#endif - -#ifndef UV_PLATFORM_LOOP_FIELDS -# define UV_PLATFORM_LOOP_FIELDS /* empty */ -#endif - -#ifndef UV_PLATFORM_FS_EVENT_FIELDS -# define UV_PLATFORM_FS_EVENT_FIELDS /* empty */ -#endif - -#ifndef UV_STREAM_PRIVATE_PLATFORM_FIELDS -# define UV_STREAM_PRIVATE_PLATFORM_FIELDS /* empty */ -#endif - -/* Note: May be cast to struct iovec. See writev(2). */ -typedef struct uv_buf_t { - char* base; - size_t len; -} uv_buf_t; - -typedef int uv_file; -typedef int uv_os_sock_t; -typedef int uv_os_fd_t; - -#define UV_ONCE_INIT PTHREAD_ONCE_INIT - -typedef pthread_once_t uv_once_t; -typedef pthread_t uv_thread_t; -typedef pthread_mutex_t uv_mutex_t; -typedef pthread_rwlock_t uv_rwlock_t; -typedef UV_PLATFORM_SEM_T uv_sem_t; -typedef pthread_cond_t uv_cond_t; -typedef pthread_key_t uv_key_t; - -#if defined(__APPLE__) && defined(__MACH__) - -typedef struct { - unsigned int n; - unsigned int count; - uv_mutex_t mutex; - uv_sem_t turnstile1; - uv_sem_t turnstile2; -} uv_barrier_t; - -#else /* defined(__APPLE__) && defined(__MACH__) */ - -typedef pthread_barrier_t uv_barrier_t; - -#endif /* defined(__APPLE__) && defined(__MACH__) */ - -/* Platform-specific definitions for uv_spawn support. */ -typedef gid_t uv_gid_t; -typedef uid_t uv_uid_t; - -typedef struct dirent uv__dirent_t; - -#if defined(DT_UNKNOWN) -# define HAVE_DIRENT_TYPES -# if defined(DT_REG) -# define UV__DT_FILE DT_REG -# else -# define UV__DT_FILE -1 -# endif -# if defined(DT_DIR) -# define UV__DT_DIR DT_DIR -# else -# define UV__DT_DIR -2 -# endif -# if defined(DT_LNK) -# define UV__DT_LINK DT_LNK -# else -# define UV__DT_LINK -3 -# endif -# if defined(DT_FIFO) -# define UV__DT_FIFO DT_FIFO -# else -# define UV__DT_FIFO -4 -# endif -# if defined(DT_SOCK) -# define UV__DT_SOCKET DT_SOCK -# else -# define UV__DT_SOCKET -5 -# endif -# if defined(DT_CHR) -# define UV__DT_CHAR DT_CHR -# else -# define UV__DT_CHAR -6 -# endif -# if defined(DT_BLK) -# define UV__DT_BLOCK DT_BLK -# else -# define UV__DT_BLOCK -7 -# endif -#endif - -/* Platform-specific definitions for uv_dlopen support. */ -#define UV_DYNAMIC /* empty */ - -typedef struct { - void* handle; - char* errmsg; -} uv_lib_t; - -#define UV_LOOP_PRIVATE_FIELDS \ - unsigned long flags; \ - int backend_fd; \ - void* pending_queue[2]; \ - void* watcher_queue[2]; \ - uv__io_t** watchers; \ - unsigned int nwatchers; \ - unsigned int nfds; \ - void* wq[2]; \ - uv_mutex_t wq_mutex; \ - uv_async_t wq_async; \ - uv_rwlock_t cloexec_lock; \ - uv_handle_t* closing_handles; \ - void* process_handles[2]; \ - void* prepare_handles[2]; \ - void* check_handles[2]; \ - void* idle_handles[2]; \ - void* async_handles[2]; \ - struct uv__async async_watcher; \ - struct { \ - void* min; \ - unsigned int nelts; \ - } timer_heap; \ - uint64_t timer_counter; \ - uint64_t time; \ - int signal_pipefd[2]; \ - uv__io_t signal_io_watcher; \ - uv_signal_t child_watcher; \ - int emfile_fd; \ - UV_PLATFORM_LOOP_FIELDS \ - -#define UV_REQ_TYPE_PRIVATE /* empty */ - -#define UV_REQ_PRIVATE_FIELDS /* empty */ - -#define UV_PRIVATE_REQ_TYPES /* empty */ - -#define UV_WRITE_PRIVATE_FIELDS \ - void* queue[2]; \ - unsigned int write_index; \ - uv_buf_t* bufs; \ - unsigned int nbufs; \ - int error; \ - uv_buf_t bufsml[4]; \ - -#define UV_CONNECT_PRIVATE_FIELDS \ - void* queue[2]; \ - -#define UV_SHUTDOWN_PRIVATE_FIELDS /* empty */ - -#define UV_UDP_SEND_PRIVATE_FIELDS \ - void* queue[2]; \ - struct sockaddr_storage addr; \ - unsigned int nbufs; \ - uv_buf_t* bufs; \ - ssize_t status; \ - uv_udp_send_cb send_cb; \ - uv_buf_t bufsml[4]; \ - -#define UV_HANDLE_PRIVATE_FIELDS \ - uv_handle_t* next_closing; \ - unsigned int flags; \ - -#define UV_STREAM_PRIVATE_FIELDS \ - uv_connect_t *connect_req; \ - uv_shutdown_t *shutdown_req; \ - uv__io_t io_watcher; \ - void* write_queue[2]; \ - void* write_completed_queue[2]; \ - uv_connection_cb connection_cb; \ - int delayed_error; \ - int accepted_fd; \ - void* queued_fds; \ - UV_STREAM_PRIVATE_PLATFORM_FIELDS \ - -#define UV_TCP_PRIVATE_FIELDS /* empty */ - -#define UV_UDP_PRIVATE_FIELDS \ - uv_alloc_cb alloc_cb; \ - uv_udp_recv_cb recv_cb; \ - uv__io_t io_watcher; \ - void* write_queue[2]; \ - void* write_completed_queue[2]; \ - -#define UV_PIPE_PRIVATE_FIELDS \ - const char* pipe_fname; /* strdup'ed */ - -#define UV_POLL_PRIVATE_FIELDS \ - uv__io_t io_watcher; - -#define UV_PREPARE_PRIVATE_FIELDS \ - uv_prepare_cb prepare_cb; \ - void* queue[2]; \ - -#define UV_CHECK_PRIVATE_FIELDS \ - uv_check_cb check_cb; \ - void* queue[2]; \ - -#define UV_IDLE_PRIVATE_FIELDS \ - uv_idle_cb idle_cb; \ - void* queue[2]; \ - -#define UV_ASYNC_PRIVATE_FIELDS \ - uv_async_cb async_cb; \ - void* queue[2]; \ - int pending; \ - -#define UV_TIMER_PRIVATE_FIELDS \ - uv_timer_cb timer_cb; \ - void* heap_node[3]; \ - uint64_t timeout; \ - uint64_t repeat; \ - uint64_t start_id; - -#define UV_GETADDRINFO_PRIVATE_FIELDS \ - struct uv__work work_req; \ - uv_getaddrinfo_cb cb; \ - struct addrinfo* hints; \ - char* hostname; \ - char* service; \ - struct addrinfo* addrinfo; \ - int retcode; - -#define UV_GETNAMEINFO_PRIVATE_FIELDS \ - struct uv__work work_req; \ - uv_getnameinfo_cb getnameinfo_cb; \ - struct sockaddr_storage storage; \ - int flags; \ - char host[NI_MAXHOST]; \ - char service[NI_MAXSERV]; \ - int retcode; - -#define UV_PROCESS_PRIVATE_FIELDS \ - void* queue[2]; \ - int status; \ - -#define UV_FS_PRIVATE_FIELDS \ - const char *new_path; \ - uv_file file; \ - int flags; \ - mode_t mode; \ - unsigned int nbufs; \ - uv_buf_t* bufs; \ - off_t off; \ - uv_uid_t uid; \ - uv_gid_t gid; \ - double atime; \ - double mtime; \ - struct uv__work work_req; \ - uv_buf_t bufsml[4]; \ - -#define UV_WORK_PRIVATE_FIELDS \ - struct uv__work work_req; - -#define UV_TTY_PRIVATE_FIELDS \ - struct termios orig_termios; \ - int mode; - -#define UV_SIGNAL_PRIVATE_FIELDS \ - /* RB_ENTRY(uv_signal_s) tree_entry; */ \ - struct { \ - struct uv_signal_s* rbe_left; \ - struct uv_signal_s* rbe_right; \ - struct uv_signal_s* rbe_parent; \ - int rbe_color; \ - } tree_entry; \ - /* Use two counters here so we don have to fiddle with atomics. */ \ - unsigned int caught_signals; \ - unsigned int dispatched_signals; - -#define UV_FS_EVENT_PRIVATE_FIELDS \ - uv_fs_event_cb cb; \ - UV_PLATFORM_FS_EVENT_FIELDS \ - -#endif /* UV_UNIX_H */ diff --git a/libuv/include/uv-version.h b/libuv/include/uv-version.h deleted file mode 100644 index c78c8b7..0000000 --- a/libuv/include/uv-version.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_VERSION_H -#define UV_VERSION_H - - /* - * Versions with the same major number are ABI stable. API is allowed to - * evolve between minor releases, but only in a backwards compatible way. - * Make sure you update the -soname directives in configure.ac - * and uv.gyp whenever you bump UV_VERSION_MAJOR or UV_VERSION_MINOR (but - * not UV_VERSION_PATCH.) - */ - -#define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 3 -#define UV_VERSION_PATCH 0 -#define UV_VERSION_IS_RELEASE 1 -#define UV_VERSION_SUFFIX "" - -#endif /* UV_VERSION_H */ diff --git a/libuv/include/uv-win.h b/libuv/include/uv-win.h deleted file mode 100644 index b744d62..0000000 --- a/libuv/include/uv-win.h +++ /dev/null @@ -1,656 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef _WIN32_WINNT -# define _WIN32_WINNT 0x0502 -#endif - -#if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED) -typedef intptr_t ssize_t; -# define _SSIZE_T_ -# define _SSIZE_T_DEFINED -#endif - -#include - -#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) -typedef struct pollfd { - SOCKET fd; - short events; - short revents; -} WSAPOLLFD, *PWSAPOLLFD, *LPWSAPOLLFD; -#endif - -#ifndef LOCALE_INVARIANT -# define LOCALE_INVARIANT 0x007f -#endif - -#ifndef _malloca -# if defined(_DEBUG) -# define _malloca(size) malloc(size) -# define _freea(ptr) free(ptr) -# else -# define _malloca(size) alloca(size) -# define _freea(ptr) -# endif -#endif - -#include -#include -#include - -#include -#include -#include - -#if defined(_MSC_VER) && _MSC_VER < 1600 -# include "stdint-msvc2008.h" -#else -# include -#endif - -#include "tree.h" -#include "uv-threadpool.h" - -#define MAX_PIPENAME_LEN 256 - -#ifndef S_IFLNK -# define S_IFLNK 0xA000 -#endif - -/* Additional signals supported by uv_signal and or uv_kill. The CRT defines - * the following signals already: - * - * #define SIGINT 2 - * #define SIGILL 4 - * #define SIGABRT_COMPAT 6 - * #define SIGFPE 8 - * #define SIGSEGV 11 - * #define SIGTERM 15 - * #define SIGBREAK 21 - * #define SIGABRT 22 - * - * The additional signals have values that are common on other Unix - * variants (Linux and Darwin) - */ -#define SIGHUP 1 -#define SIGKILL 9 -#define SIGWINCH 28 - -/* The CRT defines SIGABRT_COMPAT as 6, which equals SIGABRT on many */ -/* unix-like platforms. However MinGW doesn't define it, so we do. */ -#ifndef SIGABRT_COMPAT -# define SIGABRT_COMPAT 6 -#endif - -/* - * Guids and typedefs for winsock extension functions - * Mingw32 doesn't have these :-( - */ -#ifndef WSAID_ACCEPTEX -# define WSAID_ACCEPTEX \ - {0xb5367df1, 0xcbac, 0x11cf, \ - {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}} - -# define WSAID_CONNECTEX \ - {0x25a207b9, 0xddf3, 0x4660, \ - {0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e}} - -# define WSAID_GETACCEPTEXSOCKADDRS \ - {0xb5367df2, 0xcbac, 0x11cf, \ - {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}} - -# define WSAID_DISCONNECTEX \ - {0x7fda2e11, 0x8630, 0x436f, \ - {0xa0, 0x31, 0xf5, 0x36, 0xa6, 0xee, 0xc1, 0x57}} - -# define WSAID_TRANSMITFILE \ - {0xb5367df0, 0xcbac, 0x11cf, \ - {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}} - - typedef BOOL PASCAL (*LPFN_ACCEPTEX) - (SOCKET sListenSocket, - SOCKET sAcceptSocket, - PVOID lpOutputBuffer, - DWORD dwReceiveDataLength, - DWORD dwLocalAddressLength, - DWORD dwRemoteAddressLength, - LPDWORD lpdwBytesReceived, - LPOVERLAPPED lpOverlapped); - - typedef BOOL PASCAL (*LPFN_CONNECTEX) - (SOCKET s, - const struct sockaddr* name, - int namelen, - PVOID lpSendBuffer, - DWORD dwSendDataLength, - LPDWORD lpdwBytesSent, - LPOVERLAPPED lpOverlapped); - - typedef void PASCAL (*LPFN_GETACCEPTEXSOCKADDRS) - (PVOID lpOutputBuffer, - DWORD dwReceiveDataLength, - DWORD dwLocalAddressLength, - DWORD dwRemoteAddressLength, - LPSOCKADDR* LocalSockaddr, - LPINT LocalSockaddrLength, - LPSOCKADDR* RemoteSockaddr, - LPINT RemoteSockaddrLength); - - typedef BOOL PASCAL (*LPFN_DISCONNECTEX) - (SOCKET hSocket, - LPOVERLAPPED lpOverlapped, - DWORD dwFlags, - DWORD reserved); - - typedef BOOL PASCAL (*LPFN_TRANSMITFILE) - (SOCKET hSocket, - HANDLE hFile, - DWORD nNumberOfBytesToWrite, - DWORD nNumberOfBytesPerSend, - LPOVERLAPPED lpOverlapped, - LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers, - DWORD dwFlags); - - typedef PVOID RTL_SRWLOCK; - typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK; -#endif - -typedef int (WSAAPI* LPFN_WSARECV) - (SOCKET socket, - LPWSABUF buffers, - DWORD buffer_count, - LPDWORD bytes, - LPDWORD flags, - LPWSAOVERLAPPED overlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine); - -typedef int (WSAAPI* LPFN_WSARECVFROM) - (SOCKET socket, - LPWSABUF buffers, - DWORD buffer_count, - LPDWORD bytes, - LPDWORD flags, - struct sockaddr* addr, - LPINT addr_len, - LPWSAOVERLAPPED overlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine); - -#ifndef _NTDEF_ - typedef LONG NTSTATUS; - typedef NTSTATUS *PNTSTATUS; -#endif - -#ifndef RTL_CONDITION_VARIABLE_INIT - typedef PVOID CONDITION_VARIABLE, *PCONDITION_VARIABLE; -#endif - -typedef struct _AFD_POLL_HANDLE_INFO { - HANDLE Handle; - ULONG Events; - NTSTATUS Status; -} AFD_POLL_HANDLE_INFO, *PAFD_POLL_HANDLE_INFO; - -typedef struct _AFD_POLL_INFO { - LARGE_INTEGER Timeout; - ULONG NumberOfHandles; - ULONG Exclusive; - AFD_POLL_HANDLE_INFO Handles[1]; -} AFD_POLL_INFO, *PAFD_POLL_INFO; - -#define UV_MSAFD_PROVIDER_COUNT 3 - - -/** - * It should be possible to cast uv_buf_t[] to WSABUF[] - * see http://msdn.microsoft.com/en-us/library/ms741542(v=vs.85).aspx - */ -typedef struct uv_buf_t { - ULONG len; - char* base; -} uv_buf_t; - -typedef int uv_file; -typedef SOCKET uv_os_sock_t; -typedef HANDLE uv_os_fd_t; - -typedef HANDLE uv_thread_t; - -typedef HANDLE uv_sem_t; - -typedef CRITICAL_SECTION uv_mutex_t; - -/* This condition variable implementation is based on the SetEvent solution - * (section 3.2) at http://www.cs.wustl.edu/~schmidt/win32-cv-1.html - * We could not use the SignalObjectAndWait solution (section 3.4) because - * it want the 2nd argument (type uv_mutex_t) of uv_cond_wait() and - * uv_cond_timedwait() to be HANDLEs, but we use CRITICAL_SECTIONs. - */ - -typedef union { - CONDITION_VARIABLE cond_var; - struct { - unsigned int waiters_count; - CRITICAL_SECTION waiters_count_lock; - HANDLE signal_event; - HANDLE broadcast_event; - } fallback; -} uv_cond_t; - -typedef union { - /* srwlock_ has type SRWLOCK, but not all toolchains define this type in */ - /* windows.h. */ - SRWLOCK srwlock_; - struct { - uv_mutex_t read_mutex_; - uv_mutex_t write_mutex_; - unsigned int num_readers_; - } fallback_; -} uv_rwlock_t; - -typedef struct { - unsigned int n; - unsigned int count; - uv_mutex_t mutex; - uv_sem_t turnstile1; - uv_sem_t turnstile2; -} uv_barrier_t; - -typedef struct { - DWORD tls_index; -} uv_key_t; - -#define UV_ONCE_INIT { 0, NULL } - -typedef struct uv_once_s { - unsigned char ran; - HANDLE event; -} uv_once_t; - -/* Platform-specific definitions for uv_spawn support. */ -typedef unsigned char uv_uid_t; -typedef unsigned char uv_gid_t; - -typedef struct uv__dirent_s { - int d_type; - char d_name[1]; -} uv__dirent_t; - -#define UV__DT_DIR UV_DIRENT_DIR -#define UV__DT_FILE UV_DIRENT_FILE -#define UV__DT_LINK UV_DIRENT_LINK -#define UV__DT_FIFO UV_DIRENT_FIFO -#define UV__DT_SOCKET UV_DIRENT_SOCKET -#define UV__DT_CHAR UV_DIRENT_CHAR -#define UV__DT_BLOCK UV_DIRENT_BLOCK - -/* Platform-specific definitions for uv_dlopen support. */ -#define UV_DYNAMIC FAR WINAPI -typedef struct { - HMODULE handle; - char* errmsg; -} uv_lib_t; - -RB_HEAD(uv_timer_tree_s, uv_timer_s); - -#define UV_LOOP_PRIVATE_FIELDS \ - /* The loop's I/O completion port */ \ - HANDLE iocp; \ - /* The current time according to the event loop. in msecs. */ \ - uint64_t time; \ - /* Tail of a single-linked circular queue of pending reqs. If the queue */ \ - /* is empty, tail_ is NULL. If there is only one item, */ \ - /* tail_->next_req == tail_ */ \ - uv_req_t* pending_reqs_tail; \ - /* Head of a single-linked list of closed handles */ \ - uv_handle_t* endgame_handles; \ - /* The head of the timers tree */ \ - struct uv_timer_tree_s timers; \ - /* Lists of active loop (prepare / check / idle) watchers */ \ - uv_prepare_t* prepare_handles; \ - uv_check_t* check_handles; \ - uv_idle_t* idle_handles; \ - /* This pointer will refer to the prepare/check/idle handle whose */ \ - /* callback is scheduled to be called next. This is needed to allow */ \ - /* safe removal from one of the lists above while that list being */ \ - /* iterated over. */ \ - uv_prepare_t* next_prepare_handle; \ - uv_check_t* next_check_handle; \ - uv_idle_t* next_idle_handle; \ - /* This handle holds the peer sockets for the fast variant of uv_poll_t */ \ - SOCKET poll_peer_sockets[UV_MSAFD_PROVIDER_COUNT]; \ - /* Counter to keep track of active tcp streams */ \ - unsigned int active_tcp_streams; \ - /* Counter to keep track of active udp streams */ \ - unsigned int active_udp_streams; \ - /* Counter to started timer */ \ - uint64_t timer_counter; \ - /* Threadpool */ \ - void* wq[2]; \ - uv_mutex_t wq_mutex; \ - uv_async_t wq_async; - -#define UV_REQ_TYPE_PRIVATE \ - /* TODO: remove the req suffix */ \ - UV_ACCEPT, \ - UV_FS_EVENT_REQ, \ - UV_POLL_REQ, \ - UV_PROCESS_EXIT, \ - UV_READ, \ - UV_UDP_RECV, \ - UV_WAKEUP, \ - UV_SIGNAL_REQ, - -#define UV_REQ_PRIVATE_FIELDS \ - union { \ - /* Used by I/O operations */ \ - struct { \ - OVERLAPPED overlapped; \ - size_t queued_bytes; \ - }; \ - }; \ - struct uv_req_s* next_req; - -#define UV_WRITE_PRIVATE_FIELDS \ - int ipc_header; \ - uv_buf_t write_buffer; \ - HANDLE event_handle; \ - HANDLE wait_handle; - -#define UV_CONNECT_PRIVATE_FIELDS \ - /* empty */ - -#define UV_SHUTDOWN_PRIVATE_FIELDS \ - /* empty */ - -#define UV_UDP_SEND_PRIVATE_FIELDS \ - /* empty */ - -#define UV_PRIVATE_REQ_TYPES \ - typedef struct uv_pipe_accept_s { \ - UV_REQ_FIELDS \ - HANDLE pipeHandle; \ - struct uv_pipe_accept_s* next_pending; \ - } uv_pipe_accept_t; \ - \ - typedef struct uv_tcp_accept_s { \ - UV_REQ_FIELDS \ - SOCKET accept_socket; \ - char accept_buffer[sizeof(struct sockaddr_storage) * 2 + 32]; \ - HANDLE event_handle; \ - HANDLE wait_handle; \ - struct uv_tcp_accept_s* next_pending; \ - } uv_tcp_accept_t; \ - \ - typedef struct uv_read_s { \ - UV_REQ_FIELDS \ - HANDLE event_handle; \ - HANDLE wait_handle; \ - } uv_read_t; - -#define uv_stream_connection_fields \ - unsigned int write_reqs_pending; \ - uv_shutdown_t* shutdown_req; - -#define uv_stream_server_fields \ - uv_connection_cb connection_cb; - -#define UV_STREAM_PRIVATE_FIELDS \ - unsigned int reqs_pending; \ - int activecnt; \ - uv_read_t read_req; \ - union { \ - struct { uv_stream_connection_fields }; \ - struct { uv_stream_server_fields }; \ - }; - -#define uv_tcp_server_fields \ - uv_tcp_accept_t* accept_reqs; \ - unsigned int processed_accepts; \ - uv_tcp_accept_t* pending_accepts; \ - LPFN_ACCEPTEX func_acceptex; - -#define uv_tcp_connection_fields \ - uv_buf_t read_buffer; \ - LPFN_CONNECTEX func_connectex; - -#define UV_TCP_PRIVATE_FIELDS \ - SOCKET socket; \ - int delayed_error; \ - union { \ - struct { uv_tcp_server_fields }; \ - struct { uv_tcp_connection_fields }; \ - }; - -#define UV_UDP_PRIVATE_FIELDS \ - SOCKET socket; \ - unsigned int reqs_pending; \ - int activecnt; \ - uv_req_t recv_req; \ - uv_buf_t recv_buffer; \ - struct sockaddr_storage recv_from; \ - int recv_from_len; \ - uv_udp_recv_cb recv_cb; \ - uv_alloc_cb alloc_cb; \ - LPFN_WSARECV func_wsarecv; \ - LPFN_WSARECVFROM func_wsarecvfrom; - -#define uv_pipe_server_fields \ - int pending_instances; \ - uv_pipe_accept_t* accept_reqs; \ - uv_pipe_accept_t* pending_accepts; - -#define uv_pipe_connection_fields \ - uv_timer_t* eof_timer; \ - uv_write_t ipc_header_write_req; \ - int ipc_pid; \ - uint64_t remaining_ipc_rawdata_bytes; \ - struct { \ - void* queue[2]; \ - int queue_len; \ - } pending_ipc_info; \ - uv_write_t* non_overlapped_writes_tail; \ - uv_mutex_t readfile_mutex; \ - volatile HANDLE readfile_thread; - -#define UV_PIPE_PRIVATE_FIELDS \ - HANDLE handle; \ - WCHAR* name; \ - union { \ - struct { uv_pipe_server_fields }; \ - struct { uv_pipe_connection_fields }; \ - }; - -/* TODO: put the parser states in an union - TTY handles are always */ -/* half-duplex so read-state can safely overlap write-state. */ -#define UV_TTY_PRIVATE_FIELDS \ - HANDLE handle; \ - union { \ - struct { \ - /* Used for readable TTY handles */ \ - HANDLE read_line_handle; \ - uv_buf_t read_line_buffer; \ - HANDLE read_raw_wait; \ - /* Fields used for translating win keystrokes into vt100 characters */ \ - char last_key[8]; \ - unsigned char last_key_offset; \ - unsigned char last_key_len; \ - WCHAR last_utf16_high_surrogate; \ - INPUT_RECORD last_input_record; \ - }; \ - struct { \ - /* Used for writable TTY handles */ \ - /* utf8-to-utf16 conversion state */ \ - unsigned int utf8_codepoint; \ - unsigned char utf8_bytes_left; \ - /* eol conversion state */ \ - unsigned char previous_eol; \ - /* ansi parser state */ \ - unsigned char ansi_parser_state; \ - unsigned char ansi_csi_argc; \ - unsigned short ansi_csi_argv[4]; \ - COORD saved_position; \ - WORD saved_attributes; \ - }; \ - }; - -#define UV_POLL_PRIVATE_FIELDS \ - SOCKET socket; \ - /* Used in fast mode */ \ - SOCKET peer_socket; \ - AFD_POLL_INFO afd_poll_info_1; \ - AFD_POLL_INFO afd_poll_info_2; \ - /* Used in fast and slow mode. */ \ - uv_req_t poll_req_1; \ - uv_req_t poll_req_2; \ - unsigned char submitted_events_1; \ - unsigned char submitted_events_2; \ - unsigned char mask_events_1; \ - unsigned char mask_events_2; \ - unsigned char events; - -#define UV_TIMER_PRIVATE_FIELDS \ - RB_ENTRY(uv_timer_s) tree_entry; \ - uint64_t due; \ - uint64_t repeat; \ - uint64_t start_id; \ - uv_timer_cb timer_cb; - -#define UV_ASYNC_PRIVATE_FIELDS \ - struct uv_req_s async_req; \ - uv_async_cb async_cb; \ - /* char to avoid alignment issues */ \ - char volatile async_sent; - -#define UV_PREPARE_PRIVATE_FIELDS \ - uv_prepare_t* prepare_prev; \ - uv_prepare_t* prepare_next; \ - uv_prepare_cb prepare_cb; - -#define UV_CHECK_PRIVATE_FIELDS \ - uv_check_t* check_prev; \ - uv_check_t* check_next; \ - uv_check_cb check_cb; - -#define UV_IDLE_PRIVATE_FIELDS \ - uv_idle_t* idle_prev; \ - uv_idle_t* idle_next; \ - uv_idle_cb idle_cb; - -#define UV_HANDLE_PRIVATE_FIELDS \ - uv_handle_t* endgame_next; \ - unsigned int flags; - -#define UV_GETADDRINFO_PRIVATE_FIELDS \ - struct uv__work work_req; \ - uv_getaddrinfo_cb getaddrinfo_cb; \ - void* alloc; \ - WCHAR* node; \ - WCHAR* service; \ - /* The addrinfoW field is used to store a pointer to the hints, and */ \ - /* later on to store the result of GetAddrInfoW. The final result will */ \ - /* be converted to struct addrinfo* and stored in the addrinfo field. */ \ - struct addrinfoW* addrinfow; \ - struct addrinfo* addrinfo; \ - int retcode; - -#define UV_GETNAMEINFO_PRIVATE_FIELDS \ - struct uv__work work_req; \ - uv_getnameinfo_cb getnameinfo_cb; \ - struct sockaddr_storage storage; \ - int flags; \ - char host[NI_MAXHOST]; \ - char service[NI_MAXSERV]; \ - int retcode; - -#define UV_PROCESS_PRIVATE_FIELDS \ - struct uv_process_exit_s { \ - UV_REQ_FIELDS \ - } exit_req; \ - BYTE* child_stdio_buffer; \ - int exit_signal; \ - HANDLE wait_handle; \ - HANDLE process_handle; \ - volatile char exit_cb_pending; - -#define UV_FS_PRIVATE_FIELDS \ - struct uv__work work_req; \ - int flags; \ - DWORD sys_errno_; \ - union { \ - /* TODO: remove me in 0.9. */ \ - WCHAR* pathw; \ - int fd; \ - }; \ - union { \ - struct { \ - int mode; \ - WCHAR* new_pathw; \ - int file_flags; \ - int fd_out; \ - unsigned int nbufs; \ - uv_buf_t* bufs; \ - int64_t offset; \ - uv_buf_t bufsml[4]; \ - }; \ - struct { \ - double atime; \ - double mtime; \ - }; \ - }; - -#define UV_WORK_PRIVATE_FIELDS \ - struct uv__work work_req; - -#define UV_FS_EVENT_PRIVATE_FIELDS \ - struct uv_fs_event_req_s { \ - UV_REQ_FIELDS \ - } req; \ - HANDLE dir_handle; \ - int req_pending; \ - uv_fs_event_cb cb; \ - WCHAR* filew; \ - WCHAR* short_filew; \ - WCHAR* dirw; \ - char* buffer; - -#define UV_SIGNAL_PRIVATE_FIELDS \ - RB_ENTRY(uv_signal_s) tree_entry; \ - struct uv_req_s signal_req; \ - unsigned long pending_signum; - -int uv_utf16_to_utf8(const WCHAR* utf16Buffer, size_t utf16Size, - char* utf8Buffer, size_t utf8Size); -int uv_utf8_to_utf16(const char* utf8Buffer, WCHAR* utf16Buffer, - size_t utf16Size); - -#ifndef F_OK -#define F_OK 0 -#endif -#ifndef R_OK -#define R_OK 4 -#endif -#ifndef W_OK -#define W_OK 2 -#endif -#ifndef X_OK -#define X_OK 1 -#endif diff --git a/libuv/include/uv.h b/libuv/include/uv.h deleted file mode 100644 index 191eeca..0000000 --- a/libuv/include/uv.h +++ /dev/null @@ -1,1453 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* See https://github.com/libuv/libuv#documentation for documentation. */ - -#ifndef UV_H -#define UV_H -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _WIN32 - /* Windows - set up dll import/export decorators. */ -# if defined(BUILDING_UV_SHARED) - /* Building shared library. */ -# define UV_EXTERN __declspec(dllexport) -# elif defined(USING_UV_SHARED) - /* Using shared library. */ -# define UV_EXTERN __declspec(dllimport) -# else - /* Building static library. */ -# define UV_EXTERN /* nothing */ -# endif -#elif __GNUC__ >= 4 -# define UV_EXTERN __attribute__((visibility("default"))) -#else -# define UV_EXTERN /* nothing */ -#endif - -#include "uv-errno.h" -#include "uv-version.h" -#include - -#if defined(_MSC_VER) && _MSC_VER < 1600 -# include "stdint-msvc2008.h" -#else -# include -#endif - -#if defined(_WIN32) -# include "uv-win.h" -#else -# include "uv-unix.h" -#endif - -/* Expand this list if necessary. */ -#define UV_ERRNO_MAP(XX) \ - XX(E2BIG, "argument list too long") \ - XX(EACCES, "permission denied") \ - XX(EADDRINUSE, "address already in use") \ - XX(EADDRNOTAVAIL, "address not available") \ - XX(EAFNOSUPPORT, "address family not supported") \ - XX(EAGAIN, "resource temporarily unavailable") \ - XX(EAI_ADDRFAMILY, "address family not supported") \ - XX(EAI_AGAIN, "temporary failure") \ - XX(EAI_BADFLAGS, "bad ai_flags value") \ - XX(EAI_BADHINTS, "invalid value for hints") \ - XX(EAI_CANCELED, "request canceled") \ - XX(EAI_FAIL, "permanent failure") \ - XX(EAI_FAMILY, "ai_family not supported") \ - XX(EAI_MEMORY, "out of memory") \ - XX(EAI_NODATA, "no address") \ - XX(EAI_NONAME, "unknown node or service") \ - XX(EAI_OVERFLOW, "argument buffer overflow") \ - XX(EAI_PROTOCOL, "resolved protocol is unknown") \ - XX(EAI_SERVICE, "service not available for socket type") \ - XX(EAI_SOCKTYPE, "socket type not supported") \ - XX(EALREADY, "connection already in progress") \ - XX(EBADF, "bad file descriptor") \ - XX(EBUSY, "resource busy or locked") \ - XX(ECANCELED, "operation canceled") \ - XX(ECHARSET, "invalid Unicode character") \ - XX(ECONNABORTED, "software caused connection abort") \ - XX(ECONNREFUSED, "connection refused") \ - XX(ECONNRESET, "connection reset by peer") \ - XX(EDESTADDRREQ, "destination address required") \ - XX(EEXIST, "file already exists") \ - XX(EFAULT, "bad address in system call argument") \ - XX(EFBIG, "file too large") \ - XX(EHOSTUNREACH, "host is unreachable") \ - XX(EINTR, "interrupted system call") \ - XX(EINVAL, "invalid argument") \ - XX(EIO, "i/o error") \ - XX(EISCONN, "socket is already connected") \ - XX(EISDIR, "illegal operation on a directory") \ - XX(ELOOP, "too many symbolic links encountered") \ - XX(EMFILE, "too many open files") \ - XX(EMSGSIZE, "message too long") \ - XX(ENAMETOOLONG, "name too long") \ - XX(ENETDOWN, "network is down") \ - XX(ENETUNREACH, "network is unreachable") \ - XX(ENFILE, "file table overflow") \ - XX(ENOBUFS, "no buffer space available") \ - XX(ENODEV, "no such device") \ - XX(ENOENT, "no such file or directory") \ - XX(ENOMEM, "not enough memory") \ - XX(ENONET, "machine is not on the network") \ - XX(ENOPROTOOPT, "protocol not available") \ - XX(ENOSPC, "no space left on device") \ - XX(ENOSYS, "function not implemented") \ - XX(ENOTCONN, "socket is not connected") \ - XX(ENOTDIR, "not a directory") \ - XX(ENOTEMPTY, "directory not empty") \ - XX(ENOTSOCK, "socket operation on non-socket") \ - XX(ENOTSUP, "operation not supported on socket") \ - XX(EPERM, "operation not permitted") \ - XX(EPIPE, "broken pipe") \ - XX(EPROTO, "protocol error") \ - XX(EPROTONOSUPPORT, "protocol not supported") \ - XX(EPROTOTYPE, "protocol wrong type for socket") \ - XX(ERANGE, "result too large") \ - XX(EROFS, "read-only file system") \ - XX(ESHUTDOWN, "cannot send after transport endpoint shutdown") \ - XX(ESPIPE, "invalid seek") \ - XX(ESRCH, "no such process") \ - XX(ETIMEDOUT, "connection timed out") \ - XX(ETXTBSY, "text file is busy") \ - XX(EXDEV, "cross-device link not permitted") \ - XX(UNKNOWN, "unknown error") \ - XX(EOF, "end of file") \ - XX(ENXIO, "no such device or address") \ - XX(EMLINK, "too many links") \ - -#define UV_HANDLE_TYPE_MAP(XX) \ - XX(ASYNC, async) \ - XX(CHECK, check) \ - XX(FS_EVENT, fs_event) \ - XX(FS_POLL, fs_poll) \ - XX(HANDLE, handle) \ - XX(IDLE, idle) \ - XX(NAMED_PIPE, pipe) \ - XX(POLL, poll) \ - XX(PREPARE, prepare) \ - XX(PROCESS, process) \ - XX(STREAM, stream) \ - XX(TCP, tcp) \ - XX(TIMER, timer) \ - XX(TTY, tty) \ - XX(UDP, udp) \ - XX(SIGNAL, signal) \ - -#define UV_REQ_TYPE_MAP(XX) \ - XX(REQ, req) \ - XX(CONNECT, connect) \ - XX(WRITE, write) \ - XX(SHUTDOWN, shutdown) \ - XX(UDP_SEND, udp_send) \ - XX(FS, fs) \ - XX(WORK, work) \ - XX(GETADDRINFO, getaddrinfo) \ - XX(GETNAMEINFO, getnameinfo) \ - -typedef enum { -#define XX(code, _) UV_ ## code = UV__ ## code, - UV_ERRNO_MAP(XX) -#undef XX - UV_ERRNO_MAX = UV__EOF - 1 -} uv_errno_t; - -typedef enum { - UV_UNKNOWN_HANDLE = 0, -#define XX(uc, lc) UV_##uc, - UV_HANDLE_TYPE_MAP(XX) -#undef XX - UV_FILE, - UV_HANDLE_TYPE_MAX -} uv_handle_type; - -typedef enum { - UV_UNKNOWN_REQ = 0, -#define XX(uc, lc) UV_##uc, - UV_REQ_TYPE_MAP(XX) -#undef XX - UV_REQ_TYPE_PRIVATE - UV_REQ_TYPE_MAX -} uv_req_type; - - -/* Handle types. */ -typedef struct uv_loop_s uv_loop_t; -typedef struct uv_handle_s uv_handle_t; -typedef struct uv_stream_s uv_stream_t; -typedef struct uv_tcp_s uv_tcp_t; -typedef struct uv_udp_s uv_udp_t; -typedef struct uv_pipe_s uv_pipe_t; -typedef struct uv_tty_s uv_tty_t; -typedef struct uv_poll_s uv_poll_t; -typedef struct uv_timer_s uv_timer_t; -typedef struct uv_prepare_s uv_prepare_t; -typedef struct uv_check_s uv_check_t; -typedef struct uv_idle_s uv_idle_t; -typedef struct uv_async_s uv_async_t; -typedef struct uv_process_s uv_process_t; -typedef struct uv_fs_event_s uv_fs_event_t; -typedef struct uv_fs_poll_s uv_fs_poll_t; -typedef struct uv_signal_s uv_signal_t; - -/* Request types. */ -typedef struct uv_req_s uv_req_t; -typedef struct uv_getaddrinfo_s uv_getaddrinfo_t; -typedef struct uv_getnameinfo_s uv_getnameinfo_t; -typedef struct uv_shutdown_s uv_shutdown_t; -typedef struct uv_write_s uv_write_t; -typedef struct uv_connect_s uv_connect_t; -typedef struct uv_udp_send_s uv_udp_send_t; -typedef struct uv_fs_s uv_fs_t; -typedef struct uv_work_s uv_work_t; - -/* None of the above. */ -typedef struct uv_cpu_info_s uv_cpu_info_t; -typedef struct uv_interface_address_s uv_interface_address_t; -typedef struct uv_dirent_s uv_dirent_t; - -typedef enum { - UV_LOOP_BLOCK_SIGNAL -} uv_loop_option; - -typedef enum { - UV_RUN_DEFAULT = 0, - UV_RUN_ONCE, - UV_RUN_NOWAIT -} uv_run_mode; - - -UV_EXTERN unsigned int uv_version(void); -UV_EXTERN const char* uv_version_string(void); - -UV_EXTERN uv_loop_t* uv_default_loop(void); -UV_EXTERN int uv_loop_init(uv_loop_t* loop); -UV_EXTERN int uv_loop_close(uv_loop_t* loop); -/* - * NOTE: - * This function is DEPRECATED (to be removed after 0.12), users should - * allocate the loop manually and use uv_loop_init instead. - */ -UV_EXTERN uv_loop_t* uv_loop_new(void); -/* - * NOTE: - * This function is DEPRECATED (to be removed after 0.12). Users should use - * uv_loop_close and free the memory manually instead. - */ -UV_EXTERN void uv_loop_delete(uv_loop_t*); -UV_EXTERN size_t uv_loop_size(void); -UV_EXTERN int uv_loop_alive(const uv_loop_t* loop); -UV_EXTERN int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...); - -UV_EXTERN int uv_run(uv_loop_t*, uv_run_mode mode); -UV_EXTERN void uv_stop(uv_loop_t*); - -UV_EXTERN void uv_ref(uv_handle_t*); -UV_EXTERN void uv_unref(uv_handle_t*); -UV_EXTERN int uv_has_ref(const uv_handle_t*); - -UV_EXTERN void uv_update_time(uv_loop_t*); -UV_EXTERN uint64_t uv_now(const uv_loop_t*); - -UV_EXTERN int uv_backend_fd(const uv_loop_t*); -UV_EXTERN int uv_backend_timeout(const uv_loop_t*); - -typedef void (*uv_alloc_cb)(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf); -typedef void (*uv_read_cb)(uv_stream_t* stream, - ssize_t nread, - const uv_buf_t* buf); -typedef void (*uv_write_cb)(uv_write_t* req, int status); -typedef void (*uv_connect_cb)(uv_connect_t* req, int status); -typedef void (*uv_shutdown_cb)(uv_shutdown_t* req, int status); -typedef void (*uv_connection_cb)(uv_stream_t* server, int status); -typedef void (*uv_close_cb)(uv_handle_t* handle); -typedef void (*uv_poll_cb)(uv_poll_t* handle, int status, int events); -typedef void (*uv_timer_cb)(uv_timer_t* handle); -typedef void (*uv_async_cb)(uv_async_t* handle); -typedef void (*uv_prepare_cb)(uv_prepare_t* handle); -typedef void (*uv_check_cb)(uv_check_t* handle); -typedef void (*uv_idle_cb)(uv_idle_t* handle); -typedef void (*uv_exit_cb)(uv_process_t*, int64_t exit_status, int term_signal); -typedef void (*uv_walk_cb)(uv_handle_t* handle, void* arg); -typedef void (*uv_fs_cb)(uv_fs_t* req); -typedef void (*uv_work_cb)(uv_work_t* req); -typedef void (*uv_after_work_cb)(uv_work_t* req, int status); -typedef void (*uv_getaddrinfo_cb)(uv_getaddrinfo_t* req, - int status, - struct addrinfo* res); -typedef void (*uv_getnameinfo_cb)(uv_getnameinfo_t* req, - int status, - const char* hostname, - const char* service); - -typedef struct { - long tv_sec; - long tv_nsec; -} uv_timespec_t; - - -typedef struct { - uint64_t st_dev; - uint64_t st_mode; - uint64_t st_nlink; - uint64_t st_uid; - uint64_t st_gid; - uint64_t st_rdev; - uint64_t st_ino; - uint64_t st_size; - uint64_t st_blksize; - uint64_t st_blocks; - uint64_t st_flags; - uint64_t st_gen; - uv_timespec_t st_atim; - uv_timespec_t st_mtim; - uv_timespec_t st_ctim; - uv_timespec_t st_birthtim; -} uv_stat_t; - - -typedef void (*uv_fs_event_cb)(uv_fs_event_t* handle, - const char* filename, - int events, - int status); - -typedef void (*uv_fs_poll_cb)(uv_fs_poll_t* handle, - int status, - const uv_stat_t* prev, - const uv_stat_t* curr); - -typedef void (*uv_signal_cb)(uv_signal_t* handle, int signum); - - -typedef enum { - UV_LEAVE_GROUP = 0, - UV_JOIN_GROUP -} uv_membership; - - -UV_EXTERN const char* uv_strerror(int err); -UV_EXTERN const char* uv_err_name(int err); - - -#define UV_REQ_FIELDS \ - /* public */ \ - void* data; \ - /* read-only */ \ - uv_req_type type; \ - /* private */ \ - void* active_queue[2]; \ - void* reserved[4]; \ - UV_REQ_PRIVATE_FIELDS \ - -/* Abstract base class of all requests. */ -struct uv_req_s { - UV_REQ_FIELDS -}; - - -/* Platform-specific request types. */ -UV_PRIVATE_REQ_TYPES - - -UV_EXTERN int uv_shutdown(uv_shutdown_t* req, - uv_stream_t* handle, - uv_shutdown_cb cb); - -struct uv_shutdown_s { - UV_REQ_FIELDS - uv_stream_t* handle; - uv_shutdown_cb cb; - UV_SHUTDOWN_PRIVATE_FIELDS -}; - - -#define UV_HANDLE_FIELDS \ - /* public */ \ - void* data; \ - /* read-only */ \ - uv_loop_t* loop; \ - uv_handle_type type; \ - /* private */ \ - uv_close_cb close_cb; \ - void* handle_queue[2]; \ - void* reserved[4]; \ - UV_HANDLE_PRIVATE_FIELDS \ - -/* The abstract base class of all handles. */ -struct uv_handle_s { - UV_HANDLE_FIELDS -}; - -UV_EXTERN size_t uv_handle_size(uv_handle_type type); -UV_EXTERN size_t uv_req_size(uv_req_type type); - -UV_EXTERN int uv_is_active(const uv_handle_t* handle); - -UV_EXTERN void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg); - -UV_EXTERN void uv_close(uv_handle_t* handle, uv_close_cb close_cb); - -UV_EXTERN int uv_send_buffer_size(uv_handle_t* handle, int* value); -UV_EXTERN int uv_recv_buffer_size(uv_handle_t* handle, int* value); - -UV_EXTERN int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd); - -UV_EXTERN uv_buf_t uv_buf_init(char* base, unsigned int len); - - -#define UV_STREAM_FIELDS \ - /* number of bytes queued for writing */ \ - size_t write_queue_size; \ - uv_alloc_cb alloc_cb; \ - uv_read_cb read_cb; \ - /* private */ \ - UV_STREAM_PRIVATE_FIELDS - -/* - * uv_stream_t is a subclass of uv_handle_t. - * - * uv_stream is an abstract class. - * - * uv_stream_t is the parent class of uv_tcp_t, uv_pipe_t and uv_tty_t. - */ -struct uv_stream_s { - UV_HANDLE_FIELDS - UV_STREAM_FIELDS -}; - -UV_EXTERN int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb); -UV_EXTERN int uv_accept(uv_stream_t* server, uv_stream_t* client); - -UV_EXTERN int uv_read_start(uv_stream_t*, - uv_alloc_cb alloc_cb, - uv_read_cb read_cb); -UV_EXTERN int uv_read_stop(uv_stream_t*); - -UV_EXTERN int uv_write(uv_write_t* req, - uv_stream_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - uv_write_cb cb); -UV_EXTERN int uv_write2(uv_write_t* req, - uv_stream_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - uv_stream_t* send_handle, - uv_write_cb cb); -UV_EXTERN int uv_try_write(uv_stream_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs); - -/* uv_write_t is a subclass of uv_req_t. */ -struct uv_write_s { - UV_REQ_FIELDS - uv_write_cb cb; - uv_stream_t* send_handle; - uv_stream_t* handle; - UV_WRITE_PRIVATE_FIELDS -}; - - -UV_EXTERN int uv_is_readable(const uv_stream_t* handle); -UV_EXTERN int uv_is_writable(const uv_stream_t* handle); - -UV_EXTERN int uv_stream_set_blocking(uv_stream_t* handle, int blocking); - -UV_EXTERN int uv_is_closing(const uv_handle_t* handle); - - -/* - * uv_tcp_t is a subclass of uv_stream_t. - * - * Represents a TCP stream or TCP server. - */ -struct uv_tcp_s { - UV_HANDLE_FIELDS - UV_STREAM_FIELDS - UV_TCP_PRIVATE_FIELDS -}; - -UV_EXTERN int uv_tcp_init(uv_loop_t*, uv_tcp_t* handle); -UV_EXTERN int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock); -UV_EXTERN int uv_tcp_nodelay(uv_tcp_t* handle, int enable); -UV_EXTERN int uv_tcp_keepalive(uv_tcp_t* handle, - int enable, - unsigned int delay); -UV_EXTERN int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable); - -enum uv_tcp_flags { - /* Used with uv_tcp_bind, when an IPv6 address is used. */ - UV_TCP_IPV6ONLY = 1 -}; - -UV_EXTERN int uv_tcp_bind(uv_tcp_t* handle, - const struct sockaddr* addr, - unsigned int flags); -UV_EXTERN int uv_tcp_getsockname(const uv_tcp_t* handle, - struct sockaddr* name, - int* namelen); -UV_EXTERN int uv_tcp_getpeername(const uv_tcp_t* handle, - struct sockaddr* name, - int* namelen); -UV_EXTERN int uv_tcp_connect(uv_connect_t* req, - uv_tcp_t* handle, - const struct sockaddr* addr, - uv_connect_cb cb); - -/* uv_connect_t is a subclass of uv_req_t. */ -struct uv_connect_s { - UV_REQ_FIELDS - uv_connect_cb cb; - uv_stream_t* handle; - UV_CONNECT_PRIVATE_FIELDS -}; - - -/* - * UDP support. - */ - -enum uv_udp_flags { - /* Disables dual stack mode. */ - UV_UDP_IPV6ONLY = 1, - /* - * Indicates message was truncated because read buffer was too small. The - * remainder was discarded by the OS. Used in uv_udp_recv_cb. - */ - UV_UDP_PARTIAL = 2, - /* - * Indicates if SO_REUSEADDR will be set when binding the handle. - * This sets the SO_REUSEPORT socket flag on the BSDs and OS X. On other - * Unix platforms, it sets the SO_REUSEADDR flag. What that means is that - * multiple threads or processes can bind to the same address without error - * (provided they all set the flag) but only the last one to bind will receive - * any traffic, in effect "stealing" the port from the previous listener. - */ - UV_UDP_REUSEADDR = 4 -}; - -typedef void (*uv_udp_send_cb)(uv_udp_send_t* req, int status); -typedef void (*uv_udp_recv_cb)(uv_udp_t* handle, - ssize_t nread, - const uv_buf_t* buf, - const struct sockaddr* addr, - unsigned flags); - -/* uv_udp_t is a subclass of uv_handle_t. */ -struct uv_udp_s { - UV_HANDLE_FIELDS - /* read-only */ - /* - * Number of bytes queued for sending. This field strictly shows how much - * information is currently queued. - */ - size_t send_queue_size; - /* - * Number of send requests currently in the queue awaiting to be processed. - */ - size_t send_queue_count; - UV_UDP_PRIVATE_FIELDS -}; - -/* uv_udp_send_t is a subclass of uv_req_t. */ -struct uv_udp_send_s { - UV_REQ_FIELDS - uv_udp_t* handle; - uv_udp_send_cb cb; - UV_UDP_SEND_PRIVATE_FIELDS -}; - -UV_EXTERN int uv_udp_init(uv_loop_t*, uv_udp_t* handle); -UV_EXTERN int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock); -UV_EXTERN int uv_udp_bind(uv_udp_t* handle, - const struct sockaddr* addr, - unsigned int flags); - -UV_EXTERN int uv_udp_getsockname(const uv_udp_t* handle, - struct sockaddr* name, - int* namelen); -UV_EXTERN int uv_udp_set_membership(uv_udp_t* handle, - const char* multicast_addr, - const char* interface_addr, - uv_membership membership); -UV_EXTERN int uv_udp_set_multicast_loop(uv_udp_t* handle, int on); -UV_EXTERN int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl); -UV_EXTERN int uv_udp_set_multicast_interface(uv_udp_t* handle, - const char* interface_addr); -UV_EXTERN int uv_udp_set_broadcast(uv_udp_t* handle, int on); -UV_EXTERN int uv_udp_set_ttl(uv_udp_t* handle, int ttl); -UV_EXTERN int uv_udp_send(uv_udp_send_t* req, - uv_udp_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - const struct sockaddr* addr, - uv_udp_send_cb send_cb); -UV_EXTERN int uv_udp_try_send(uv_udp_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - const struct sockaddr* addr); -UV_EXTERN int uv_udp_recv_start(uv_udp_t* handle, - uv_alloc_cb alloc_cb, - uv_udp_recv_cb recv_cb); -UV_EXTERN int uv_udp_recv_stop(uv_udp_t* handle); - - -/* - * uv_tty_t is a subclass of uv_stream_t. - * - * Representing a stream for the console. - */ -struct uv_tty_s { - UV_HANDLE_FIELDS - UV_STREAM_FIELDS - UV_TTY_PRIVATE_FIELDS -}; - -typedef enum { - /* Initial/normal terminal mode */ - UV_TTY_MODE_NORMAL, - /* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled) */ - UV_TTY_MODE_RAW, - /* Binary-safe I/O mode for IPC (Unix-only) */ - UV_TTY_MODE_IO -} uv_tty_mode_t; - -UV_EXTERN int uv_tty_init(uv_loop_t*, uv_tty_t*, uv_file fd, int readable); -UV_EXTERN int uv_tty_set_mode(uv_tty_t*, uv_tty_mode_t mode); -UV_EXTERN int uv_tty_reset_mode(void); -UV_EXTERN int uv_tty_get_winsize(uv_tty_t*, int* width, int* height); - -#ifdef __cplusplus -} /* extern "C" */ - -inline int uv_tty_set_mode(uv_tty_t* handle, int mode) { - return uv_tty_set_mode(handle, static_cast(mode)); -} - -extern "C" { -#endif - -UV_EXTERN uv_handle_type uv_guess_handle(uv_file file); - -/* - * uv_pipe_t is a subclass of uv_stream_t. - * - * Representing a pipe stream or pipe server. On Windows this is a Named - * Pipe. On Unix this is a Unix domain socket. - */ -struct uv_pipe_s { - UV_HANDLE_FIELDS - UV_STREAM_FIELDS - int ipc; /* non-zero if this pipe is used for passing handles */ - UV_PIPE_PRIVATE_FIELDS -}; - -UV_EXTERN int uv_pipe_init(uv_loop_t*, uv_pipe_t* handle, int ipc); -UV_EXTERN int uv_pipe_open(uv_pipe_t*, uv_file file); -UV_EXTERN int uv_pipe_bind(uv_pipe_t* handle, const char* name); -UV_EXTERN void uv_pipe_connect(uv_connect_t* req, - uv_pipe_t* handle, - const char* name, - uv_connect_cb cb); -UV_EXTERN int uv_pipe_getsockname(const uv_pipe_t* handle, - char* buffer, - size_t* size); -UV_EXTERN int uv_pipe_getpeername(const uv_pipe_t* handle, - char* buffer, - size_t* size); -UV_EXTERN void uv_pipe_pending_instances(uv_pipe_t* handle, int count); -UV_EXTERN int uv_pipe_pending_count(uv_pipe_t* handle); -UV_EXTERN uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle); - - -struct uv_poll_s { - UV_HANDLE_FIELDS - uv_poll_cb poll_cb; - UV_POLL_PRIVATE_FIELDS -}; - -enum uv_poll_event { - UV_READABLE = 1, - UV_WRITABLE = 2 -}; - -UV_EXTERN int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd); -UV_EXTERN int uv_poll_init_socket(uv_loop_t* loop, - uv_poll_t* handle, - uv_os_sock_t socket); -UV_EXTERN int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb cb); -UV_EXTERN int uv_poll_stop(uv_poll_t* handle); - - -struct uv_prepare_s { - UV_HANDLE_FIELDS - UV_PREPARE_PRIVATE_FIELDS -}; - -UV_EXTERN int uv_prepare_init(uv_loop_t*, uv_prepare_t* prepare); -UV_EXTERN int uv_prepare_start(uv_prepare_t* prepare, uv_prepare_cb cb); -UV_EXTERN int uv_prepare_stop(uv_prepare_t* prepare); - - -struct uv_check_s { - UV_HANDLE_FIELDS - UV_CHECK_PRIVATE_FIELDS -}; - -UV_EXTERN int uv_check_init(uv_loop_t*, uv_check_t* check); -UV_EXTERN int uv_check_start(uv_check_t* check, uv_check_cb cb); -UV_EXTERN int uv_check_stop(uv_check_t* check); - - -struct uv_idle_s { - UV_HANDLE_FIELDS - UV_IDLE_PRIVATE_FIELDS -}; - -UV_EXTERN int uv_idle_init(uv_loop_t*, uv_idle_t* idle); -UV_EXTERN int uv_idle_start(uv_idle_t* idle, uv_idle_cb cb); -UV_EXTERN int uv_idle_stop(uv_idle_t* idle); - - -struct uv_async_s { - UV_HANDLE_FIELDS - UV_ASYNC_PRIVATE_FIELDS -}; - -UV_EXTERN int uv_async_init(uv_loop_t*, - uv_async_t* async, - uv_async_cb async_cb); -UV_EXTERN int uv_async_send(uv_async_t* async); - - -/* - * uv_timer_t is a subclass of uv_handle_t. - * - * Used to get woken up at a specified time in the future. - */ -struct uv_timer_s { - UV_HANDLE_FIELDS - UV_TIMER_PRIVATE_FIELDS -}; - -UV_EXTERN int uv_timer_init(uv_loop_t*, uv_timer_t* handle); -UV_EXTERN int uv_timer_start(uv_timer_t* handle, - uv_timer_cb cb, - uint64_t timeout, - uint64_t repeat); -UV_EXTERN int uv_timer_stop(uv_timer_t* handle); -UV_EXTERN int uv_timer_again(uv_timer_t* handle); -UV_EXTERN void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat); -UV_EXTERN uint64_t uv_timer_get_repeat(const uv_timer_t* handle); - - -/* - * uv_getaddrinfo_t is a subclass of uv_req_t. - * - * Request object for uv_getaddrinfo. - */ -struct uv_getaddrinfo_s { - UV_REQ_FIELDS - /* read-only */ - uv_loop_t* loop; - /* struct addrinfo* addrinfo is marked as private, but it really isn't. */ - UV_GETADDRINFO_PRIVATE_FIELDS -}; - - -UV_EXTERN int uv_getaddrinfo(uv_loop_t* loop, - uv_getaddrinfo_t* req, - uv_getaddrinfo_cb getaddrinfo_cb, - const char* node, - const char* service, - const struct addrinfo* hints); -UV_EXTERN void uv_freeaddrinfo(struct addrinfo* ai); - - -/* -* uv_getnameinfo_t is a subclass of uv_req_t. -* -* Request object for uv_getnameinfo. -*/ -struct uv_getnameinfo_s { - UV_REQ_FIELDS - /* read-only */ - uv_loop_t* loop; - UV_GETNAMEINFO_PRIVATE_FIELDS -}; - -UV_EXTERN int uv_getnameinfo(uv_loop_t* loop, - uv_getnameinfo_t* req, - uv_getnameinfo_cb getnameinfo_cb, - const struct sockaddr* addr, - int flags); - - -/* uv_spawn() options. */ -typedef enum { - UV_IGNORE = 0x00, - UV_CREATE_PIPE = 0x01, - UV_INHERIT_FD = 0x02, - UV_INHERIT_STREAM = 0x04, - - /* - * When UV_CREATE_PIPE is specified, UV_READABLE_PIPE and UV_WRITABLE_PIPE - * determine the direction of flow, from the child process' perspective. Both - * flags may be specified to create a duplex data stream. - */ - UV_READABLE_PIPE = 0x10, - UV_WRITABLE_PIPE = 0x20 -} uv_stdio_flags; - -typedef struct uv_stdio_container_s { - uv_stdio_flags flags; - - union { - uv_stream_t* stream; - int fd; - } data; -} uv_stdio_container_t; - -typedef struct uv_process_options_s { - uv_exit_cb exit_cb; /* Called after the process exits. */ - const char* file; /* Path to program to execute. */ - /* - * Command line arguments. args[0] should be the path to the program. On - * Windows this uses CreateProcess which concatenates the arguments into a - * string this can cause some strange errors. See the note at - * windows_verbatim_arguments. - */ - char** args; - /* - * This will be set as the environ variable in the subprocess. If this is - * NULL then the parents environ will be used. - */ - char** env; - /* - * If non-null this represents a directory the subprocess should execute - * in. Stands for current working directory. - */ - const char* cwd; - /* - * Various flags that control how uv_spawn() behaves. See the definition of - * `enum uv_process_flags` below. - */ - unsigned int flags; - /* - * The `stdio` field points to an array of uv_stdio_container_t structs that - * describe the file descriptors that will be made available to the child - * process. The convention is that stdio[0] points to stdin, fd 1 is used for - * stdout, and fd 2 is stderr. - * - * Note that on windows file descriptors greater than 2 are available to the - * child process only if the child processes uses the MSVCRT runtime. - */ - int stdio_count; - uv_stdio_container_t* stdio; - /* - * Libuv can change the child process' user/group id. This happens only when - * the appropriate bits are set in the flags fields. This is not supported on - * windows; uv_spawn() will fail and set the error to UV_ENOTSUP. - */ - uv_uid_t uid; - uv_gid_t gid; -} uv_process_options_t; - -/* - * These are the flags that can be used for the uv_process_options.flags field. - */ -enum uv_process_flags { - /* - * Set the child process' user id. The user id is supplied in the `uid` field - * of the options struct. This does not work on windows; setting this flag - * will cause uv_spawn() to fail. - */ - UV_PROCESS_SETUID = (1 << 0), - /* - * Set the child process' group id. The user id is supplied in the `gid` - * field of the options struct. This does not work on windows; setting this - * flag will cause uv_spawn() to fail. - */ - UV_PROCESS_SETGID = (1 << 1), - /* - * Do not wrap any arguments in quotes, or perform any other escaping, when - * converting the argument list into a command line string. This option is - * only meaningful on Windows systems. On Unix it is silently ignored. - */ - UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS = (1 << 2), - /* - * Spawn the child process in a detached state - this will make it a process - * group leader, and will effectively enable the child to keep running after - * the parent exits. Note that the child process will still keep the - * parent's event loop alive unless the parent process calls uv_unref() on - * the child's process handle. - */ - UV_PROCESS_DETACHED = (1 << 3), - /* - * Hide the subprocess console window that would normally be created. This - * option is only meaningful on Windows systems. On Unix it is silently - * ignored. - */ - UV_PROCESS_WINDOWS_HIDE = (1 << 4) -}; - -/* - * uv_process_t is a subclass of uv_handle_t. - */ -struct uv_process_s { - UV_HANDLE_FIELDS - uv_exit_cb exit_cb; - int pid; - UV_PROCESS_PRIVATE_FIELDS -}; - -UV_EXTERN int uv_spawn(uv_loop_t* loop, - uv_process_t* handle, - const uv_process_options_t* options); -UV_EXTERN int uv_process_kill(uv_process_t*, int signum); -UV_EXTERN int uv_kill(int pid, int signum); - - -/* - * uv_work_t is a subclass of uv_req_t. - */ -struct uv_work_s { - UV_REQ_FIELDS - uv_loop_t* loop; - uv_work_cb work_cb; - uv_after_work_cb after_work_cb; - UV_WORK_PRIVATE_FIELDS -}; - -UV_EXTERN int uv_queue_work(uv_loop_t* loop, - uv_work_t* req, - uv_work_cb work_cb, - uv_after_work_cb after_work_cb); - -UV_EXTERN int uv_cancel(uv_req_t* req); - - -struct uv_cpu_info_s { - char* model; - int speed; - struct uv_cpu_times_s { - uint64_t user; - uint64_t nice; - uint64_t sys; - uint64_t idle; - uint64_t irq; - } cpu_times; -}; - -struct uv_interface_address_s { - char* name; - char phys_addr[6]; - int is_internal; - union { - struct sockaddr_in address4; - struct sockaddr_in6 address6; - } address; - union { - struct sockaddr_in netmask4; - struct sockaddr_in6 netmask6; - } netmask; -}; - -typedef enum { - UV_DIRENT_UNKNOWN, - UV_DIRENT_FILE, - UV_DIRENT_DIR, - UV_DIRENT_LINK, - UV_DIRENT_FIFO, - UV_DIRENT_SOCKET, - UV_DIRENT_CHAR, - UV_DIRENT_BLOCK -} uv_dirent_type_t; - -struct uv_dirent_s { - const char* name; - uv_dirent_type_t type; -}; - -UV_EXTERN char** uv_setup_args(int argc, char** argv); -UV_EXTERN int uv_get_process_title(char* buffer, size_t size); -UV_EXTERN int uv_set_process_title(const char* title); -UV_EXTERN int uv_resident_set_memory(size_t* rss); -UV_EXTERN int uv_uptime(double* uptime); - -typedef struct { - long tv_sec; - long tv_usec; -} uv_timeval_t; - -typedef struct { - uv_timeval_t ru_utime; /* user CPU time used */ - uv_timeval_t ru_stime; /* system CPU time used */ - uint64_t ru_maxrss; /* maximum resident set size */ - uint64_t ru_ixrss; /* integral shared memory size */ - uint64_t ru_idrss; /* integral unshared data size */ - uint64_t ru_isrss; /* integral unshared stack size */ - uint64_t ru_minflt; /* page reclaims (soft page faults) */ - uint64_t ru_majflt; /* page faults (hard page faults) */ - uint64_t ru_nswap; /* swaps */ - uint64_t ru_inblock; /* block input operations */ - uint64_t ru_oublock; /* block output operations */ - uint64_t ru_msgsnd; /* IPC messages sent */ - uint64_t ru_msgrcv; /* IPC messages received */ - uint64_t ru_nsignals; /* signals received */ - uint64_t ru_nvcsw; /* voluntary context switches */ - uint64_t ru_nivcsw; /* involuntary context switches */ -} uv_rusage_t; - -UV_EXTERN int uv_getrusage(uv_rusage_t* rusage); - -UV_EXTERN int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count); -UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count); - -UV_EXTERN int uv_interface_addresses(uv_interface_address_t** addresses, - int* count); -UV_EXTERN void uv_free_interface_addresses(uv_interface_address_t* addresses, - int count); - - -typedef enum { - UV_FS_UNKNOWN = -1, - UV_FS_CUSTOM, - UV_FS_OPEN, - UV_FS_CLOSE, - UV_FS_READ, - UV_FS_WRITE, - UV_FS_SENDFILE, - UV_FS_STAT, - UV_FS_LSTAT, - UV_FS_FSTAT, - UV_FS_FTRUNCATE, - UV_FS_UTIME, - UV_FS_FUTIME, - UV_FS_ACCESS, - UV_FS_CHMOD, - UV_FS_FCHMOD, - UV_FS_FSYNC, - UV_FS_FDATASYNC, - UV_FS_UNLINK, - UV_FS_RMDIR, - UV_FS_MKDIR, - UV_FS_MKDTEMP, - UV_FS_RENAME, - UV_FS_SCANDIR, - UV_FS_LINK, - UV_FS_SYMLINK, - UV_FS_READLINK, - UV_FS_CHOWN, - UV_FS_FCHOWN -} uv_fs_type; - -/* uv_fs_t is a subclass of uv_req_t. */ -struct uv_fs_s { - UV_REQ_FIELDS - uv_fs_type fs_type; - uv_loop_t* loop; - uv_fs_cb cb; - ssize_t result; - void* ptr; - const char* path; - uv_stat_t statbuf; /* Stores the result of uv_fs_stat() and uv_fs_fstat(). */ - UV_FS_PRIVATE_FIELDS -}; - -UV_EXTERN void uv_fs_req_cleanup(uv_fs_t* req); -UV_EXTERN int uv_fs_close(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - uv_fs_cb cb); -UV_EXTERN int uv_fs_open(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - int flags, - int mode, - uv_fs_cb cb); -UV_EXTERN int uv_fs_read(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - const uv_buf_t bufs[], - unsigned int nbufs, - int64_t offset, - uv_fs_cb cb); -UV_EXTERN int uv_fs_unlink(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - uv_fs_cb cb); -UV_EXTERN int uv_fs_write(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - const uv_buf_t bufs[], - unsigned int nbufs, - int64_t offset, - uv_fs_cb cb); -UV_EXTERN int uv_fs_mkdir(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - int mode, - uv_fs_cb cb); -UV_EXTERN int uv_fs_mkdtemp(uv_loop_t* loop, - uv_fs_t* req, - const char* tpl, - uv_fs_cb cb); -UV_EXTERN int uv_fs_rmdir(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - uv_fs_cb cb); -UV_EXTERN int uv_fs_scandir(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - int flags, - uv_fs_cb cb); -UV_EXTERN int uv_fs_scandir_next(uv_fs_t* req, - uv_dirent_t* ent); -UV_EXTERN int uv_fs_stat(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - uv_fs_cb cb); -UV_EXTERN int uv_fs_fstat(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - uv_fs_cb cb); -UV_EXTERN int uv_fs_rename(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - const char* new_path, - uv_fs_cb cb); -UV_EXTERN int uv_fs_fsync(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - uv_fs_cb cb); -UV_EXTERN int uv_fs_fdatasync(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - uv_fs_cb cb); -UV_EXTERN int uv_fs_ftruncate(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - int64_t offset, - uv_fs_cb cb); -UV_EXTERN int uv_fs_sendfile(uv_loop_t* loop, - uv_fs_t* req, - uv_file out_fd, - uv_file in_fd, - int64_t in_offset, - size_t length, - uv_fs_cb cb); -UV_EXTERN int uv_fs_access(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - int mode, - uv_fs_cb cb); -UV_EXTERN int uv_fs_chmod(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - int mode, - uv_fs_cb cb); -UV_EXTERN int uv_fs_utime(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - double atime, - double mtime, - uv_fs_cb cb); -UV_EXTERN int uv_fs_futime(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - double atime, - double mtime, - uv_fs_cb cb); -UV_EXTERN int uv_fs_lstat(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - uv_fs_cb cb); -UV_EXTERN int uv_fs_link(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - const char* new_path, - uv_fs_cb cb); - -/* - * This flag can be used with uv_fs_symlink() on Windows to specify whether - * path argument points to a directory. - */ -#define UV_FS_SYMLINK_DIR 0x0001 - -/* - * This flag can be used with uv_fs_symlink() on Windows to specify whether - * the symlink is to be created using junction points. - */ -#define UV_FS_SYMLINK_JUNCTION 0x0002 - -UV_EXTERN int uv_fs_symlink(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - const char* new_path, - int flags, - uv_fs_cb cb); -UV_EXTERN int uv_fs_readlink(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - uv_fs_cb cb); -UV_EXTERN int uv_fs_fchmod(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - int mode, - uv_fs_cb cb); -UV_EXTERN int uv_fs_chown(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - uv_uid_t uid, - uv_gid_t gid, - uv_fs_cb cb); -UV_EXTERN int uv_fs_fchown(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - uv_uid_t uid, - uv_gid_t gid, - uv_fs_cb cb); - - -enum uv_fs_event { - UV_RENAME = 1, - UV_CHANGE = 2 -}; - - -struct uv_fs_event_s { - UV_HANDLE_FIELDS - /* private */ - char* path; - UV_FS_EVENT_PRIVATE_FIELDS -}; - - -/* - * uv_fs_stat() based polling file watcher. - */ -struct uv_fs_poll_s { - UV_HANDLE_FIELDS - /* Private, don't touch. */ - void* poll_ctx; -}; - -UV_EXTERN int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle); -UV_EXTERN int uv_fs_poll_start(uv_fs_poll_t* handle, - uv_fs_poll_cb poll_cb, - const char* path, - unsigned int interval); -UV_EXTERN int uv_fs_poll_stop(uv_fs_poll_t* handle); -UV_EXTERN int uv_fs_poll_getpath(uv_fs_poll_t* handle, - char* buffer, - size_t* size); - - -struct uv_signal_s { - UV_HANDLE_FIELDS - uv_signal_cb signal_cb; - int signum; - UV_SIGNAL_PRIVATE_FIELDS -}; - -UV_EXTERN int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle); -UV_EXTERN int uv_signal_start(uv_signal_t* handle, - uv_signal_cb signal_cb, - int signum); -UV_EXTERN int uv_signal_stop(uv_signal_t* handle); - -UV_EXTERN void uv_loadavg(double avg[3]); - - -/* - * Flags to be passed to uv_fs_event_start(). - */ -enum uv_fs_event_flags { - /* - * By default, if the fs event watcher is given a directory name, we will - * watch for all events in that directory. This flags overrides this behavior - * and makes fs_event report only changes to the directory entry itself. This - * flag does not affect individual files watched. - * This flag is currently not implemented yet on any backend. - */ - UV_FS_EVENT_WATCH_ENTRY = 1, - - /* - * By default uv_fs_event will try to use a kernel interface such as inotify - * or kqueue to detect events. This may not work on remote filesystems such - * as NFS mounts. This flag makes fs_event fall back to calling stat() on a - * regular interval. - * This flag is currently not implemented yet on any backend. - */ - UV_FS_EVENT_STAT = 2, - - /* - * By default, event watcher, when watching directory, is not registering - * (is ignoring) changes in it's subdirectories. - * This flag will override this behaviour on platforms that support it. - */ - UV_FS_EVENT_RECURSIVE = 4 -}; - - -UV_EXTERN int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle); -UV_EXTERN int uv_fs_event_start(uv_fs_event_t* handle, - uv_fs_event_cb cb, - const char* path, - unsigned int flags); -UV_EXTERN int uv_fs_event_stop(uv_fs_event_t* handle); -UV_EXTERN int uv_fs_event_getpath(uv_fs_event_t* handle, - char* buffer, - size_t* size); - -UV_EXTERN int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr); -UV_EXTERN int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr); - -UV_EXTERN int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size); -UV_EXTERN int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size); - -UV_EXTERN int uv_inet_ntop(int af, const void* src, char* dst, size_t size); -UV_EXTERN int uv_inet_pton(int af, const char* src, void* dst); - -UV_EXTERN int uv_exepath(char* buffer, size_t* size); - -UV_EXTERN int uv_cwd(char* buffer, size_t* size); - -UV_EXTERN int uv_chdir(const char* dir); - -UV_EXTERN uint64_t uv_get_free_memory(void); -UV_EXTERN uint64_t uv_get_total_memory(void); - -UV_EXTERN extern uint64_t uv_hrtime(void); - -UV_EXTERN void uv_disable_stdio_inheritance(void); - -UV_EXTERN int uv_dlopen(const char* filename, uv_lib_t* lib); -UV_EXTERN void uv_dlclose(uv_lib_t* lib); -UV_EXTERN int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr); -UV_EXTERN const char* uv_dlerror(const uv_lib_t* lib); - -UV_EXTERN int uv_mutex_init(uv_mutex_t* handle); -UV_EXTERN void uv_mutex_destroy(uv_mutex_t* handle); -UV_EXTERN void uv_mutex_lock(uv_mutex_t* handle); -UV_EXTERN int uv_mutex_trylock(uv_mutex_t* handle); -UV_EXTERN void uv_mutex_unlock(uv_mutex_t* handle); - -UV_EXTERN int uv_rwlock_init(uv_rwlock_t* rwlock); -UV_EXTERN void uv_rwlock_destroy(uv_rwlock_t* rwlock); -UV_EXTERN void uv_rwlock_rdlock(uv_rwlock_t* rwlock); -UV_EXTERN int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock); -UV_EXTERN void uv_rwlock_rdunlock(uv_rwlock_t* rwlock); -UV_EXTERN void uv_rwlock_wrlock(uv_rwlock_t* rwlock); -UV_EXTERN int uv_rwlock_trywrlock(uv_rwlock_t* rwlock); -UV_EXTERN void uv_rwlock_wrunlock(uv_rwlock_t* rwlock); - -UV_EXTERN int uv_sem_init(uv_sem_t* sem, unsigned int value); -UV_EXTERN void uv_sem_destroy(uv_sem_t* sem); -UV_EXTERN void uv_sem_post(uv_sem_t* sem); -UV_EXTERN void uv_sem_wait(uv_sem_t* sem); -UV_EXTERN int uv_sem_trywait(uv_sem_t* sem); - -UV_EXTERN int uv_cond_init(uv_cond_t* cond); -UV_EXTERN void uv_cond_destroy(uv_cond_t* cond); -UV_EXTERN void uv_cond_signal(uv_cond_t* cond); -UV_EXTERN void uv_cond_broadcast(uv_cond_t* cond); - -UV_EXTERN int uv_barrier_init(uv_barrier_t* barrier, unsigned int count); -UV_EXTERN void uv_barrier_destroy(uv_barrier_t* barrier); -UV_EXTERN int uv_barrier_wait(uv_barrier_t* barrier); - -UV_EXTERN void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex); -UV_EXTERN int uv_cond_timedwait(uv_cond_t* cond, - uv_mutex_t* mutex, - uint64_t timeout); - -UV_EXTERN void uv_once(uv_once_t* guard, void (*callback)(void)); - -UV_EXTERN int uv_key_create(uv_key_t* key); -UV_EXTERN void uv_key_delete(uv_key_t* key); -UV_EXTERN void* uv_key_get(uv_key_t* key); -UV_EXTERN void uv_key_set(uv_key_t* key, void* value); - -typedef void (*uv_thread_cb)(void* arg); - -UV_EXTERN int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg); -UV_EXTERN uv_thread_t uv_thread_self(void); -UV_EXTERN int uv_thread_join(uv_thread_t *tid); -UV_EXTERN int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2); - -/* The presence of these unions force similar struct layout. */ -#define XX(_, name) uv_ ## name ## _t name; -union uv_any_handle { - UV_HANDLE_TYPE_MAP(XX) -}; - -union uv_any_req { - UV_REQ_TYPE_MAP(XX) -}; -#undef XX - - -struct uv_loop_s { - /* User data - use this for whatever. */ - void* data; - /* Loop reference counting. */ - unsigned int active_handles; - void* handle_queue[2]; - void* active_reqs[2]; - /* Internal flag to signal loop stop. */ - unsigned int stop_flag; - UV_LOOP_PRIVATE_FIELDS -}; - - -/* Don't export the private CPP symbols. */ -#undef UV_HANDLE_TYPE_PRIVATE -#undef UV_REQ_TYPE_PRIVATE -#undef UV_REQ_PRIVATE_FIELDS -#undef UV_STREAM_PRIVATE_FIELDS -#undef UV_TCP_PRIVATE_FIELDS -#undef UV_PREPARE_PRIVATE_FIELDS -#undef UV_CHECK_PRIVATE_FIELDS -#undef UV_IDLE_PRIVATE_FIELDS -#undef UV_ASYNC_PRIVATE_FIELDS -#undef UV_TIMER_PRIVATE_FIELDS -#undef UV_GETADDRINFO_PRIVATE_FIELDS -#undef UV_GETNAMEINFO_PRIVATE_FIELDS -#undef UV_FS_REQ_PRIVATE_FIELDS -#undef UV_WORK_PRIVATE_FIELDS -#undef UV_FS_EVENT_PRIVATE_FIELDS -#undef UV_SIGNAL_PRIVATE_FIELDS -#undef UV_LOOP_PRIVATE_FIELDS -#undef UV_LOOP_PRIVATE_PLATFORM_FIELDS - -#ifdef __cplusplus -} -#endif -#endif /* UV_H */ diff --git a/libuv/libuv.pc.in b/libuv/libuv.pc.in deleted file mode 100644 index 2933ec2..0000000 --- a/libuv/libuv.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=@prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: @PACKAGE_NAME@ -Version: @PACKAGE_VERSION@ -Description: multi-platform support library with a focus on asynchronous I/O. - -Libs: -L${libdir} -luv @LIBS@ -Cflags: -I${includedir} diff --git a/libuv/m4/.gitignore b/libuv/m4/.gitignore deleted file mode 100644 index c44e4c2..0000000 --- a/libuv/m4/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Ignore libtoolize-generated files. -*.m4 -!as_case.m4 -!libuv-check-flags.m4 diff --git a/libuv/m4/as_case.m4 b/libuv/m4/as_case.m4 deleted file mode 100644 index c7ae0f0..0000000 --- a/libuv/m4/as_case.m4 +++ /dev/null @@ -1,21 +0,0 @@ -# AS_CASE(WORD, [PATTERN1], [IF-MATCHED1]...[DEFAULT]) -# ---------------------------------------------------- -# Expand into -# | case WORD in -# | PATTERN1) IF-MATCHED1 ;; -# | ... -# | *) DEFAULT ;; -# | esac -m4_define([_AS_CASE], -[m4_if([$#], 0, [m4_fatal([$0: too few arguments: $#])], - [$#], 1, [ *) $1 ;;], - [$#], 2, [ $1) m4_default([$2], [:]) ;;], - [ $1) m4_default([$2], [:]) ;; -$0(m4_shiftn(2, $@))])dnl -]) -m4_defun([AS_CASE], -[m4_ifval([$2$3], -[case $1 in -_AS_CASE(m4_shift($@)) -esac])]) - diff --git a/libuv/m4/libuv-check-flags.m4 b/libuv/m4/libuv-check-flags.m4 deleted file mode 100644 index 59c3063..0000000 --- a/libuv/m4/libuv-check-flags.m4 +++ /dev/null @@ -1,319 +0,0 @@ -dnl Macros to check the presence of generic (non-typed) symbols. -dnl Copyright (c) 2006-2008 Diego Pettenà -dnl Copyright (c) 2006-2008 xine project -dnl -dnl This program is free software; you can redistribute it and/or modify -dnl it under the terms of the GNU General Public License as published by -dnl the Free Software Foundation; either version 3, or (at your option) -dnl any later version. -dnl -dnl This program is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -dnl GNU General Public License for more details. -dnl -dnl You should have received a copy of the GNU General Public License -dnl along with this program; if not, write to the Free Software -dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -dnl 02110-1301, USA. -dnl -dnl As a special exception, the copyright owners of the -dnl macro gives unlimited permission to copy, distribute and modify the -dnl configure scripts that are the output of Autoconf when processing the -dnl Macro. You need not follow the terms of the GNU General Public -dnl License when using or distributing such scripts, even though portions -dnl of the text of the Macro appear in them. The GNU General Public -dnl License (GPL) does govern all other use of the material that -dnl constitutes the Autoconf Macro. -dnl -dnl This special exception to the GPL applies to versions of the -dnl Autoconf Macro released by this project. When you make and -dnl distribute a modified version of the Autoconf Macro, you may extend -dnl this special exception to the GPL to apply to your modified version as -dnl well. - -dnl Check if the flag is supported by compiler -dnl CC_CHECK_CFLAGS_SILENT([FLAG], [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND]) - -AC_DEFUN([CC_CHECK_CFLAGS_SILENT], [ - AC_CACHE_VAL(AS_TR_SH([cc_cv_cflags_$1]), - [ac_save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $1" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([int a;])], - [eval "AS_TR_SH([cc_cv_cflags_$1])='yes'"], - [eval "AS_TR_SH([cc_cv_cflags_$1])='no'"]) - CFLAGS="$ac_save_CFLAGS" - ]) - - AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes], - [$2], [$3]) -]) - -dnl Check if the flag is supported by compiler (cacheable) -dnl CC_CHECK_CFLAGS([FLAG], [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND]) - -AC_DEFUN([CC_CHECK_CFLAGS], [ - AC_CACHE_CHECK([if $CC supports $1 flag], - AS_TR_SH([cc_cv_cflags_$1]), - CC_CHECK_CFLAGS_SILENT([$1]) dnl Don't execute actions here! - ) - - AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes], - [$2], [$3]) -]) - -dnl CC_CHECK_CFLAG_APPEND(FLAG, [action-if-found], [action-if-not-found]) -dnl Check for CFLAG and appends them to CFLAGS if supported -AC_DEFUN([CC_CHECK_CFLAG_APPEND], [ - AC_CACHE_CHECK([if $CC supports $1 flag], - AS_TR_SH([cc_cv_cflags_$1]), - CC_CHECK_CFLAGS_SILENT([$1]) dnl Don't execute actions here! - ) - - AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes], - [CFLAGS="$CFLAGS $1"; DEBUG_CFLAGS="$DEBUG_CFLAGS $1"; $2], [$3]) -]) - -dnl CC_CHECK_CFLAGS_APPEND([FLAG1 FLAG2], [action-if-found], [action-if-not]) -AC_DEFUN([CC_CHECK_CFLAGS_APPEND], [ - for flag in $1; do - CC_CHECK_CFLAG_APPEND($flag, [$2], [$3]) - done -]) - -dnl Check if the flag is supported by linker (cacheable) -dnl CC_CHECK_LDFLAGS([FLAG], [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND]) - -AC_DEFUN([CC_CHECK_LDFLAGS], [ - AC_CACHE_CHECK([if $CC supports $1 flag], - AS_TR_SH([cc_cv_ldflags_$1]), - [ac_save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $1" - AC_LANG_PUSH([C]) - AC_LINK_IFELSE([AC_LANG_SOURCE([int main() { return 1; }])], - [eval "AS_TR_SH([cc_cv_ldflags_$1])='yes'"], - [eval "AS_TR_SH([cc_cv_ldflags_$1])="]) - AC_LANG_POP([C]) - LDFLAGS="$ac_save_LDFLAGS" - ]) - - AS_IF([eval test x$]AS_TR_SH([cc_cv_ldflags_$1])[ = xyes], - [$2], [$3]) -]) - -dnl define the LDFLAGS_NOUNDEFINED variable with the correct value for -dnl the current linker to avoid undefined references in a shared object. -AC_DEFUN([CC_NOUNDEFINED], [ - dnl We check $host for which systems to enable this for. - AC_REQUIRE([AC_CANONICAL_HOST]) - - case $host in - dnl FreeBSD (et al.) does not complete linking for shared objects when pthreads - dnl are requested, as different implementations are present; to avoid problems - dnl use -Wl,-z,defs only for those platform not behaving this way. - *-freebsd* | *-openbsd*) ;; - *) - dnl First of all check for the --no-undefined variant of GNU ld. This allows - dnl for a much more readable commandline, so that people can understand what - dnl it does without going to look for what the heck -z defs does. - for possible_flags in "-Wl,--no-undefined" "-Wl,-z,defs"; do - CC_CHECK_LDFLAGS([$possible_flags], [LDFLAGS_NOUNDEFINED="$possible_flags"]) - break - done - ;; - esac - - AC_SUBST([LDFLAGS_NOUNDEFINED]) -]) - -dnl Check for a -Werror flag or equivalent. -Werror is the GCC -dnl and ICC flag that tells the compiler to treat all the warnings -dnl as fatal. We usually need this option to make sure that some -dnl constructs (like attributes) are not simply ignored. -dnl -dnl Other compilers don't support -Werror per se, but they support -dnl an equivalent flag: -dnl - Sun Studio compiler supports -errwarn=%all -AC_DEFUN([CC_CHECK_WERROR], [ - AC_CACHE_CHECK( - [for $CC way to treat warnings as errors], - [cc_cv_werror], - [CC_CHECK_CFLAGS_SILENT([-Werror], [cc_cv_werror=-Werror], - [CC_CHECK_CFLAGS_SILENT([-errwarn=%all], [cc_cv_werror=-errwarn=%all])]) - ]) -]) - -AC_DEFUN([CC_CHECK_ATTRIBUTE], [ - AC_REQUIRE([CC_CHECK_WERROR]) - AC_CACHE_CHECK([if $CC supports __attribute__(( ifelse([$2], , [$1], [$2]) ))], - AS_TR_SH([cc_cv_attribute_$1]), - [ac_save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $cc_cv_werror" - AC_LANG_PUSH([C]) - AC_COMPILE_IFELSE([AC_LANG_SOURCE([$3])], - [eval "AS_TR_SH([cc_cv_attribute_$1])='yes'"], - [eval "AS_TR_SH([cc_cv_attribute_$1])='no'"]) - AC_LANG_POP([C]) - CFLAGS="$ac_save_CFLAGS" - ]) - - AS_IF([eval test x$]AS_TR_SH([cc_cv_attribute_$1])[ = xyes], - [AC_DEFINE( - AS_TR_CPP([SUPPORT_ATTRIBUTE_$1]), 1, - [Define this if the compiler supports __attribute__(( ifelse([$2], , [$1], [$2]) ))] - ) - $4], - [$5]) -]) - -AC_DEFUN([CC_ATTRIBUTE_CONSTRUCTOR], [ - CC_CHECK_ATTRIBUTE( - [constructor],, - [void __attribute__((constructor)) ctor() { int a; }], - [$1], [$2]) -]) - -AC_DEFUN([CC_ATTRIBUTE_FORMAT], [ - CC_CHECK_ATTRIBUTE( - [format], [format(printf, n, n)], - [void __attribute__((format(printf, 1, 2))) printflike(const char *fmt, ...) { fmt = (void *)0; }], - [$1], [$2]) -]) - -AC_DEFUN([CC_ATTRIBUTE_FORMAT_ARG], [ - CC_CHECK_ATTRIBUTE( - [format_arg], [format_arg(printf)], - [char *__attribute__((format_arg(1))) gettextlike(const char *fmt) { fmt = (void *)0; }], - [$1], [$2]) -]) - -AC_DEFUN([CC_ATTRIBUTE_VISIBILITY], [ - CC_CHECK_ATTRIBUTE( - [visibility_$1], [visibility("$1")], - [void __attribute__((visibility("$1"))) $1_function() { }], - [$2], [$3]) -]) - -AC_DEFUN([CC_ATTRIBUTE_NONNULL], [ - CC_CHECK_ATTRIBUTE( - [nonnull], [nonnull()], - [void __attribute__((nonnull())) some_function(void *foo, void *bar) { foo = (void*)0; bar = (void*)0; }], - [$1], [$2]) -]) - -AC_DEFUN([CC_ATTRIBUTE_UNUSED], [ - CC_CHECK_ATTRIBUTE( - [unused], , - [void some_function(void *foo, __attribute__((unused)) void *bar);], - [$1], [$2]) -]) - -AC_DEFUN([CC_ATTRIBUTE_SENTINEL], [ - CC_CHECK_ATTRIBUTE( - [sentinel], , - [void some_function(void *foo, ...) __attribute__((sentinel));], - [$1], [$2]) -]) - -AC_DEFUN([CC_ATTRIBUTE_DEPRECATED], [ - CC_CHECK_ATTRIBUTE( - [deprecated], , - [void some_function(void *foo, ...) __attribute__((deprecated));], - [$1], [$2]) -]) - -AC_DEFUN([CC_ATTRIBUTE_ALIAS], [ - CC_CHECK_ATTRIBUTE( - [alias], [weak, alias], - [void other_function(void *foo) { } - void some_function(void *foo) __attribute__((weak, alias("other_function")));], - [$1], [$2]) -]) - -AC_DEFUN([CC_ATTRIBUTE_MALLOC], [ - CC_CHECK_ATTRIBUTE( - [malloc], , - [void * __attribute__((malloc)) my_alloc(int n);], - [$1], [$2]) -]) - -AC_DEFUN([CC_ATTRIBUTE_PACKED], [ - CC_CHECK_ATTRIBUTE( - [packed], , - [struct astructure { char a; int b; long c; void *d; } __attribute__((packed));], - [$1], [$2]) -]) - -AC_DEFUN([CC_ATTRIBUTE_CONST], [ - CC_CHECK_ATTRIBUTE( - [const], , - [int __attribute__((const)) twopow(int n) { return 1 << n; } ], - [$1], [$2]) -]) - -AC_DEFUN([CC_FLAG_VISIBILITY], [ - AC_REQUIRE([CC_CHECK_WERROR]) - AC_CACHE_CHECK([if $CC supports -fvisibility=hidden], - [cc_cv_flag_visibility], - [cc_flag_visibility_save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $cc_cv_werror" - CC_CHECK_CFLAGS_SILENT([-fvisibility=hidden], - cc_cv_flag_visibility='yes', - cc_cv_flag_visibility='no') - CFLAGS="$cc_flag_visibility_save_CFLAGS"]) - - AS_IF([test "x$cc_cv_flag_visibility" = "xyes"], - [AC_DEFINE([SUPPORT_FLAG_VISIBILITY], 1, - [Define this if the compiler supports the -fvisibility flag]) - $1], - [$2]) -]) - -AC_DEFUN([CC_FUNC_EXPECT], [ - AC_REQUIRE([CC_CHECK_WERROR]) - AC_CACHE_CHECK([if compiler has __builtin_expect function], - [cc_cv_func_expect], - [ac_save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $cc_cv_werror" - AC_LANG_PUSH([C]) - AC_COMPILE_IFELSE([AC_LANG_SOURCE( - [int some_function() { - int a = 3; - return (int)__builtin_expect(a, 3); - }])], - [cc_cv_func_expect=yes], - [cc_cv_func_expect=no]) - AC_LANG_POP([C]) - CFLAGS="$ac_save_CFLAGS" - ]) - - AS_IF([test "x$cc_cv_func_expect" = "xyes"], - [AC_DEFINE([SUPPORT__BUILTIN_EXPECT], 1, - [Define this if the compiler supports __builtin_expect() function]) - $1], - [$2]) -]) - -AC_DEFUN([CC_ATTRIBUTE_ALIGNED], [ - AC_REQUIRE([CC_CHECK_WERROR]) - AC_CACHE_CHECK([highest __attribute__ ((aligned ())) supported], - [cc_cv_attribute_aligned], - [ac_save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $cc_cv_werror" - AC_LANG_PUSH([C]) - for cc_attribute_align_try in 64 32 16 8 4 2; do - AC_COMPILE_IFELSE([AC_LANG_SOURCE([ - int main() { - static char c __attribute__ ((aligned($cc_attribute_align_try))) = 0; - return c; - }])], [cc_cv_attribute_aligned=$cc_attribute_align_try; break]) - done - AC_LANG_POP([C]) - CFLAGS="$ac_save_CFLAGS" - ]) - - if test "x$cc_cv_attribute_aligned" != "x"; then - AC_DEFINE_UNQUOTED([ATTRIBUTE_ALIGNED_MAX], [$cc_cv_attribute_aligned], - [Define the highest alignment supported]) - fi -]) \ No newline at end of file diff --git a/libuv/samples/.gitignore b/libuv/samples/.gitignore deleted file mode 100644 index f868091..0000000 --- a/libuv/samples/.gitignore +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright StrongLoop, Inc. All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -*.mk -*.Makefile diff --git a/libuv/samples/socks5-proxy/.gitignore b/libuv/samples/socks5-proxy/.gitignore deleted file mode 100644 index c177f37..0000000 --- a/libuv/samples/socks5-proxy/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright StrongLoop, Inc. All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -/build/ diff --git a/libuv/samples/socks5-proxy/LICENSE b/libuv/samples/socks5-proxy/LICENSE deleted file mode 100644 index 63c1447..0000000 --- a/libuv/samples/socks5-proxy/LICENSE +++ /dev/null @@ -1,53 +0,0 @@ -Files: * -======== - -Copyright StrongLoop, Inc. All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. - - -Files: getopt.c -=============== - -Copyright (c) 1987, 1993, 1994 -The Regents of the University of California. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. Neither the name of the University nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. diff --git a/libuv/samples/socks5-proxy/build.gyp b/libuv/samples/socks5-proxy/build.gyp deleted file mode 100644 index 771a1e1..0000000 --- a/libuv/samples/socks5-proxy/build.gyp +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright StrongLoop, Inc. All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -{ - 'targets': [ - { - 'dependencies': ['../../uv.gyp:libuv'], - 'target_name': 's5-proxy', - 'type': 'executable', - 'sources': [ - 'client.c', - 'defs.h', - 'main.c', - 's5.c', - 's5.h', - 'server.c', - 'util.c', - ], - 'conditions': [ - ['OS=="win"', { - 'defines': ['HAVE_UNISTD_H=0'], - 'sources': ['getopt.c'] - }, { - 'defines': ['HAVE_UNISTD_H=1'] - }] - ] - } - ] -} diff --git a/libuv/samples/socks5-proxy/client.c b/libuv/samples/socks5-proxy/client.c deleted file mode 100644 index ae9913a..0000000 --- a/libuv/samples/socks5-proxy/client.c +++ /dev/null @@ -1,737 +0,0 @@ -/* Copyright StrongLoop, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "defs.h" -#include -#include -#include - -/* A connection is modeled as an abstraction on top of two simple state - * machines, one for reading and one for writing. Either state machine - * is, when active, in one of three states: busy, done or stop; the fourth - * and final state, dead, is an end state and only relevant when shutting - * down the connection. A short overview: - * - * busy done stop - * ----------|---------------------------|--------------------|------| - * readable | waiting for incoming data | have incoming data | idle | - * writable | busy writing out data | completed write | idle | - * - * We could remove the done state from the writable state machine. For our - * purposes, it's functionally equivalent to the stop state. - * - * When the connection with upstream has been established, the client_ctx - * moves into a state where incoming data from the client is sent upstream - * and vice versa, incoming data from upstream is sent to the client. In - * other words, we're just piping data back and forth. See conn_cycle() - * for details. - * - * An interesting deviation from libuv's I/O model is that reads are discrete - * rather than continuous events. In layman's terms, when a read operation - * completes, the connection stops reading until further notice. - * - * The rationale for this approach is that we have to wait until the data - * has been sent out again before we can reuse the read buffer. - * - * It also pleasingly unifies with the request model that libuv uses for - * writes and everything else; libuv may switch to a request model for - * reads in the future. - */ -enum conn_state { - c_busy, /* Busy; waiting for incoming data or for a write to complete. */ - c_done, /* Done; read incoming data or write finished. */ - c_stop, /* Stopped. */ - c_dead -}; - -/* Session states. */ -enum sess_state { - s_handshake, /* Wait for client handshake. */ - s_handshake_auth, /* Wait for client authentication data. */ - s_req_start, /* Start waiting for request data. */ - s_req_parse, /* Wait for request data. */ - s_req_lookup, /* Wait for upstream hostname DNS lookup to complete. */ - s_req_connect, /* Wait for uv_tcp_connect() to complete. */ - s_proxy_start, /* Connected. Start piping data. */ - s_proxy, /* Connected. Pipe data back and forth. */ - s_kill, /* Tear down session. */ - s_almost_dead_0, /* Waiting for finalizers to complete. */ - s_almost_dead_1, /* Waiting for finalizers to complete. */ - s_almost_dead_2, /* Waiting for finalizers to complete. */ - s_almost_dead_3, /* Waiting for finalizers to complete. */ - s_almost_dead_4, /* Waiting for finalizers to complete. */ - s_dead /* Dead. Safe to free now. */ -}; - -static void do_next(client_ctx *cx); -static int do_handshake(client_ctx *cx); -static int do_handshake_auth(client_ctx *cx); -static int do_req_start(client_ctx *cx); -static int do_req_parse(client_ctx *cx); -static int do_req_lookup(client_ctx *cx); -static int do_req_connect_start(client_ctx *cx); -static int do_req_connect(client_ctx *cx); -static int do_proxy_start(client_ctx *cx); -static int do_proxy(client_ctx *cx); -static int do_kill(client_ctx *cx); -static int do_almost_dead(client_ctx *cx); -static int conn_cycle(const char *who, conn *a, conn *b); -static void conn_timer_reset(conn *c); -static void conn_timer_expire(uv_timer_t *handle, int status); -static void conn_getaddrinfo(conn *c, const char *hostname); -static void conn_getaddrinfo_done(uv_getaddrinfo_t *req, - int status, - struct addrinfo *ai); -static int conn_connect(conn *c); -static void conn_connect_done(uv_connect_t *req, int status); -static void conn_read(conn *c); -static void conn_read_done(uv_stream_t *handle, - ssize_t nread, - const uv_buf_t *buf); -static void conn_alloc(uv_handle_t *handle, size_t size, uv_buf_t *buf); -static void conn_write(conn *c, const void *data, unsigned int len); -static void conn_write_done(uv_write_t *req, int status); -static void conn_close(conn *c); -static void conn_close_done(uv_handle_t *handle); - -/* |incoming| has been initialized by server.c when this is called. */ -void client_finish_init(server_ctx *sx, client_ctx *cx) { - conn *incoming; - conn *outgoing; - - cx->sx = sx; - cx->state = s_handshake; - s5_init(&cx->parser); - - incoming = &cx->incoming; - incoming->client = cx; - incoming->result = 0; - incoming->rdstate = c_stop; - incoming->wrstate = c_stop; - incoming->idle_timeout = sx->idle_timeout; - CHECK(0 == uv_timer_init(sx->loop, &incoming->timer_handle)); - - outgoing = &cx->outgoing; - outgoing->client = cx; - outgoing->result = 0; - outgoing->rdstate = c_stop; - outgoing->wrstate = c_stop; - outgoing->idle_timeout = sx->idle_timeout; - CHECK(0 == uv_tcp_init(cx->sx->loop, &outgoing->handle.tcp)); - CHECK(0 == uv_timer_init(cx->sx->loop, &outgoing->timer_handle)); - - /* Wait for the initial packet. */ - conn_read(incoming); -} - -/* This is the core state machine that drives the client <-> upstream proxy. - * We move through the initial handshake and authentication steps first and - * end up (if all goes well) in the proxy state where we're just proxying - * data between the client and upstream. - */ -static void do_next(client_ctx *cx) { - int new_state; - - ASSERT(cx->state != s_dead); - switch (cx->state) { - case s_handshake: - new_state = do_handshake(cx); - break; - case s_handshake_auth: - new_state = do_handshake_auth(cx); - break; - case s_req_start: - new_state = do_req_start(cx); - break; - case s_req_parse: - new_state = do_req_parse(cx); - break; - case s_req_lookup: - new_state = do_req_lookup(cx); - break; - case s_req_connect: - new_state = do_req_connect(cx); - break; - case s_proxy_start: - new_state = do_proxy_start(cx); - break; - case s_proxy: - new_state = do_proxy(cx); - break; - case s_kill: - new_state = do_kill(cx); - break; - case s_almost_dead_0: - case s_almost_dead_1: - case s_almost_dead_2: - case s_almost_dead_3: - case s_almost_dead_4: - new_state = do_almost_dead(cx); - break; - default: - UNREACHABLE(); - } - cx->state = new_state; - - if (cx->state == s_dead) { - if (DEBUG_CHECKS) { - memset(cx, -1, sizeof(*cx)); - } - free(cx); - } -} - -static int do_handshake(client_ctx *cx) { - unsigned int methods; - conn *incoming; - s5_ctx *parser; - uint8_t *data; - size_t size; - int err; - - parser = &cx->parser; - incoming = &cx->incoming; - ASSERT(incoming->rdstate == c_done); - ASSERT(incoming->wrstate == c_stop); - incoming->rdstate = c_stop; - - if (incoming->result < 0) { - pr_err("read error: %s", uv_strerror(incoming->result)); - return do_kill(cx); - } - - data = (uint8_t *) incoming->t.buf; - size = (size_t) incoming->result; - err = s5_parse(parser, &data, &size); - if (err == s5_ok) { - conn_read(incoming); - return s_handshake; /* Need more data. */ - } - - if (size != 0) { - /* Could allow a round-trip saving shortcut here if the requested auth - * method is S5_AUTH_NONE (provided unauthenticated traffic is allowed.) - * Requires client support however. - */ - pr_err("junk in handshake"); - return do_kill(cx); - } - - if (err != s5_auth_select) { - pr_err("handshake error: %s", s5_strerror(err)); - return do_kill(cx); - } - - methods = s5_auth_methods(parser); - if ((methods & S5_AUTH_NONE) && can_auth_none(cx->sx, cx)) { - s5_select_auth(parser, S5_AUTH_NONE); - conn_write(incoming, "\5\0", 2); /* No auth required. */ - return s_req_start; - } - - if ((methods & S5_AUTH_PASSWD) && can_auth_passwd(cx->sx, cx)) { - /* TODO(bnoordhuis) Implement username/password auth. */ - } - - conn_write(incoming, "\5\377", 2); /* No acceptable auth. */ - return s_kill; -} - -/* TODO(bnoordhuis) Implement username/password auth. */ -static int do_handshake_auth(client_ctx *cx) { - UNREACHABLE(); - return do_kill(cx); -} - -static int do_req_start(client_ctx *cx) { - conn *incoming; - - incoming = &cx->incoming; - ASSERT(incoming->rdstate == c_stop); - ASSERT(incoming->wrstate == c_done); - incoming->wrstate = c_stop; - - if (incoming->result < 0) { - pr_err("write error: %s", uv_strerror(incoming->result)); - return do_kill(cx); - } - - conn_read(incoming); - return s_req_parse; -} - -static int do_req_parse(client_ctx *cx) { - conn *incoming; - conn *outgoing; - s5_ctx *parser; - uint8_t *data; - size_t size; - int err; - - parser = &cx->parser; - incoming = &cx->incoming; - outgoing = &cx->outgoing; - ASSERT(incoming->rdstate == c_done); - ASSERT(incoming->wrstate == c_stop); - ASSERT(outgoing->rdstate == c_stop); - ASSERT(outgoing->wrstate == c_stop); - incoming->rdstate = c_stop; - - if (incoming->result < 0) { - pr_err("read error: %s", uv_strerror(incoming->result)); - return do_kill(cx); - } - - data = (uint8_t *) incoming->t.buf; - size = (size_t) incoming->result; - err = s5_parse(parser, &data, &size); - if (err == s5_ok) { - conn_read(incoming); - return s_req_parse; /* Need more data. */ - } - - if (size != 0) { - pr_err("junk in request %u", (unsigned) size); - return do_kill(cx); - } - - if (err != s5_exec_cmd) { - pr_err("request error: %s", s5_strerror(err)); - return do_kill(cx); - } - - if (parser->cmd == s5_cmd_tcp_bind) { - /* Not supported but relatively straightforward to implement. */ - pr_warn("BIND requests are not supported."); - return do_kill(cx); - } - - if (parser->cmd == s5_cmd_udp_assoc) { - /* Not supported. Might be hard to implement because libuv has no - * functionality for detecting the MTU size which the RFC mandates. - */ - pr_warn("UDP ASSOC requests are not supported."); - return do_kill(cx); - } - ASSERT(parser->cmd == s5_cmd_tcp_connect); - - if (parser->atyp == s5_atyp_host) { - conn_getaddrinfo(outgoing, (const char *) parser->daddr); - return s_req_lookup; - } - - if (parser->atyp == s5_atyp_ipv4) { - memset(&outgoing->t.addr4, 0, sizeof(outgoing->t.addr4)); - outgoing->t.addr4.sin_family = AF_INET; - outgoing->t.addr4.sin_port = htons(parser->dport); - memcpy(&outgoing->t.addr4.sin_addr, - parser->daddr, - sizeof(outgoing->t.addr4.sin_addr)); - } else if (parser->atyp == s5_atyp_ipv6) { - memset(&outgoing->t.addr6, 0, sizeof(outgoing->t.addr6)); - outgoing->t.addr6.sin6_family = AF_INET6; - outgoing->t.addr6.sin6_port = htons(parser->dport); - memcpy(&outgoing->t.addr6.sin6_addr, - parser->daddr, - sizeof(outgoing->t.addr6.sin6_addr)); - } else { - UNREACHABLE(); - } - - return do_req_connect_start(cx); -} - -static int do_req_lookup(client_ctx *cx) { - s5_ctx *parser; - conn *incoming; - conn *outgoing; - - parser = &cx->parser; - incoming = &cx->incoming; - outgoing = &cx->outgoing; - ASSERT(incoming->rdstate == c_stop); - ASSERT(incoming->wrstate == c_stop); - ASSERT(outgoing->rdstate == c_stop); - ASSERT(outgoing->wrstate == c_stop); - - if (outgoing->result < 0) { - /* TODO(bnoordhuis) Escape control characters in parser->daddr. */ - pr_err("lookup error for \"%s\": %s", - parser->daddr, - uv_strerror(outgoing->result)); - /* Send back a 'Host unreachable' reply. */ - conn_write(incoming, "\5\4\0\1\0\0\0\0\0\0", 10); - return s_kill; - } - - /* Don't make assumptions about the offset of sin_port/sin6_port. */ - switch (outgoing->t.addr.sa_family) { - case AF_INET: - outgoing->t.addr4.sin_port = htons(parser->dport); - break; - case AF_INET6: - outgoing->t.addr6.sin6_port = htons(parser->dport); - break; - default: - UNREACHABLE(); - } - - return do_req_connect_start(cx); -} - -/* Assumes that cx->outgoing.t.sa contains a valid AF_INET/AF_INET6 address. */ -static int do_req_connect_start(client_ctx *cx) { - conn *incoming; - conn *outgoing; - int err; - - incoming = &cx->incoming; - outgoing = &cx->outgoing; - ASSERT(incoming->rdstate == c_stop); - ASSERT(incoming->wrstate == c_stop); - ASSERT(outgoing->rdstate == c_stop); - ASSERT(outgoing->wrstate == c_stop); - - if (!can_access(cx->sx, cx, &outgoing->t.addr)) { - pr_warn("connection not allowed by ruleset"); - /* Send a 'Connection not allowed by ruleset' reply. */ - conn_write(incoming, "\5\2\0\1\0\0\0\0\0\0", 10); - return s_kill; - } - - err = conn_connect(outgoing); - if (err != 0) { - pr_err("connect error: %s\n", uv_strerror(err)); - return do_kill(cx); - } - - return s_req_connect; -} - -static int do_req_connect(client_ctx *cx) { - const struct sockaddr_in6 *in6; - const struct sockaddr_in *in; - char addr_storage[sizeof(*in6)]; - conn *incoming; - conn *outgoing; - uint8_t *buf; - int addrlen; - - incoming = &cx->incoming; - outgoing = &cx->outgoing; - ASSERT(incoming->rdstate == c_stop); - ASSERT(incoming->wrstate == c_stop); - ASSERT(outgoing->rdstate == c_stop); - ASSERT(outgoing->wrstate == c_stop); - - /* Build and send the reply. Not very pretty but gets the job done. */ - buf = (uint8_t *) incoming->t.buf; - if (outgoing->result == 0) { - /* The RFC mandates that the SOCKS server must include the local port - * and address in the reply. So that's what we do. - */ - addrlen = sizeof(addr_storage); - CHECK(0 == uv_tcp_getsockname(&outgoing->handle.tcp, - (struct sockaddr *) addr_storage, - &addrlen)); - buf[0] = 5; /* Version. */ - buf[1] = 0; /* Success. */ - buf[2] = 0; /* Reserved. */ - if (addrlen == sizeof(*in)) { - buf[3] = 1; /* IPv4. */ - in = (const struct sockaddr_in *) &addr_storage; - memcpy(buf + 4, &in->sin_addr, 4); - memcpy(buf + 8, &in->sin_port, 2); - conn_write(incoming, buf, 10); - } else if (addrlen == sizeof(*in6)) { - buf[3] = 4; /* IPv6. */ - in6 = (const struct sockaddr_in6 *) &addr_storage; - memcpy(buf + 4, &in6->sin6_addr, 16); - memcpy(buf + 20, &in6->sin6_port, 2); - conn_write(incoming, buf, 22); - } else { - UNREACHABLE(); - } - return s_proxy_start; - } else { - pr_err("upstream connection error: %s\n", uv_strerror(outgoing->result)); - /* Send a 'Connection refused' reply. */ - conn_write(incoming, "\5\5\0\1\0\0\0\0\0\0", 10); - return s_kill; - } - - UNREACHABLE(); - return s_kill; -} - -static int do_proxy_start(client_ctx *cx) { - conn *incoming; - conn *outgoing; - - incoming = &cx->incoming; - outgoing = &cx->outgoing; - ASSERT(incoming->rdstate == c_stop); - ASSERT(incoming->wrstate == c_done); - ASSERT(outgoing->rdstate == c_stop); - ASSERT(outgoing->wrstate == c_stop); - incoming->wrstate = c_stop; - - if (incoming->result < 0) { - pr_err("write error: %s", uv_strerror(incoming->result)); - return do_kill(cx); - } - - conn_read(incoming); - conn_read(outgoing); - return s_proxy; -} - -/* Proxy incoming data back and forth. */ -static int do_proxy(client_ctx *cx) { - if (conn_cycle("client", &cx->incoming, &cx->outgoing)) { - return do_kill(cx); - } - - if (conn_cycle("upstream", &cx->outgoing, &cx->incoming)) { - return do_kill(cx); - } - - return s_proxy; -} - -static int do_kill(client_ctx *cx) { - int new_state; - - if (cx->state >= s_almost_dead_0) { - return cx->state; - } - - /* Try to cancel the request. The callback still runs but if the - * cancellation succeeded, it gets called with status=UV_ECANCELED. - */ - new_state = s_almost_dead_1; - if (cx->state == s_req_lookup) { - new_state = s_almost_dead_0; - uv_cancel(&cx->outgoing.t.req); - } - - conn_close(&cx->incoming); - conn_close(&cx->outgoing); - return new_state; -} - -static int do_almost_dead(client_ctx *cx) { - ASSERT(cx->state >= s_almost_dead_0); - return cx->state + 1; /* Another finalizer completed. */ -} - -static int conn_cycle(const char *who, conn *a, conn *b) { - if (a->result < 0) { - if (a->result != UV_EOF) { - pr_err("%s error: %s", who, uv_strerror(a->result)); - } - return -1; - } - - if (b->result < 0) { - return -1; - } - - if (a->wrstate == c_done) { - a->wrstate = c_stop; - } - - /* The logic is as follows: read when we don't write and write when we don't - * read. That gives us back-pressure handling for free because if the peer - * sends data faster than we consume it, TCP congestion control kicks in. - */ - if (a->wrstate == c_stop) { - if (b->rdstate == c_stop) { - conn_read(b); - } else if (b->rdstate == c_done) { - conn_write(a, b->t.buf, b->result); - b->rdstate = c_stop; /* Triggers the call to conn_read() above. */ - } - } - - return 0; -} - -static void conn_timer_reset(conn *c) { - CHECK(0 == uv_timer_start(&c->timer_handle, - conn_timer_expire, - c->idle_timeout, - 0)); -} - -static void conn_timer_expire(uv_timer_t *handle, int status) { - conn *c; - - CHECK(0 == status); - c = CONTAINER_OF(handle, conn, timer_handle); - c->result = UV_ETIMEDOUT; - do_next(c->client); -} - -static void conn_getaddrinfo(conn *c, const char *hostname) { - struct addrinfo hints; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - CHECK(0 == uv_getaddrinfo(c->client->sx->loop, - &c->t.addrinfo_req, - conn_getaddrinfo_done, - hostname, - NULL, - &hints)); - conn_timer_reset(c); -} - -static void conn_getaddrinfo_done(uv_getaddrinfo_t *req, - int status, - struct addrinfo *ai) { - conn *c; - - c = CONTAINER_OF(req, conn, t.addrinfo_req); - c->result = status; - - if (status == 0) { - /* FIXME(bnoordhuis) Should try all addresses. */ - if (ai->ai_family == AF_INET) { - c->t.addr4 = *(const struct sockaddr_in *) ai->ai_addr; - } else if (ai->ai_family == AF_INET6) { - c->t.addr6 = *(const struct sockaddr_in6 *) ai->ai_addr; - } else { - UNREACHABLE(); - } - } - - uv_freeaddrinfo(ai); - do_next(c->client); -} - -/* Assumes that c->t.sa contains a valid AF_INET or AF_INET6 address. */ -static int conn_connect(conn *c) { - ASSERT(c->t.addr.sa_family == AF_INET || - c->t.addr.sa_family == AF_INET6); - conn_timer_reset(c); - return uv_tcp_connect(&c->t.connect_req, - &c->handle.tcp, - &c->t.addr, - conn_connect_done); -} - -static void conn_connect_done(uv_connect_t *req, int status) { - conn *c; - - if (status == UV_ECANCELED) { - return; /* Handle has been closed. */ - } - - c = CONTAINER_OF(req, conn, t.connect_req); - c->result = status; - do_next(c->client); -} - -static void conn_read(conn *c) { - ASSERT(c->rdstate == c_stop); - CHECK(0 == uv_read_start(&c->handle.stream, conn_alloc, conn_read_done)); - c->rdstate = c_busy; - conn_timer_reset(c); -} - -static void conn_read_done(uv_stream_t *handle, - ssize_t nread, - const uv_buf_t *buf) { - conn *c; - - c = CONTAINER_OF(handle, conn, handle); - ASSERT(c->t.buf == buf->base); - ASSERT(c->rdstate == c_busy); - c->rdstate = c_done; - c->result = nread; - - uv_read_stop(&c->handle.stream); - do_next(c->client); -} - -static void conn_alloc(uv_handle_t *handle, size_t size, uv_buf_t *buf) { - conn *c; - - c = CONTAINER_OF(handle, conn, handle); - ASSERT(c->rdstate == c_busy); - buf->base = c->t.buf; - buf->len = sizeof(c->t.buf); -} - -static void conn_write(conn *c, const void *data, unsigned int len) { - uv_buf_t buf; - - ASSERT(c->wrstate == c_stop || c->wrstate == c_done); - c->wrstate = c_busy; - - /* It's okay to cast away constness here, uv_write() won't modify the - * memory. - */ - buf.base = (char *) data; - buf.len = len; - - CHECK(0 == uv_write(&c->write_req, - &c->handle.stream, - &buf, - 1, - conn_write_done)); - conn_timer_reset(c); -} - -static void conn_write_done(uv_write_t *req, int status) { - conn *c; - - if (status == UV_ECANCELED) { - return; /* Handle has been closed. */ - } - - c = CONTAINER_OF(req, conn, write_req); - ASSERT(c->wrstate == c_busy); - c->wrstate = c_done; - c->result = status; - do_next(c->client); -} - -static void conn_close(conn *c) { - ASSERT(c->rdstate != c_dead); - ASSERT(c->wrstate != c_dead); - c->rdstate = c_dead; - c->wrstate = c_dead; - c->timer_handle.data = c; - c->handle.handle.data = c; - uv_close(&c->handle.handle, conn_close_done); - uv_close((uv_handle_t *) &c->timer_handle, conn_close_done); -} - -static void conn_close_done(uv_handle_t *handle) { - conn *c; - - c = handle->data; - do_next(c->client); -} diff --git a/libuv/samples/socks5-proxy/defs.h b/libuv/samples/socks5-proxy/defs.h deleted file mode 100644 index 99ee816..0000000 --- a/libuv/samples/socks5-proxy/defs.h +++ /dev/null @@ -1,139 +0,0 @@ -/* Copyright StrongLoop, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef DEFS_H_ -#define DEFS_H_ - -#include "s5.h" -#include "uv.h" - -#include -#include /* sockaddr_in, sockaddr_in6 */ -#include /* size_t, ssize_t */ -#include -#include /* sockaddr */ - -struct client_ctx; - -typedef struct { - const char *bind_host; - unsigned short bind_port; - unsigned int idle_timeout; -} server_config; - -typedef struct { - unsigned int idle_timeout; /* Connection idle timeout in ms. */ - uv_tcp_t tcp_handle; - uv_loop_t *loop; -} server_ctx; - -typedef struct { - unsigned char rdstate; - unsigned char wrstate; - unsigned int idle_timeout; - struct client_ctx *client; /* Backlink to owning client context. */ - ssize_t result; - union { - uv_handle_t handle; - uv_stream_t stream; - uv_tcp_t tcp; - uv_udp_t udp; - } handle; - uv_timer_t timer_handle; /* For detecting timeouts. */ - uv_write_t write_req; - /* We only need one of these at a time so make them share memory. */ - union { - uv_getaddrinfo_t addrinfo_req; - uv_connect_t connect_req; - uv_req_t req; - struct sockaddr_in6 addr6; - struct sockaddr_in addr4; - struct sockaddr addr; - char buf[2048]; /* Scratch space. Used to read data into. */ - } t; -} conn; - -typedef struct client_ctx { - unsigned int state; - server_ctx *sx; /* Backlink to owning server context. */ - s5_ctx parser; /* The SOCKS protocol parser. */ - conn incoming; /* Connection with the SOCKS client. */ - conn outgoing; /* Connection with upstream. */ -} client_ctx; - -/* server.c */ -int server_run(const server_config *cf, uv_loop_t *loop); -int can_auth_none(const server_ctx *sx, const client_ctx *cx); -int can_auth_passwd(const server_ctx *sx, const client_ctx *cx); -int can_access(const server_ctx *sx, - const client_ctx *cx, - const struct sockaddr *addr); - -/* client.c */ -void client_finish_init(server_ctx *sx, client_ctx *cx); - -/* util.c */ -#if defined(__GNUC__) -# define ATTRIBUTE_FORMAT_PRINTF(a, b) __attribute__((format(printf, a, b))) -#else -# define ATTRIBUTE_FORMAT_PRINTF(a, b) -#endif -void pr_info(const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(1, 2); -void pr_warn(const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(1, 2); -void pr_err(const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(1, 2); -void *xmalloc(size_t size); - -/* main.c */ -const char *_getprogname(void); - -/* getopt.c */ -#if !HAVE_UNISTD_H -extern char *optarg; -int getopt(int argc, char **argv, const char *options); -#endif - -/* ASSERT() is for debug checks, CHECK() for run-time sanity checks. - * DEBUG_CHECKS is for expensive debug checks that we only want to - * enable in debug builds but still want type-checked by the compiler - * in release builds. - */ -#if defined(NDEBUG) -# define ASSERT(exp) -# define CHECK(exp) do { if (!(exp)) abort(); } while (0) -# define DEBUG_CHECKS (0) -#else -# define ASSERT(exp) assert(exp) -# define CHECK(exp) assert(exp) -# define DEBUG_CHECKS (1) -#endif - -#define UNREACHABLE() CHECK(!"Unreachable code reached.") - -/* This macro looks complicated but it's not: it calculates the address - * of the embedding struct through the address of the embedded struct. - * In other words, if struct A embeds struct B, then we can obtain - * the address of A by taking the address of B and subtracting the - * field offset of B in A. - */ -#define CONTAINER_OF(ptr, type, field) \ - ((type *) ((char *) (ptr) - ((char *) &((type *) 0)->field))) - -#endif /* DEFS_H_ */ diff --git a/libuv/samples/socks5-proxy/getopt.c b/libuv/samples/socks5-proxy/getopt.c deleted file mode 100644 index 8481b22..0000000 --- a/libuv/samples/socks5-proxy/getopt.c +++ /dev/null @@ -1,131 +0,0 @@ -/* $NetBSD: getopt.c,v 1.26 2003/08/07 16:43:40 agc Exp $ */ - -/* - * Copyright (c) 1987, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95"; -#endif /* LIBC_SCCS and not lint */ - -#include -#include -#include -#include - -extern const char *_getprogname(void); - -int opterr = 1, /* if error message should be printed */ - optind = 1, /* index into parent argv vector */ - optopt, /* character checked for validity */ - optreset; /* reset getopt */ -char *optarg; /* argument associated with option */ - -#define BADCH (int)'?' -#define BADARG (int)':' -#define EMSG "" - -/* - * getopt -- - * Parse argc/argv argument vector. - */ -int -getopt(nargc, nargv, ostr) - int nargc; - char * const nargv[]; - const char *ostr; -{ - static char *place = EMSG; /* option letter processing */ - char *oli; /* option letter list index */ - - if (optreset || *place == 0) { /* update scanning pointer */ - optreset = 0; - place = nargv[optind]; - if (optind >= nargc || *place++ != '-') { - /* Argument is absent or is not an option */ - place = EMSG; - return (-1); - } - optopt = *place++; - if (optopt == '-' && *place == 0) { - /* "--" => end of options */ - ++optind; - place = EMSG; - return (-1); - } - if (optopt == 0) { - /* Solitary '-', treat as a '-' option - if the program (eg su) is looking for it. */ - place = EMSG; - if (strchr(ostr, '-') == NULL) - return (-1); - optopt = '-'; - } - } else - optopt = *place++; - - /* See if option letter is one the caller wanted... */ - if (optopt == ':' || (oli = strchr(ostr, optopt)) == NULL) { - if (*place == 0) - ++optind; - if (opterr && *ostr != ':') - (void)fprintf(stderr, - "%s: illegal option -- %c\n", _getprogname(), - optopt); - return (BADCH); - } - - /* Does this option need an argument? */ - if (oli[1] != ':') { - /* don't need argument */ - optarg = NULL; - if (*place == 0) - ++optind; - } else { - /* Option-argument is either the rest of this argument or the - entire next argument. */ - if (*place) - optarg = place; - else if (nargc > ++optind) - optarg = nargv[optind]; - else { - /* option-argument absent */ - place = EMSG; - if (*ostr == ':') - return (BADARG); - if (opterr) - (void)fprintf(stderr, - "%s: option requires an argument -- %c\n", - _getprogname(), optopt); - return (BADCH); - } - place = EMSG; - ++optind; - } - return (optopt); /* return option letter */ -} diff --git a/libuv/samples/socks5-proxy/main.c b/libuv/samples/socks5-proxy/main.c deleted file mode 100644 index 04020cb..0000000 --- a/libuv/samples/socks5-proxy/main.c +++ /dev/null @@ -1,99 +0,0 @@ -/* Copyright StrongLoop, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "defs.h" -#include -#include -#include - -#if HAVE_UNISTD_H -#include /* getopt */ -#endif - -#define DEFAULT_BIND_HOST "127.0.0.1" -#define DEFAULT_BIND_PORT 1080 -#define DEFAULT_IDLE_TIMEOUT (60 * 1000) - -static void parse_opts(server_config *cf, int argc, char **argv); -static void usage(void); - -static const char *progname = __FILE__; /* Reset in main(). */ - -int main(int argc, char **argv) { - server_config config; - int err; - - progname = argv[0]; - memset(&config, 0, sizeof(config)); - config.bind_host = DEFAULT_BIND_HOST; - config.bind_port = DEFAULT_BIND_PORT; - config.idle_timeout = DEFAULT_IDLE_TIMEOUT; - parse_opts(&config, argc, argv); - - err = server_run(&config, uv_default_loop()); - if (err) { - exit(1); - } - - return 0; -} - -const char *_getprogname(void) { - return progname; -} - -static void parse_opts(server_config *cf, int argc, char **argv) { - int opt; - - while (-1 != (opt = getopt(argc, argv, "H:hp:"))) { - switch (opt) { - case 'H': - cf->bind_host = optarg; - break; - - case 'p': - if (1 != sscanf(optarg, "%hu", &cf->bind_port)) { - pr_err("bad port number: %s", optarg); - usage(); - } - break; - - default: - usage(); - } - } -} - -static void usage(void) { - printf("Usage:\n" - "\n" - " %s [-b
[-h] [-p ]\n" - "\n" - "Options:\n" - "\n" - " -b Bind to this address or hostname.\n" - " Default: \"127.0.0.1\"\n" - " -h Show this help message.\n" - " -p Bind to this port number. Default: 1080\n" - "", - progname); - exit(1); -} diff --git a/libuv/samples/socks5-proxy/s5.c b/libuv/samples/socks5-proxy/s5.c deleted file mode 100644 index 4f08e34..0000000 --- a/libuv/samples/socks5-proxy/s5.c +++ /dev/null @@ -1,271 +0,0 @@ -/* Copyright StrongLoop, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "s5.h" -#include -#include -#include /* abort() */ -#include /* memset() */ - -enum { - s5_version, - s5_nmethods, - s5_methods, - s5_auth_pw_version, - s5_auth_pw_userlen, - s5_auth_pw_username, - s5_auth_pw_passlen, - s5_auth_pw_password, - s5_req_version, - s5_req_cmd, - s5_req_reserved, - s5_req_atyp, - s5_req_atyp_host, - s5_req_daddr, - s5_req_dport0, - s5_req_dport1, - s5_dead -}; - -void s5_init(s5_ctx *cx) { - memset(cx, 0, sizeof(*cx)); - cx->state = s5_version; -} - -s5_err s5_parse(s5_ctx *cx, uint8_t **data, size_t *size) { - s5_err err; - uint8_t *p; - uint8_t c; - size_t i; - size_t n; - - p = *data; - n = *size; - i = 0; - - while (i < n) { - c = p[i]; - i += 1; - switch (cx->state) { - case s5_version: - if (c != 5) { - err = s5_bad_version; - goto out; - } - cx->state = s5_nmethods; - break; - - case s5_nmethods: - cx->arg0 = 0; - cx->arg1 = c; /* Number of bytes to read. */ - cx->state = s5_methods; - break; - - case s5_methods: - if (cx->arg0 < cx->arg1) { - switch (c) { - case 0: - cx->methods |= S5_AUTH_NONE; - break; - case 1: - cx->methods |= S5_AUTH_GSSAPI; - break; - case 2: - cx->methods |= S5_AUTH_PASSWD; - break; - /* Ignore everything we don't understand. */ - } - cx->arg0 += 1; - } - if (cx->arg0 == cx->arg1) { - err = s5_auth_select; - goto out; - } - break; - - case s5_auth_pw_version: - if (c != 1) { - err = s5_bad_version; - goto out; - } - cx->state = s5_auth_pw_userlen; - break; - - case s5_auth_pw_userlen: - cx->arg0 = 0; - cx->userlen = c; - cx->state = s5_auth_pw_username; - break; - - case s5_auth_pw_username: - if (cx->arg0 < cx->userlen) { - cx->username[cx->arg0] = c; - cx->arg0 += 1; - } - if (cx->arg0 == cx->userlen) { - cx->username[cx->userlen] = '\0'; - cx->state = s5_auth_pw_passlen; - } - break; - - case s5_auth_pw_passlen: - cx->arg0 = 0; - cx->passlen = c; - cx->state = s5_auth_pw_password; - break; - - case s5_auth_pw_password: - if (cx->arg0 < cx->passlen) { - cx->password[cx->arg0] = c; - cx->arg0 += 1; - } - if (cx->arg0 == cx->passlen) { - cx->password[cx->passlen] = '\0'; - cx->state = s5_req_version; - err = s5_auth_verify; - goto out; - } - break; - - case s5_req_version: - if (c != 5) { - err = s5_bad_version; - goto out; - } - cx->state = s5_req_cmd; - break; - - case s5_req_cmd: - switch (c) { - case 1: /* TCP connect */ - cx->cmd = s5_cmd_tcp_connect; - break; - case 3: /* UDP associate */ - cx->cmd = s5_cmd_udp_assoc; - break; - default: - err = s5_bad_cmd; - goto out; - } - cx->state = s5_req_reserved; - break; - - case s5_req_reserved: - cx->state = s5_req_atyp; - break; - - case s5_req_atyp: - cx->arg0 = 0; - switch (c) { - case 1: /* IPv4, four octets. */ - cx->state = s5_req_daddr; - cx->atyp = s5_atyp_ipv4; - cx->arg1 = 4; - break; - case 3: /* Hostname. First byte is length. */ - cx->state = s5_req_atyp_host; - cx->atyp = s5_atyp_host; - cx->arg1 = 0; - break; - case 4: /* IPv6, sixteen octets. */ - cx->state = s5_req_daddr; - cx->atyp = s5_atyp_ipv6; - cx->arg1 = 16; - break; - default: - err = s5_bad_atyp; - goto out; - } - break; - - case s5_req_atyp_host: - cx->arg1 = c; - cx->state = s5_req_daddr; - break; - - case s5_req_daddr: - if (cx->arg0 < cx->arg1) { - cx->daddr[cx->arg0] = c; - cx->arg0 += 1; - } - if (cx->arg0 == cx->arg1) { - cx->daddr[cx->arg1] = '\0'; - cx->state = s5_req_dport0; - } - break; - - case s5_req_dport0: - cx->dport = c << 8; - cx->state = s5_req_dport1; - break; - - case s5_req_dport1: - cx->dport |= c; - cx->state = s5_dead; - err = s5_exec_cmd; - goto out; - - case s5_dead: - break; - - default: - abort(); - } - } - err = s5_ok; - -out: - *data = p + i; - *size = n - i; - return err; -} - -unsigned int s5_auth_methods(const s5_ctx *cx) { - return cx->methods; -} - -int s5_select_auth(s5_ctx *cx, s5_auth_method method) { - int err; - - err = 0; - switch (method) { - case S5_AUTH_NONE: - cx->state = s5_req_version; - break; - case S5_AUTH_PASSWD: - cx->state = s5_auth_pw_version; - break; - default: - err = -EINVAL; - } - - return err; -} - -const char *s5_strerror(s5_err err) { -#define S5_ERR_GEN(_, name, errmsg) case s5_ ## name: return errmsg; - switch (err) { - S5_ERR_MAP(S5_ERR_GEN) - default: ; /* Silence s5_max_errors -Wswitch warning. */ - } -#undef S5_ERR_GEN - return "Unknown error."; -} diff --git a/libuv/samples/socks5-proxy/s5.h b/libuv/samples/socks5-proxy/s5.h deleted file mode 100644 index 715f322..0000000 --- a/libuv/samples/socks5-proxy/s5.h +++ /dev/null @@ -1,94 +0,0 @@ -/* Copyright StrongLoop, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef S5_H_ -#define S5_H_ - -#include -#include - -#define S5_ERR_MAP(V) \ - V(-1, bad_version, "Bad protocol version.") \ - V(-2, bad_cmd, "Bad protocol command.") \ - V(-3, bad_atyp, "Bad address type.") \ - V(0, ok, "No error.") \ - V(1, auth_select, "Select authentication method.") \ - V(2, auth_verify, "Verify authentication.") \ - V(3, exec_cmd, "Execute command.") \ - -typedef enum { -#define S5_ERR_GEN(code, name, _) s5_ ## name = code, - S5_ERR_MAP(S5_ERR_GEN) -#undef S5_ERR_GEN - s5_max_errors -} s5_err; - -typedef enum { - S5_AUTH_NONE = 1 << 0, - S5_AUTH_GSSAPI = 1 << 1, - S5_AUTH_PASSWD = 1 << 2 -} s5_auth_method; - -typedef enum { - s5_auth_allow, - s5_auth_deny -} s5_auth_result; - -typedef enum { - s5_atyp_ipv4, - s5_atyp_ipv6, - s5_atyp_host -} s5_atyp; - -typedef enum { - s5_cmd_tcp_connect, - s5_cmd_tcp_bind, - s5_cmd_udp_assoc -} s5_cmd; - -typedef struct { - uint32_t arg0; /* Scratch space for the state machine. */ - uint32_t arg1; /* Scratch space for the state machine. */ - uint8_t state; - uint8_t methods; - uint8_t cmd; - uint8_t atyp; - uint8_t userlen; - uint8_t passlen; - uint16_t dport; - uint8_t username[257]; - uint8_t password[257]; - uint8_t daddr[257]; /* TODO(bnoordhuis) Merge with username/password. */ -} s5_ctx; - -void s5_init(s5_ctx *ctx); - -s5_err s5_parse(s5_ctx *cx, uint8_t **data, size_t *size); - -/* Only call after s5_parse() has returned s5_want_auth_method. */ -unsigned int s5_auth_methods(const s5_ctx *cx); - -/* Call after s5_parse() has returned s5_want_auth_method. */ -int s5_select_auth(s5_ctx *cx, s5_auth_method method); - -const char *s5_strerror(s5_err err); - -#endif /* S5_H_ */ diff --git a/libuv/samples/socks5-proxy/server.c b/libuv/samples/socks5-proxy/server.c deleted file mode 100644 index 3f1ba42..0000000 --- a/libuv/samples/socks5-proxy/server.c +++ /dev/null @@ -1,241 +0,0 @@ -/* Copyright StrongLoop, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "defs.h" -#include /* INET6_ADDRSTRLEN */ -#include -#include - -#ifndef INET6_ADDRSTRLEN -# define INET6_ADDRSTRLEN 63 -#endif - -typedef struct { - uv_getaddrinfo_t getaddrinfo_req; - server_config config; - server_ctx *servers; - uv_loop_t *loop; -} server_state; - -static void do_bind(uv_getaddrinfo_t *req, int status, struct addrinfo *ai); -static void on_connection(uv_stream_t *server, int status); - -int server_run(const server_config *cf, uv_loop_t *loop) { - struct addrinfo hints; - server_state state; - int err; - - memset(&state, 0, sizeof(state)); - state.servers = NULL; - state.config = *cf; - state.loop = loop; - - /* Resolve the address of the interface that we should bind to. - * The getaddrinfo callback starts the server and everything else. - */ - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - - err = uv_getaddrinfo(loop, - &state.getaddrinfo_req, - do_bind, - cf->bind_host, - NULL, - &hints); - if (err != 0) { - pr_err("getaddrinfo: %s", uv_strerror(err)); - return err; - } - - /* Start the event loop. Control continues in do_bind(). */ - if (uv_run(loop, UV_RUN_DEFAULT)) { - abort(); - } - - /* Please Valgrind. */ - uv_loop_delete(loop); - free(state.servers); - return 0; -} - -/* Bind a server to each address that getaddrinfo() reported. */ -static void do_bind(uv_getaddrinfo_t *req, int status, struct addrinfo *addrs) { - char addrbuf[INET6_ADDRSTRLEN + 1]; - unsigned int ipv4_naddrs; - unsigned int ipv6_naddrs; - server_state *state; - server_config *cf; - struct addrinfo *ai; - const void *addrv; - const char *what; - uv_loop_t *loop; - server_ctx *sx; - unsigned int n; - int err; - union { - struct sockaddr addr; - struct sockaddr_in addr4; - struct sockaddr_in6 addr6; - } s; - - state = CONTAINER_OF(req, server_state, getaddrinfo_req); - loop = state->loop; - cf = &state->config; - - if (status < 0) { - pr_err("getaddrinfo(\"%s\"): %s", cf->bind_host, uv_strerror(status)); - uv_freeaddrinfo(addrs); - return; - } - - ipv4_naddrs = 0; - ipv6_naddrs = 0; - for (ai = addrs; ai != NULL; ai = ai->ai_next) { - if (ai->ai_family == AF_INET) { - ipv4_naddrs += 1; - } else if (ai->ai_family == AF_INET6) { - ipv6_naddrs += 1; - } - } - - if (ipv4_naddrs == 0 && ipv6_naddrs == 0) { - pr_err("%s has no IPv4/6 addresses", cf->bind_host); - uv_freeaddrinfo(addrs); - return; - } - - state->servers = - xmalloc((ipv4_naddrs + ipv6_naddrs) * sizeof(state->servers[0])); - - n = 0; - for (ai = addrs; ai != NULL; ai = ai->ai_next) { - if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) { - continue; - } - - if (ai->ai_family == AF_INET) { - s.addr4 = *(const struct sockaddr_in *) ai->ai_addr; - s.addr4.sin_port = htons(cf->bind_port); - addrv = &s.addr4.sin_addr; - } else if (ai->ai_family == AF_INET6) { - s.addr6 = *(const struct sockaddr_in6 *) ai->ai_addr; - s.addr6.sin6_port = htons(cf->bind_port); - addrv = &s.addr6.sin6_addr; - } else { - UNREACHABLE(); - } - - if (uv_inet_ntop(s.addr.sa_family, addrv, addrbuf, sizeof(addrbuf))) { - UNREACHABLE(); - } - - sx = state->servers + n; - sx->loop = loop; - sx->idle_timeout = state->config.idle_timeout; - CHECK(0 == uv_tcp_init(loop, &sx->tcp_handle)); - - what = "uv_tcp_bind"; - err = uv_tcp_bind(&sx->tcp_handle, &s.addr, 0); - if (err == 0) { - what = "uv_listen"; - err = uv_listen((uv_stream_t *) &sx->tcp_handle, 128, on_connection); - } - - if (err != 0) { - pr_err("%s(\"%s:%hu\"): %s", - what, - addrbuf, - cf->bind_port, - uv_strerror(err)); - while (n > 0) { - n -= 1; - uv_close((uv_handle_t *) (state->servers + n), NULL); - } - break; - } - - pr_info("listening on %s:%hu", addrbuf, cf->bind_port); - n += 1; - } - - uv_freeaddrinfo(addrs); -} - -static void on_connection(uv_stream_t *server, int status) { - server_ctx *sx; - client_ctx *cx; - - CHECK(status == 0); - sx = CONTAINER_OF(server, server_ctx, tcp_handle); - cx = xmalloc(sizeof(*cx)); - CHECK(0 == uv_tcp_init(sx->loop, &cx->incoming.handle.tcp)); - CHECK(0 == uv_accept(server, &cx->incoming.handle.stream)); - client_finish_init(sx, cx); -} - -int can_auth_none(const server_ctx *sx, const client_ctx *cx) { - return 1; -} - -int can_auth_passwd(const server_ctx *sx, const client_ctx *cx) { - return 0; -} - -int can_access(const server_ctx *sx, - const client_ctx *cx, - const struct sockaddr *addr) { - const struct sockaddr_in6 *addr6; - const struct sockaddr_in *addr4; - const uint32_t *p; - uint32_t a; - uint32_t b; - uint32_t c; - uint32_t d; - - /* TODO(bnoordhuis) Implement proper access checks. For now, just reject - * traffic to localhost. - */ - if (addr->sa_family == AF_INET) { - addr4 = (const struct sockaddr_in *) addr; - d = ntohl(addr4->sin_addr.s_addr); - return (d >> 24) != 0x7F; - } - - if (addr->sa_family == AF_INET6) { - addr6 = (const struct sockaddr_in6 *) addr; - p = (const uint32_t *) &addr6->sin6_addr.s6_addr; - a = ntohl(p[0]); - b = ntohl(p[1]); - c = ntohl(p[2]); - d = ntohl(p[3]); - if (a == 0 && b == 0 && c == 0 && d == 1) { - return 0; /* "::1" style address. */ - } - if (a == 0 && b == 0 && c == 0xFFFF && (d >> 24) == 0x7F) { - return 0; /* "::ffff:127.x.x.x" style address. */ - } - return 1; - } - - return 0; -} diff --git a/libuv/samples/socks5-proxy/util.c b/libuv/samples/socks5-proxy/util.c deleted file mode 100644 index af34f05..0000000 --- a/libuv/samples/socks5-proxy/util.c +++ /dev/null @@ -1,72 +0,0 @@ -/* Copyright StrongLoop, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "defs.h" -#include -#include -#include - -static void pr_do(FILE *stream, - const char *label, - const char *fmt, - va_list ap); - -void *xmalloc(size_t size) { - void *ptr; - - ptr = malloc(size); - if (ptr == NULL) { - pr_err("out of memory, need %lu bytes", (unsigned long) size); - exit(1); - } - - return ptr; -} - -void pr_info(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - pr_do(stdout, "info", fmt, ap); - va_end(ap); -} - -void pr_warn(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - pr_do(stderr, "warn", fmt, ap); - va_end(ap); -} - -void pr_err(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - pr_do(stderr, "error", fmt, ap); - va_end(ap); -} - -static void pr_do(FILE *stream, - const char *label, - const char *fmt, - va_list ap) { - char fmtbuf[1024]; - vsnprintf(fmtbuf, sizeof(fmtbuf), fmt, ap); - fprintf(stream, "%s:%s: %s\n", _getprogname(), label, fmtbuf); -} diff --git a/libuv/src/fs-poll.c b/libuv/src/fs-poll.c deleted file mode 100644 index 1145e5f..0000000 --- a/libuv/src/fs-poll.c +++ /dev/null @@ -1,255 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "uv-common.h" - -#include -#include -#include - -struct poll_ctx { - uv_fs_poll_t* parent_handle; /* NULL if parent has been stopped or closed */ - int busy_polling; - unsigned int interval; - uint64_t start_time; - uv_loop_t* loop; - uv_fs_poll_cb poll_cb; - uv_timer_t timer_handle; - uv_fs_t fs_req; /* TODO(bnoordhuis) mark fs_req internal */ - uv_stat_t statbuf; - char path[1]; /* variable length */ -}; - -static int statbuf_eq(const uv_stat_t* a, const uv_stat_t* b); -static void poll_cb(uv_fs_t* req); -static void timer_cb(uv_timer_t* timer); -static void timer_close_cb(uv_handle_t* handle); - -static uv_stat_t zero_statbuf; - - -int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle) { - uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_POLL); - return 0; -} - - -int uv_fs_poll_start(uv_fs_poll_t* handle, - uv_fs_poll_cb cb, - const char* path, - unsigned int interval) { - struct poll_ctx* ctx; - uv_loop_t* loop; - size_t len; - int err; - - if (uv__is_active(handle)) - return 0; - - loop = handle->loop; - len = strlen(path); - ctx = calloc(1, sizeof(*ctx) + len); - - if (ctx == NULL) - return UV_ENOMEM; - - ctx->loop = loop; - ctx->poll_cb = cb; - ctx->interval = interval ? interval : 1; - ctx->start_time = uv_now(loop); - ctx->parent_handle = handle; - memcpy(ctx->path, path, len + 1); - - err = uv_timer_init(loop, &ctx->timer_handle); - if (err < 0) - goto error; - - ctx->timer_handle.flags |= UV__HANDLE_INTERNAL; - uv__handle_unref(&ctx->timer_handle); - - err = uv_fs_stat(loop, &ctx->fs_req, ctx->path, poll_cb); - if (err < 0) - goto error; - - handle->poll_ctx = ctx; - uv__handle_start(handle); - - return 0; - -error: - free(ctx); - return err; -} - - -int uv_fs_poll_stop(uv_fs_poll_t* handle) { - struct poll_ctx* ctx; - - if (!uv__is_active(handle)) - return 0; - - ctx = handle->poll_ctx; - assert(ctx != NULL); - assert(ctx->parent_handle != NULL); - ctx->parent_handle = NULL; - handle->poll_ctx = NULL; - - /* Close the timer if it's active. If it's inactive, there's a stat request - * in progress and poll_cb will take care of the cleanup. - */ - if (uv__is_active(&ctx->timer_handle)) - uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb); - - uv__handle_stop(handle); - - return 0; -} - - -int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buffer, size_t* size) { - struct poll_ctx* ctx; - size_t required_len; - - if (!uv__is_active(handle)) { - *size = 0; - return UV_EINVAL; - } - - ctx = handle->poll_ctx; - assert(ctx != NULL); - - required_len = strlen(ctx->path); - if (required_len > *size) { - *size = required_len; - return UV_ENOBUFS; - } - - memcpy(buffer, ctx->path, required_len); - *size = required_len; - - return 0; -} - - -void uv__fs_poll_close(uv_fs_poll_t* handle) { - uv_fs_poll_stop(handle); -} - - -static void timer_cb(uv_timer_t* timer) { - struct poll_ctx* ctx; - - ctx = container_of(timer, struct poll_ctx, timer_handle); - assert(ctx->parent_handle != NULL); - assert(ctx->parent_handle->poll_ctx == ctx); - ctx->start_time = uv_now(ctx->loop); - - if (uv_fs_stat(ctx->loop, &ctx->fs_req, ctx->path, poll_cb)) - abort(); -} - - -static void poll_cb(uv_fs_t* req) { - uv_stat_t* statbuf; - struct poll_ctx* ctx; - uint64_t interval; - - ctx = container_of(req, struct poll_ctx, fs_req); - - if (ctx->parent_handle == NULL) { /* handle has been stopped or closed */ - uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb); - uv_fs_req_cleanup(req); - return; - } - - if (req->result != 0) { - if (ctx->busy_polling != req->result) { - ctx->poll_cb(ctx->parent_handle, - req->result, - &ctx->statbuf, - &zero_statbuf); - ctx->busy_polling = req->result; - } - goto out; - } - - statbuf = &req->statbuf; - - if (ctx->busy_polling != 0) - if (ctx->busy_polling < 0 || !statbuf_eq(&ctx->statbuf, statbuf)) - ctx->poll_cb(ctx->parent_handle, 0, &ctx->statbuf, statbuf); - - ctx->statbuf = *statbuf; - ctx->busy_polling = 1; - -out: - uv_fs_req_cleanup(req); - - if (ctx->parent_handle == NULL) { /* handle has been stopped by callback */ - uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb); - return; - } - - /* Reschedule timer, subtract the delay from doing the stat(). */ - interval = ctx->interval; - interval -= (uv_now(ctx->loop) - ctx->start_time) % interval; - - if (uv_timer_start(&ctx->timer_handle, timer_cb, interval, 0)) - abort(); -} - - -static void timer_close_cb(uv_handle_t* handle) { - free(container_of(handle, struct poll_ctx, timer_handle)); -} - - -static int statbuf_eq(const uv_stat_t* a, const uv_stat_t* b) { - return a->st_ctim.tv_nsec == b->st_ctim.tv_nsec - && a->st_mtim.tv_nsec == b->st_mtim.tv_nsec - && a->st_birthtim.tv_nsec == b->st_birthtim.tv_nsec - && a->st_ctim.tv_sec == b->st_ctim.tv_sec - && a->st_mtim.tv_sec == b->st_mtim.tv_sec - && a->st_birthtim.tv_sec == b->st_birthtim.tv_sec - && a->st_size == b->st_size - && a->st_mode == b->st_mode - && a->st_uid == b->st_uid - && a->st_gid == b->st_gid - && a->st_ino == b->st_ino - && a->st_dev == b->st_dev - && a->st_flags == b->st_flags - && a->st_gen == b->st_gen; -} - - -#if defined(_WIN32) - -#include "win/internal.h" -#include "win/handle-inl.h" - -void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle) { - assert(handle->flags & UV__HANDLE_CLOSING); - assert(!(handle->flags & UV_HANDLE_CLOSED)); - uv__handle_close(handle); -} - -#endif /* _WIN32 */ diff --git a/libuv/src/heap-inl.h b/libuv/src/heap-inl.h deleted file mode 100644 index 1e2ed60..0000000 --- a/libuv/src/heap-inl.h +++ /dev/null @@ -1,245 +0,0 @@ -/* Copyright (c) 2013, Ben Noordhuis - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef UV_SRC_HEAP_H_ -#define UV_SRC_HEAP_H_ - -#include /* NULL */ - -#if defined(__GNUC__) -# define HEAP_EXPORT(declaration) __attribute__((unused)) static declaration -#else -# define HEAP_EXPORT(declaration) static declaration -#endif - -struct heap_node { - struct heap_node* left; - struct heap_node* right; - struct heap_node* parent; -}; - -/* A binary min heap. The usual properties hold: the root is the lowest - * element in the set, the height of the tree is at most log2(nodes) and - * it's always a complete binary tree. - * - * The heap function try hard to detect corrupted tree nodes at the cost - * of a minor reduction in performance. Compile with -DNDEBUG to disable. - */ -struct heap { - struct heap_node* min; - unsigned int nelts; -}; - -/* Return non-zero if a < b. */ -typedef int (*heap_compare_fn)(const struct heap_node* a, - const struct heap_node* b); - -/* Public functions. */ -HEAP_EXPORT(void heap_init(struct heap* heap)); -HEAP_EXPORT(struct heap_node* heap_min(const struct heap* heap)); -HEAP_EXPORT(void heap_insert(struct heap* heap, - struct heap_node* newnode, - heap_compare_fn less_than)); -HEAP_EXPORT(void heap_remove(struct heap* heap, - struct heap_node* node, - heap_compare_fn less_than)); -HEAP_EXPORT(void heap_dequeue(struct heap* heap, heap_compare_fn less_than)); - -/* Implementation follows. */ - -HEAP_EXPORT(void heap_init(struct heap* heap)) { - heap->min = NULL; - heap->nelts = 0; -} - -HEAP_EXPORT(struct heap_node* heap_min(const struct heap* heap)) { - return heap->min; -} - -/* Swap parent with child. Child moves closer to the root, parent moves away. */ -static void heap_node_swap(struct heap* heap, - struct heap_node* parent, - struct heap_node* child) { - struct heap_node* sibling; - struct heap_node t; - - t = *parent; - *parent = *child; - *child = t; - - parent->parent = child; - if (child->left == child) { - child->left = parent; - sibling = child->right; - } else { - child->right = parent; - sibling = child->left; - } - if (sibling != NULL) - sibling->parent = child; - - if (parent->left != NULL) - parent->left->parent = parent; - if (parent->right != NULL) - parent->right->parent = parent; - - if (child->parent == NULL) - heap->min = child; - else if (child->parent->left == parent) - child->parent->left = child; - else - child->parent->right = child; -} - -HEAP_EXPORT(void heap_insert(struct heap* heap, - struct heap_node* newnode, - heap_compare_fn less_than)) { - struct heap_node** parent; - struct heap_node** child; - unsigned int path; - unsigned int n; - unsigned int k; - - newnode->left = NULL; - newnode->right = NULL; - newnode->parent = NULL; - - /* Calculate the path from the root to the insertion point. This is a min - * heap so we always insert at the left-most free node of the bottom row. - */ - path = 0; - for (k = 0, n = 1 + heap->nelts; n >= 2; k += 1, n /= 2) - path = (path << 1) | (n & 1); - - /* Now traverse the heap using the path we calculated in the previous step. */ - parent = child = &heap->min; - while (k > 0) { - parent = child; - if (path & 1) - child = &(*child)->right; - else - child = &(*child)->left; - path >>= 1; - k -= 1; - } - - /* Insert the new node. */ - newnode->parent = *parent; - *child = newnode; - heap->nelts += 1; - - /* Walk up the tree and check at each node if the heap property holds. - * It's a min heap so parent < child must be true. - */ - while (newnode->parent != NULL && less_than(newnode, newnode->parent)) - heap_node_swap(heap, newnode->parent, newnode); -} - -HEAP_EXPORT(void heap_remove(struct heap* heap, - struct heap_node* node, - heap_compare_fn less_than)) { - struct heap_node* smallest; - struct heap_node** max; - struct heap_node* child; - unsigned int path; - unsigned int k; - unsigned int n; - - if (heap->nelts == 0) - return; - - /* Calculate the path from the min (the root) to the max, the left-most node - * of the bottom row. - */ - path = 0; - for (k = 0, n = heap->nelts; n >= 2; k += 1, n /= 2) - path = (path << 1) | (n & 1); - - /* Now traverse the heap using the path we calculated in the previous step. */ - max = &heap->min; - while (k > 0) { - if (path & 1) - max = &(*max)->right; - else - max = &(*max)->left; - path >>= 1; - k -= 1; - } - - heap->nelts -= 1; - - /* Unlink the max node. */ - child = *max; - *max = NULL; - - if (child == node) { - /* We're removing either the max or the last node in the tree. */ - if (child == heap->min) { - heap->min = NULL; - } - return; - } - - /* Replace the to be deleted node with the max node. */ - child->left = node->left; - child->right = node->right; - child->parent = node->parent; - - if (child->left != NULL) { - child->left->parent = child; - } - - if (child->right != NULL) { - child->right->parent = child; - } - - if (node->parent == NULL) { - heap->min = child; - } else if (node->parent->left == node) { - node->parent->left = child; - } else { - node->parent->right = child; - } - - /* Walk down the subtree and check at each node if the heap property holds. - * It's a min heap so parent < child must be true. If the parent is bigger, - * swap it with the smallest child. - */ - for (;;) { - smallest = child; - if (child->left != NULL && less_than(child->left, smallest)) - smallest = child->left; - if (child->right != NULL && less_than(child->right, smallest)) - smallest = child->right; - if (smallest == child) - break; - heap_node_swap(heap, child, smallest); - } - - /* Walk up the subtree and check that each parent is less than the node - * this is required, because `max` node is not guaranteed to be the - * actual maximum in tree - */ - while (child->parent != NULL && less_than(child, child->parent)) - heap_node_swap(heap, child->parent, child); -} - -HEAP_EXPORT(void heap_dequeue(struct heap* heap, heap_compare_fn less_than)) { - heap_remove(heap, heap->min, less_than); -} - -#undef HEAP_EXPORT - -#endif /* UV_SRC_HEAP_H_ */ diff --git a/libuv/src/inet.c b/libuv/src/inet.c deleted file mode 100644 index c948b2e..0000000 --- a/libuv/src/inet.c +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1996-1999 by Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include - -#if defined(_MSC_VER) && _MSC_VER < 1600 -# include "stdint-msvc2008.h" -#else -# include -#endif - -#include "uv.h" -#include "uv-common.h" - -#define UV__INET_ADDRSTRLEN 16 -#define UV__INET6_ADDRSTRLEN 46 - - -static int inet_ntop4(const unsigned char *src, char *dst, size_t size); -static int inet_ntop6(const unsigned char *src, char *dst, size_t size); -static int inet_pton4(const char *src, unsigned char *dst); -static int inet_pton6(const char *src, unsigned char *dst); - - -int uv_inet_ntop(int af, const void* src, char* dst, size_t size) { - switch (af) { - case AF_INET: - return (inet_ntop4(src, dst, size)); - case AF_INET6: - return (inet_ntop6(src, dst, size)); - default: - return UV_EAFNOSUPPORT; - } - /* NOTREACHED */ -} - - -static int inet_ntop4(const unsigned char *src, char *dst, size_t size) { - static const char fmt[] = "%u.%u.%u.%u"; - char tmp[UV__INET_ADDRSTRLEN]; - int l; - -#ifndef _WIN32 - l = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]); -#else - l = _snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]); -#endif - if (l <= 0 || (size_t) l >= size) { - return UV_ENOSPC; - } - strncpy(dst, tmp, size); - dst[size - 1] = '\0'; - return 0; -} - - -static int inet_ntop6(const unsigned char *src, char *dst, size_t size) { - /* - * Note that int32_t and int16_t need only be "at least" large enough - * to contain a value of the specified size. On some systems, like - * Crays, there is no such thing as an integer variable with 16 bits. - * Keep this in mind if you think this function should have been coded - * to use pointer overlays. All the world's not a VAX. - */ - char tmp[UV__INET6_ADDRSTRLEN], *tp; - struct { int base, len; } best, cur; - unsigned int words[sizeof(struct in6_addr) / sizeof(uint16_t)]; - int i; - - /* - * Preprocess: - * Copy the input (bytewise) array into a wordwise array. - * Find the longest run of 0x00's in src[] for :: shorthanding. - */ - memset(words, '\0', sizeof words); - for (i = 0; i < (int) sizeof(struct in6_addr); i++) - words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); - best.base = -1; - best.len = 0; - cur.base = -1; - cur.len = 0; - for (i = 0; i < (int) ARRAY_SIZE(words); i++) { - if (words[i] == 0) { - if (cur.base == -1) - cur.base = i, cur.len = 1; - else - cur.len++; - } else { - if (cur.base != -1) { - if (best.base == -1 || cur.len > best.len) - best = cur; - cur.base = -1; - } - } - } - if (cur.base != -1) { - if (best.base == -1 || cur.len > best.len) - best = cur; - } - if (best.base != -1 && best.len < 2) - best.base = -1; - - /* - * Format the result. - */ - tp = tmp; - for (i = 0; i < (int) ARRAY_SIZE(words); i++) { - /* Are we inside the best run of 0x00's? */ - if (best.base != -1 && i >= best.base && - i < (best.base + best.len)) { - if (i == best.base) - *tp++ = ':'; - continue; - } - /* Are we following an initial run of 0x00s or any real hex? */ - if (i != 0) - *tp++ = ':'; - /* Is this address an encapsulated IPv4? */ - if (i == 6 && best.base == 0 && (best.len == 6 || - (best.len == 7 && words[7] != 0x0001) || - (best.len == 5 && words[5] == 0xffff))) { - int err = inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)); - if (err) - return err; - tp += strlen(tp); - break; - } - tp += sprintf(tp, "%x", words[i]); - } - /* Was it a trailing run of 0x00's? */ - if (best.base != -1 && (best.base + best.len) == ARRAY_SIZE(words)) - *tp++ = ':'; - *tp++ = '\0'; - - /* - * Check for overflow, copy, and we're done. - */ - if ((size_t)(tp - tmp) > size) { - return UV_ENOSPC; - } - strcpy(dst, tmp); - return 0; -} - - -int uv_inet_pton(int af, const char* src, void* dst) { - if (src == NULL || dst == NULL) - return UV_EINVAL; - - switch (af) { - case AF_INET: - return (inet_pton4(src, dst)); - case AF_INET6: { - int len; - char tmp[UV__INET6_ADDRSTRLEN], *s, *p; - s = (char*) src; - p = strchr(src, '%'); - if (p != NULL) { - s = tmp; - len = p - src; - if (len > UV__INET6_ADDRSTRLEN-1) - return UV_EINVAL; - memcpy(s, src, len); - s[len] = '\0'; - } - return inet_pton6(s, dst); - } - default: - return UV_EAFNOSUPPORT; - } - /* NOTREACHED */ -} - - -static int inet_pton4(const char *src, unsigned char *dst) { - static const char digits[] = "0123456789"; - int saw_digit, octets, ch; - unsigned char tmp[sizeof(struct in_addr)], *tp; - - saw_digit = 0; - octets = 0; - *(tp = tmp) = 0; - while ((ch = *src++) != '\0') { - const char *pch; - - if ((pch = strchr(digits, ch)) != NULL) { - unsigned int nw = *tp * 10 + (pch - digits); - - if (saw_digit && *tp == 0) - return UV_EINVAL; - if (nw > 255) - return UV_EINVAL; - *tp = nw; - if (!saw_digit) { - if (++octets > 4) - return UV_EINVAL; - saw_digit = 1; - } - } else if (ch == '.' && saw_digit) { - if (octets == 4) - return UV_EINVAL; - *++tp = 0; - saw_digit = 0; - } else - return UV_EINVAL; - } - if (octets < 4) - return UV_EINVAL; - memcpy(dst, tmp, sizeof(struct in_addr)); - return 0; -} - - -static int inet_pton6(const char *src, unsigned char *dst) { - static const char xdigits_l[] = "0123456789abcdef", - xdigits_u[] = "0123456789ABCDEF"; - unsigned char tmp[sizeof(struct in6_addr)], *tp, *endp, *colonp; - const char *xdigits, *curtok; - int ch, seen_xdigits; - unsigned int val; - - memset((tp = tmp), '\0', sizeof tmp); - endp = tp + sizeof tmp; - colonp = NULL; - /* Leading :: requires some special handling. */ - if (*src == ':') - if (*++src != ':') - return UV_EINVAL; - curtok = src; - seen_xdigits = 0; - val = 0; - while ((ch = *src++) != '\0') { - const char *pch; - - if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) - pch = strchr((xdigits = xdigits_u), ch); - if (pch != NULL) { - val <<= 4; - val |= (pch - xdigits); - if (++seen_xdigits > 4) - return UV_EINVAL; - continue; - } - if (ch == ':') { - curtok = src; - if (!seen_xdigits) { - if (colonp) - return UV_EINVAL; - colonp = tp; - continue; - } else if (*src == '\0') { - return UV_EINVAL; - } - if (tp + sizeof(uint16_t) > endp) - return UV_EINVAL; - *tp++ = (unsigned char) (val >> 8) & 0xff; - *tp++ = (unsigned char) val & 0xff; - seen_xdigits = 0; - val = 0; - continue; - } - if (ch == '.' && ((tp + sizeof(struct in_addr)) <= endp)) { - int err = inet_pton4(curtok, tp); - if (err == 0) { - tp += sizeof(struct in_addr); - seen_xdigits = 0; - break; /*%< '\\0' was seen by inet_pton4(). */ - } - } - return UV_EINVAL; - } - if (seen_xdigits) { - if (tp + sizeof(uint16_t) > endp) - return UV_EINVAL; - *tp++ = (unsigned char) (val >> 8) & 0xff; - *tp++ = (unsigned char) val & 0xff; - } - if (colonp != NULL) { - /* - * Since some memmove()'s erroneously fail to handle - * overlapping regions, we'll do the shift by hand. - */ - const int n = tp - colonp; - int i; - - if (tp == endp) - return UV_EINVAL; - for (i = 1; i <= n; i++) { - endp[- i] = colonp[n - i]; - colonp[n - i] = 0; - } - tp = endp; - } - if (tp != endp) - return UV_EINVAL; - memcpy(dst, tmp, sizeof tmp); - return 0; -} diff --git a/libuv/src/queue.h b/libuv/src/queue.h deleted file mode 100644 index fe02b45..0000000 --- a/libuv/src/queue.h +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright (c) 2013, Ben Noordhuis - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef QUEUE_H_ -#define QUEUE_H_ - -typedef void *QUEUE[2]; - -/* Private macros. */ -#define QUEUE_NEXT(q) (*(QUEUE **) &((*(q))[0])) -#define QUEUE_PREV(q) (*(QUEUE **) &((*(q))[1])) -#define QUEUE_PREV_NEXT(q) (QUEUE_NEXT(QUEUE_PREV(q))) -#define QUEUE_NEXT_PREV(q) (QUEUE_PREV(QUEUE_NEXT(q))) - -/* Public macros. */ -#define QUEUE_DATA(ptr, type, field) \ - ((type *) ((char *) (ptr) - ((char *) &((type *) 0)->field))) - -#define QUEUE_FOREACH(q, h) \ - for ((q) = QUEUE_NEXT(h); (q) != (h); (q) = QUEUE_NEXT(q)) - -#define QUEUE_EMPTY(q) \ - ((const QUEUE *) (q) == (const QUEUE *) QUEUE_NEXT(q)) - -#define QUEUE_HEAD(q) \ - (QUEUE_NEXT(q)) - -#define QUEUE_INIT(q) \ - do { \ - QUEUE_NEXT(q) = (q); \ - QUEUE_PREV(q) = (q); \ - } \ - while (0) - -#define QUEUE_ADD(h, n) \ - do { \ - QUEUE_PREV_NEXT(h) = QUEUE_NEXT(n); \ - QUEUE_NEXT_PREV(n) = QUEUE_PREV(h); \ - QUEUE_PREV(h) = QUEUE_PREV(n); \ - QUEUE_PREV_NEXT(h) = (h); \ - } \ - while (0) - -#define QUEUE_SPLIT(h, q, n) \ - do { \ - QUEUE_PREV(n) = QUEUE_PREV(h); \ - QUEUE_PREV_NEXT(n) = (n); \ - QUEUE_NEXT(n) = (q); \ - QUEUE_PREV(h) = QUEUE_PREV(q); \ - QUEUE_PREV_NEXT(h) = (h); \ - QUEUE_PREV(q) = (n); \ - } \ - while (0) - -#define QUEUE_INSERT_HEAD(h, q) \ - do { \ - QUEUE_NEXT(q) = QUEUE_NEXT(h); \ - QUEUE_PREV(q) = (h); \ - QUEUE_NEXT_PREV(q) = (q); \ - QUEUE_NEXT(h) = (q); \ - } \ - while (0) - -#define QUEUE_INSERT_TAIL(h, q) \ - do { \ - QUEUE_NEXT(q) = (h); \ - QUEUE_PREV(q) = QUEUE_PREV(h); \ - QUEUE_PREV_NEXT(q) = (q); \ - QUEUE_PREV(h) = (q); \ - } \ - while (0) - -#define QUEUE_REMOVE(q) \ - do { \ - QUEUE_PREV_NEXT(q) = QUEUE_NEXT(q); \ - QUEUE_NEXT_PREV(q) = QUEUE_PREV(q); \ - } \ - while (0) - -#endif /* QUEUE_H_ */ diff --git a/libuv/src/threadpool.c b/libuv/src/threadpool.c deleted file mode 100644 index 33890f0..0000000 --- a/libuv/src/threadpool.c +++ /dev/null @@ -1,303 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv-common.h" - -#if !defined(_WIN32) -# include "unix/internal.h" -#else -# include "win/req-inl.h" -/* TODO(saghul): unify internal req functions */ -static void uv__req_init(uv_loop_t* loop, - uv_req_t* req, - uv_req_type type) { - uv_req_init(loop, req); - req->type = type; - uv__req_register(loop, req); -} -# define uv__req_init(loop, req, type) \ - uv__req_init((loop), (uv_req_t*)(req), (type)) -#endif - -#include - -#define MAX_THREADPOOL_SIZE 128 - -static uv_once_t once = UV_ONCE_INIT; -static uv_cond_t cond; -static uv_mutex_t mutex; -static unsigned int nthreads; -static uv_thread_t* threads; -static uv_thread_t default_threads[4]; -static QUEUE exit_message; -static QUEUE wq; -static volatile int initialized; - - -static void uv__cancelled(struct uv__work* w) { - abort(); -} - - -/* To avoid deadlock with uv_cancel() it's crucial that the worker - * never holds the global mutex and the loop-local mutex at the same time. - */ -static void worker(void* arg) { - struct uv__work* w; - QUEUE* q; - - (void) arg; - - for (;;) { - uv_mutex_lock(&mutex); - - while (QUEUE_EMPTY(&wq)) - uv_cond_wait(&cond, &mutex); - - q = QUEUE_HEAD(&wq); - - if (q == &exit_message) - uv_cond_signal(&cond); - else { - QUEUE_REMOVE(q); - QUEUE_INIT(q); /* Signal uv_cancel() that the work req is - executing. */ - } - - uv_mutex_unlock(&mutex); - - if (q == &exit_message) - break; - - w = QUEUE_DATA(q, struct uv__work, wq); - w->work(w); - - uv_mutex_lock(&w->loop->wq_mutex); - w->work = NULL; /* Signal uv_cancel() that the work req is done - executing. */ - QUEUE_INSERT_TAIL(&w->loop->wq, &w->wq); - uv_async_send(&w->loop->wq_async); - uv_mutex_unlock(&w->loop->wq_mutex); - } -} - - -static void post(QUEUE* q) { - uv_mutex_lock(&mutex); - QUEUE_INSERT_TAIL(&wq, q); - uv_cond_signal(&cond); - uv_mutex_unlock(&mutex); -} - - -#ifndef _WIN32 -UV_DESTRUCTOR(static void cleanup(void)) { - unsigned int i; - - if (initialized == 0) - return; - - post(&exit_message); - - for (i = 0; i < nthreads; i++) - if (uv_thread_join(threads + i)) - abort(); - - if (threads != default_threads) - free(threads); - - uv_mutex_destroy(&mutex); - uv_cond_destroy(&cond); - - threads = NULL; - nthreads = 0; - initialized = 0; -} -#endif - - -static void init_once(void) { - unsigned int i; - const char* val; - - nthreads = ARRAY_SIZE(default_threads); - val = getenv("UV_THREADPOOL_SIZE"); - if (val != NULL) - nthreads = atoi(val); - if (nthreads == 0) - nthreads = 1; - if (nthreads > MAX_THREADPOOL_SIZE) - nthreads = MAX_THREADPOOL_SIZE; - - threads = default_threads; - if (nthreads > ARRAY_SIZE(default_threads)) { - threads = malloc(nthreads * sizeof(threads[0])); - if (threads == NULL) { - nthreads = ARRAY_SIZE(default_threads); - threads = default_threads; - } - } - - if (uv_cond_init(&cond)) - abort(); - - if (uv_mutex_init(&mutex)) - abort(); - - QUEUE_INIT(&wq); - - for (i = 0; i < nthreads; i++) - if (uv_thread_create(threads + i, worker, NULL)) - abort(); - - initialized = 1; -} - - -void uv__work_submit(uv_loop_t* loop, - struct uv__work* w, - void (*work)(struct uv__work* w), - void (*done)(struct uv__work* w, int status)) { - uv_once(&once, init_once); - w->loop = loop; - w->work = work; - w->done = done; - post(&w->wq); -} - - -static int uv__work_cancel(uv_loop_t* loop, uv_req_t* req, struct uv__work* w) { - int cancelled; - - uv_mutex_lock(&mutex); - uv_mutex_lock(&w->loop->wq_mutex); - - cancelled = !QUEUE_EMPTY(&w->wq) && w->work != NULL; - if (cancelled) - QUEUE_REMOVE(&w->wq); - - uv_mutex_unlock(&w->loop->wq_mutex); - uv_mutex_unlock(&mutex); - - if (!cancelled) - return UV_EBUSY; - - w->work = uv__cancelled; - uv_mutex_lock(&loop->wq_mutex); - QUEUE_INSERT_TAIL(&loop->wq, &w->wq); - uv_async_send(&loop->wq_async); - uv_mutex_unlock(&loop->wq_mutex); - - return 0; -} - - -void uv__work_done(uv_async_t* handle) { - struct uv__work* w; - uv_loop_t* loop; - QUEUE* q; - QUEUE wq; - int err; - - loop = container_of(handle, uv_loop_t, wq_async); - QUEUE_INIT(&wq); - - uv_mutex_lock(&loop->wq_mutex); - if (!QUEUE_EMPTY(&loop->wq)) { - q = QUEUE_HEAD(&loop->wq); - QUEUE_SPLIT(&loop->wq, q, &wq); - } - uv_mutex_unlock(&loop->wq_mutex); - - while (!QUEUE_EMPTY(&wq)) { - q = QUEUE_HEAD(&wq); - QUEUE_REMOVE(q); - - w = container_of(q, struct uv__work, wq); - err = (w->work == uv__cancelled) ? UV_ECANCELED : 0; - w->done(w, err); - } -} - - -static void uv__queue_work(struct uv__work* w) { - uv_work_t* req = container_of(w, uv_work_t, work_req); - - req->work_cb(req); -} - - -static void uv__queue_done(struct uv__work* w, int err) { - uv_work_t* req; - - req = container_of(w, uv_work_t, work_req); - uv__req_unregister(req->loop, req); - - if (req->after_work_cb == NULL) - return; - - req->after_work_cb(req, err); -} - - -int uv_queue_work(uv_loop_t* loop, - uv_work_t* req, - uv_work_cb work_cb, - uv_after_work_cb after_work_cb) { - if (work_cb == NULL) - return UV_EINVAL; - - uv__req_init(loop, req, UV_WORK); - req->loop = loop; - req->work_cb = work_cb; - req->after_work_cb = after_work_cb; - uv__work_submit(loop, &req->work_req, uv__queue_work, uv__queue_done); - return 0; -} - - -int uv_cancel(uv_req_t* req) { - struct uv__work* wreq; - uv_loop_t* loop; - - switch (req->type) { - case UV_FS: - loop = ((uv_fs_t*) req)->loop; - wreq = &((uv_fs_t*) req)->work_req; - break; - case UV_GETADDRINFO: - loop = ((uv_getaddrinfo_t*) req)->loop; - wreq = &((uv_getaddrinfo_t*) req)->work_req; - break; - case UV_GETNAMEINFO: - loop = ((uv_getnameinfo_t*) req)->loop; - wreq = &((uv_getnameinfo_t*) req)->work_req; - break; - case UV_WORK: - loop = ((uv_work_t*) req)->loop; - wreq = &((uv_work_t*) req)->work_req; - break; - default: - return UV_EINVAL; - } - - return uv__work_cancel(loop, req, wreq); -} diff --git a/libuv/src/unix/aix.c b/libuv/src/unix/aix.c deleted file mode 100644 index ec800c7..0000000 --- a/libuv/src/unix/aix.c +++ /dev/null @@ -1,1233 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#define RDWR_BUF_SIZE 4096 -#define EQ(a,b) (strcmp(a,b) == 0) - -int uv__platform_loop_init(uv_loop_t* loop) { - loop->fs_fd = -1; - - /* Passing maxfd of -1 should mean the limit is determined - * by the user's ulimit or the global limit as per the doc */ - loop->backend_fd = pollset_create(-1); - - if (loop->backend_fd == -1) - return -1; - - return 0; -} - - -void uv__platform_loop_delete(uv_loop_t* loop) { - if (loop->fs_fd != -1) { - uv__close(loop->fs_fd); - loop->fs_fd = -1; - } - - if (loop->backend_fd != -1) { - pollset_destroy(loop->backend_fd); - loop->backend_fd = -1; - } -} - - -void uv__io_poll(uv_loop_t* loop, int timeout) { - struct pollfd events[1024]; - struct pollfd pqry; - struct pollfd* pe; - struct poll_ctl pc; - QUEUE* q; - uv__io_t* w; - uint64_t base; - uint64_t diff; - int nevents; - int count; - int nfds; - int i; - int rc; - int add_failed; - - if (loop->nfds == 0) { - assert(QUEUE_EMPTY(&loop->watcher_queue)); - return; - } - - while (!QUEUE_EMPTY(&loop->watcher_queue)) { - q = QUEUE_HEAD(&loop->watcher_queue); - QUEUE_REMOVE(q); - QUEUE_INIT(q); - - w = QUEUE_DATA(q, uv__io_t, watcher_queue); - assert(w->pevents != 0); - assert(w->fd >= 0); - assert(w->fd < (int) loop->nwatchers); - - pc.events = w->pevents; - pc.fd = w->fd; - - add_failed = 0; - if (w->events == 0) { - pc.cmd = PS_ADD; - if (pollset_ctl(loop->backend_fd, &pc, 1)) { - if (errno != EINVAL) { - assert(0 && "Failed to add file descriptor (pc.fd) to pollset"); - abort(); - } - /* Check if the fd is already in the pollset */ - pqry.fd = pc.fd; - rc = pollset_query(loop->backend_fd, &pqry); - switch (rc) { - case -1: - assert(0 && "Failed to query pollset for file descriptor"); - abort(); - case 0: - assert(0 && "Pollset does not contain file descriptor"); - abort(); - } - /* If we got here then the pollset already contained the file descriptor even though - * we didn't think it should. This probably shouldn't happen, but we can continue. */ - add_failed = 1; - } - } - if (w->events != 0 || add_failed) { - /* Modify, potentially removing events -- need to delete then add. - * Could maybe mod if we knew for sure no events are removed, but - * content of w->events is handled above as not reliable (falls back) - * so may require a pollset_query() which would have to be pretty cheap - * compared to a PS_DELETE to be worth optimizing. Alternatively, could - * lazily remove events, squelching them in the mean time. */ - pc.cmd = PS_DELETE; - if (pollset_ctl(loop->backend_fd, &pc, 1)) { - assert(0 && "Failed to delete file descriptor (pc.fd) from pollset"); - abort(); - } - pc.cmd = PS_ADD; - if (pollset_ctl(loop->backend_fd, &pc, 1)) { - assert(0 && "Failed to add file descriptor (pc.fd) to pollset"); - abort(); - } - } - - w->events = w->pevents; - } - - assert(timeout >= -1); - base = loop->time; - count = 48; /* Benchmarks suggest this gives the best throughput. */ - - for (;;) { - nfds = pollset_poll(loop->backend_fd, - events, - ARRAY_SIZE(events), - timeout); - - /* Update loop->time unconditionally. It's tempting to skip the update when - * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the - * operating system didn't reschedule our process while in the syscall. - */ - SAVE_ERRNO(uv__update_time(loop)); - - if (nfds == 0) { - assert(timeout != -1); - return; - } - - if (nfds == -1) { - if (errno != EINTR) { - abort(); - } - - if (timeout == -1) - continue; - - if (timeout == 0) - return; - - /* Interrupted by a signal. Update timeout and poll again. */ - goto update_timeout; - } - - nevents = 0; - - assert(loop->watchers != NULL); - loop->watchers[loop->nwatchers] = (void*) events; - loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds; - - for (i = 0; i < nfds; i++) { - pe = events + i; - pc.cmd = PS_DELETE; - pc.fd = pe->fd; - - /* Skip invalidated events, see uv__platform_invalidate_fd */ - if (pc.fd == -1) - continue; - - assert(pc.fd >= 0); - assert((unsigned) pc.fd < loop->nwatchers); - - w = loop->watchers[pc.fd]; - - if (w == NULL) { - /* File descriptor that we've stopped watching, disarm it. - * - * Ignore all errors because we may be racing with another thread - * when the file descriptor is closed. - */ - pollset_ctl(loop->backend_fd, &pc, 1); - continue; - } - - w->cb(loop, w, pe->revents); - nevents++; - } - - loop->watchers[loop->nwatchers] = NULL; - loop->watchers[loop->nwatchers + 1] = NULL; - - if (nevents != 0) { - if (nfds == ARRAY_SIZE(events) && --count != 0) { - /* Poll for more events but don't block this time. */ - timeout = 0; - continue; - } - return; - } - - if (timeout == 0) - return; - - if (timeout == -1) - continue; - -update_timeout: - assert(timeout > 0); - - diff = loop->time - base; - if (diff >= (uint64_t) timeout) - return; - - timeout -= diff; - } -} - - -uint64_t uv__hrtime(uv_clocktype_t type) { - uint64_t G = 1000000000; - timebasestruct_t t; - read_wall_time(&t, TIMEBASE_SZ); - time_base_to_time(&t, TIMEBASE_SZ); - return (uint64_t) t.tb_high * G + t.tb_low; -} - - -/* - * We could use a static buffer for the path manipulations that we need outside - * of the function, but this function could be called by multiple consumers and - * we don't want to potentially create a race condition in the use of snprintf. - * There is no direct way of getting the exe path in AIX - either through /procfs - * or through some libc APIs. The below approach is to parse the argv[0]'s pattern - * and use it in conjunction with PATH environment variable to craft one. - */ -int uv_exepath(char* buffer, size_t* size) { - ssize_t res; - char cwd[PATH_MAX], cwdl[PATH_MAX]; - char symlink[PATH_MAX], temp_buffer[PATH_MAX]; - char pp[64]; - struct psinfo ps; - int fd; - char **argv; - - if (buffer == NULL || size == NULL || *size == 0) - return -EINVAL; - - snprintf(pp, sizeof(pp), "/proc/%lu/psinfo", (unsigned long) getpid()); - - fd = open(pp, O_RDONLY); - if (fd < 0) - return fd; - - res = read(fd, &ps, sizeof(ps)); - uv__close(fd); - if (res < 0) - return res; - - if (ps.pr_argv == 0) - return -EINVAL; - - argv = (char **) *((char ***) (intptr_t) ps.pr_argv); - - if ((argv == NULL) || (argv[0] == NULL)) - return -EINVAL; - - /* - * Three possibilities for argv[0]: - * i) an absolute path such as: /home/user/myprojects/nodejs/node - * ii) a relative path such as: ./node or ./myprojects/nodejs/node - * iii) a bare filename such as "node", after exporting PATH variable - * to its location. - */ - - /* case #1, absolute path. */ - if (argv[0][0] == '/') { - snprintf(symlink, PATH_MAX-1, "%s", argv[0]); - - /* This could or could not be a symlink. */ - res = readlink(symlink, temp_buffer, PATH_MAX-1); - - /* if readlink fails, it is a normal file just copy symlink to the - * output buffer. - */ - if (res < 0) { - assert(*size > strlen(symlink)); - strcpy(buffer, symlink); - - /* If it is a link, the resolved filename is again a relative path, - * make it absolute. - */ - } else { - assert(*size > (strlen(symlink) + 1 + strlen(temp_buffer))); - snprintf(buffer, *size-1, "%s/%s", dirname(symlink), temp_buffer); - } - *size = strlen(buffer); - return 0; - - /* case #2, relative path with usage of '.' */ - } else if (argv[0][0] == '.') { - char *relative = strchr(argv[0], '/'); - if (relative == NULL) - return -EINVAL; - - /* Get the current working directory to resolve the relative path. */ - snprintf(cwd, PATH_MAX-1, "/proc/%lu/cwd", (unsigned long) getpid()); - - /* This is always a symlink, resolve it. */ - res = readlink(cwd, cwdl, sizeof(cwdl) - 1); - if (res < 0) - return -errno; - - snprintf(symlink, PATH_MAX-1, "%s%s", cwdl, relative + 1); - - res = readlink(symlink, temp_buffer, PATH_MAX-1); - if (res < 0) { - assert(*size > strlen(symlink)); - strcpy(buffer, symlink); - } else { - assert(*size > (strlen(symlink) + 1 + strlen(temp_buffer))); - snprintf(buffer, *size-1, "%s/%s", dirname(symlink), temp_buffer); - } - *size = strlen(buffer); - return 0; - - /* case #3, relative path without usage of '.', such as invocations in Node test suite. */ - } else if (strchr(argv[0], '/') != NULL) { - /* Get the current working directory to resolve the relative path. */ - snprintf(cwd, PATH_MAX-1, "/proc/%lu/cwd", (unsigned long) getpid()); - - /* This is always a symlink, resolve it. */ - res = readlink(cwd, cwdl, sizeof(cwdl) - 1); - if (res < 0) - return -errno; - - snprintf(symlink, PATH_MAX-1, "%s%s", cwdl, argv[0]); - - res = readlink(symlink, temp_buffer, PATH_MAX-1); - if (res < 0) { - assert(*size > strlen(symlink)); - strcpy(buffer, symlink); - } else { - assert(*size > (strlen(symlink) + 1 + strlen(temp_buffer))); - snprintf(buffer, *size-1, "%s/%s", dirname(symlink), temp_buffer); - } - *size = strlen(buffer); - return 0; - /* Usage of absolute filename with location exported in PATH */ - } else { - char clonedpath[8192]; /* assume 8k buffer will fit PATH */ - char *token = NULL; - struct stat statstruct; - - /* Get the paths. */ - char *path = getenv("PATH"); - if(sizeof(clonedpath) <= strlen(path)) - return -EINVAL; - - /* Get a local copy. */ - strcpy(clonedpath, path); - - /* Tokenize. */ - token = strtok(clonedpath, ":"); - - /* Get current working directory. (may be required in the loop). */ - snprintf(cwd, PATH_MAX-1, "/proc/%lu/cwd", (unsigned long) getpid()); - res = readlink(cwd, cwdl, sizeof(cwdl) - 1); - if (res < 0) - return -errno; - /* Run through the tokens, append our executable file name with each, - * and see which one succeeds. Exit on first match. */ - while(token != NULL) { - if (token[0] == '.') { - /* Path contains a token relative to current directory. */ - char *relative = strchr(token, '/'); - if (relative != NULL) - /* A path which is not current directory. */ - snprintf(symlink, PATH_MAX-1, "%s%s/%s", cwdl, relative+1, ps.pr_fname); - else - snprintf(symlink, PATH_MAX-1, "%s%s", cwdl, ps.pr_fname); - if (stat(symlink, &statstruct) != -1) { - /* File exists. Resolve if it is a link. */ - res = readlink(symlink, temp_buffer, PATH_MAX-1); - if (res < 0) { - assert(*size > strlen(symlink)); - strcpy(buffer, symlink); - } else { - assert(*size > (strlen(symlink) + 1 + strlen(temp_buffer))); - snprintf(buffer, *size-1, "%s/%s", dirname(symlink), temp_buffer); - } - *size = strlen(buffer); - return 0; - } - - /* Absolute path names. */ - } else { - snprintf(symlink, PATH_MAX-1, "%s/%s", token, ps.pr_fname); - if (stat(symlink, &statstruct) != -1) { - res = readlink(symlink, temp_buffer, PATH_MAX-1); - if (res < 0) { - assert(*size > strlen(symlink)); - strcpy(buffer, symlink); - } else { - assert(*size > (strlen(symlink) + 1 + strlen(temp_buffer))); - snprintf(buffer, *size-1, "%s/%s", dirname(symlink), temp_buffer); - } - *size = strlen(buffer); - return 0; - } - } - token = strtok(NULL, ":"); - } - /* Out of tokens (path entries), and no match found */ - return -EINVAL; - } -} - - -uint64_t uv_get_free_memory(void) { - perfstat_memory_total_t mem_total; - int result = perfstat_memory_total(NULL, &mem_total, sizeof(mem_total), 1); - if (result == -1) { - return 0; - } - return mem_total.real_free * 4096; -} - - -uint64_t uv_get_total_memory(void) { - perfstat_memory_total_t mem_total; - int result = perfstat_memory_total(NULL, &mem_total, sizeof(mem_total), 1); - if (result == -1) { - return 0; - } - return mem_total.real_total * 4096; -} - - -void uv_loadavg(double avg[3]) { - perfstat_cpu_total_t ps_total; - int result = perfstat_cpu_total(NULL, &ps_total, sizeof(ps_total), 1); - if (result == -1) { - avg[0] = 0.; avg[1] = 0.; avg[2] = 0.; - return; - } - avg[0] = ps_total.loadavg[0] / (double)(1 << SBITS); - avg[1] = ps_total.loadavg[1] / (double)(1 << SBITS); - avg[2] = ps_total.loadavg[2] / (double)(1 << SBITS); -} - - -static char *uv__rawname(char *cp) { - static char rawbuf[FILENAME_MAX+1]; - char *dp = rindex(cp, '/'); - - if (dp == 0) - return 0; - - *dp = 0; - strcpy(rawbuf, cp); - *dp = '/'; - strcat(rawbuf, "/r"); - strcat(rawbuf, dp+1); - return rawbuf; -} - - -/* - * Determine whether given pathname is a directory - * Returns 0 if the path is a directory, -1 if not - * - * Note: Opportunity here for more detailed error information but - * that requires changing callers of this function as well - */ -static int uv__path_is_a_directory(char* filename) { - struct stat statbuf; - - if (stat(filename, &statbuf) < 0) - return -1; /* failed: not a directory, assume it is a file */ - - if (statbuf.st_type == VDIR) - return 0; - - return -1; -} - - -/* - * Check whether AHAFS is mounted. - * Returns 0 if AHAFS is mounted, or an error code < 0 on failure - */ -static int uv__is_ahafs_mounted(void){ - int rv, i = 2; - struct vmount *p; - int size_multiplier = 10; - size_t siz = sizeof(struct vmount)*size_multiplier; - struct vmount *vmt; - const char *dev = "/aha"; - char *obj, *stub; - - p = malloc(siz); - if (p == NULL) - return -errno; - - /* Retrieve all mounted filesystems */ - rv = mntctl(MCTL_QUERY, siz, (char*)p); - if (rv < 0) - return -errno; - if (rv == 0) { - /* buffer was not large enough, reallocate to correct size */ - siz = *(int*)p; - free(p); - p = malloc(siz); - if (p == NULL) - return -errno; - rv = mntctl(MCTL_QUERY, siz, (char*)p); - if (rv < 0) - return -errno; - } - - /* Look for dev in filesystems mount info */ - for(vmt = p, i = 0; i < rv; i++) { - obj = vmt2dataptr(vmt, VMT_OBJECT); /* device */ - stub = vmt2dataptr(vmt, VMT_STUB); /* mount point */ - - if (EQ(obj, dev) || EQ(uv__rawname(obj), dev) || EQ(stub, dev)) { - free(p); /* Found a match */ - return 0; - } - vmt = (struct vmount *) ((char *) vmt + vmt->vmt_length); - } - - /* /aha is required for monitoring filesystem changes */ - return -1; -} - -/* - * Recursive call to mkdir() to create intermediate folders, if any - * Returns code from mkdir call - */ -static int uv__makedir_p(const char *dir) { - char tmp[256]; - char *p = NULL; - size_t len; - int err; - - snprintf(tmp, sizeof(tmp),"%s",dir); - len = strlen(tmp); - if (tmp[len - 1] == '/') - tmp[len - 1] = 0; - for (p = tmp + 1; *p; p++) { - if (*p == '/') { - *p = 0; - err = mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); - if(err != 0) - return err; - *p = '/'; - } - } - return mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); -} - -/* - * Creates necessary subdirectories in the AIX Event Infrastructure - * file system for monitoring the object specified. - * Returns code from mkdir call - */ -static int uv__make_subdirs_p(const char *filename) { - char cmd[2048]; - char *p; - int rc = 0; - - /* Strip off the monitor file name */ - p = strrchr(filename, '/'); - - if (p == NULL) - return 0; - - if (uv__path_is_a_directory((char*)filename) == 0) { - sprintf(cmd, "/aha/fs/modDir.monFactory"); - } else { - sprintf(cmd, "/aha/fs/modFile.monFactory"); - } - - strncat(cmd, filename, (p - filename)); - rc = uv__makedir_p(cmd); - - if (rc == -1 && errno != EEXIST){ - return -errno; - } - - return rc; -} - - -/* - * Checks if /aha is mounted, then proceeds to set up the monitoring - * objects for the specified file. - * Returns 0 on success, or an error code < 0 on failure - */ -static int uv__setup_ahafs(const char* filename, int *fd) { - int rc = 0; - char mon_file_write_string[RDWR_BUF_SIZE]; - char mon_file[PATH_MAX]; - int file_is_directory = 0; /* -1 == NO, 0 == YES */ - - /* Create monitor file name for object */ - file_is_directory = uv__path_is_a_directory((char*)filename); - - if (file_is_directory == 0) - sprintf(mon_file, "/aha/fs/modDir.monFactory"); - else - sprintf(mon_file, "/aha/fs/modFile.monFactory"); - - if ((strlen(mon_file) + strlen(filename) + 5) > PATH_MAX) - return -ENAMETOOLONG; - - /* Make the necessary subdirectories for the monitor file */ - rc = uv__make_subdirs_p(filename); - if (rc == -1 && errno != EEXIST) - return rc; - - strcat(mon_file, filename); - strcat(mon_file, ".mon"); - - *fd = 0; errno = 0; - - /* Open the monitor file, creating it if necessary */ - *fd = open(mon_file, O_CREAT|O_RDWR); - if (*fd < 0) - return -errno; - - /* Write out the monitoring specifications. - * In this case, we are monitoring for a state change event type - * CHANGED=YES - * We will be waiting in select call, rather than a read: - * WAIT_TYPE=WAIT_IN_SELECT - * We only want minimal information for files: - * INFO_LVL=1 - * For directories, we want more information to track what file - * caused the change - * INFO_LVL=2 - */ - - if (file_is_directory == 0) - sprintf(mon_file_write_string, "CHANGED=YES;WAIT_TYPE=WAIT_IN_SELECT;INFO_LVL=2"); - else - sprintf(mon_file_write_string, "CHANGED=YES;WAIT_TYPE=WAIT_IN_SELECT;INFO_LVL=1"); - - rc = write(*fd, mon_file_write_string, strlen(mon_file_write_string)+1); - if (rc < 0) - return -errno; - - return 0; -} - -/* - * Skips a specified number of lines in the buffer passed in. - * Walks the buffer pointed to by p and attempts to skip n lines. - * Returns the total number of lines skipped - */ -static int uv__skip_lines(char **p, int n) { - int lines = 0; - - while(n > 0) { - *p = strchr(*p, '\n'); - if (!p) - return lines; - - (*p)++; - n--; - lines++; - } - return lines; -} - - -/* - * Parse the event occurrence data to figure out what event just occurred - * and take proper action. - * - * The buf is a pointer to the buffer containing the event occurrence data - * Returns 0 on success, -1 if unrecoverable error in parsing - * - */ -static int uv__parse_data(char *buf, int *events, uv_fs_event_t* handle) { - int evp_rc, i; - char *p; - char filename[PATH_MAX]; /* To be used when handling directories */ - - p = buf; - *events = 0; - - /* Clean the filename buffer*/ - for(i = 0; i < PATH_MAX; i++) { - filename[i] = 0; - } - i = 0; - - /* Check for BUF_WRAP */ - if (strncmp(buf, "BUF_WRAP", strlen("BUF_WRAP")) == 0) { - assert(0 && "Buffer wrap detected, Some event occurrences lost!"); - return 0; - } - - /* Since we are using the default buffer size (4K), and have specified - * INFO_LVL=1, we won't see any EVENT_OVERFLOW conditions. Applications - * should check for this keyword if they are using an INFO_LVL of 2 or - * higher, and have a buffer size of <= 4K - */ - - /* Skip to RC_FROM_EVPROD */ - if (uv__skip_lines(&p, 9) != 9) - return -1; - - if (sscanf(p, "RC_FROM_EVPROD=%d\nEND_EVENT_DATA", &evp_rc) == 1) { - if (uv__path_is_a_directory(handle->path) == 0) { /* Directory */ - if (evp_rc == AHAFS_MODDIR_UNMOUNT || evp_rc == AHAFS_MODDIR_REMOVE_SELF) { - /* The directory is no longer available for monitoring */ - *events = UV_RENAME; - handle->dir_filename = NULL; - } else { - /* A file was added/removed inside the directory */ - *events = UV_CHANGE; - - /* Get the EVPROD_INFO */ - if (uv__skip_lines(&p, 1) != 1) - return -1; - - /* Scan out the name of the file that triggered the event*/ - if (sscanf(p, "BEGIN_EVPROD_INFO\n%sEND_EVPROD_INFO", filename) == 1) { - handle->dir_filename = strdup((const char*)&filename); - } else - return -1; - } - } else { /* Regular File */ - if (evp_rc == AHAFS_MODFILE_RENAME) - *events = UV_RENAME; - else - *events = UV_CHANGE; - } - } - else - return -1; - - return 0; -} - - -/* This is the internal callback */ -static void uv__ahafs_event(uv_loop_t* loop, uv__io_t* event_watch, unsigned int fflags) { - char result_data[RDWR_BUF_SIZE]; - int bytes, rc = 0; - uv_fs_event_t* handle; - int events = 0; - int i = 0; - char fname[PATH_MAX]; - char *p; - - handle = container_of(event_watch, uv_fs_event_t, event_watcher); - - /* Clean all the buffers*/ - for(i = 0; i < PATH_MAX; i++) { - fname[i] = 0; - } - i = 0; - - /* At this point, we assume that polling has been done on the - * file descriptor, so we can just read the AHAFS event occurrence - * data and parse its results without having to block anything - */ - bytes = pread(event_watch->fd, result_data, RDWR_BUF_SIZE, 0); - - assert((bytes <= 0) && "uv__ahafs_event - Error reading monitor file"); - - /* Parse the data */ - if(bytes > 0) - rc = uv__parse_data(result_data, &events, handle); - - /* For directory changes, the name of the files that triggered the change - * are never absolute pathnames - */ - if (uv__path_is_a_directory(handle->path) == 0) { - p = handle->dir_filename; - while(*p != NULL){ - fname[i]= *p; - i++; - p++; - } - } else { - /* For file changes, figure out whether filename is absolute or not */ - if (handle->path[0] == '/') { - p = strrchr(handle->path, '/'); - p++; - - while(*p != NULL) { - fname[i]= *p; - i++; - p++; - } - } - } - - /* Unrecoverable error */ - if (rc == -1) - return; - else /* Call the actual JavaScript callback function */ - handle->cb(handle, (const char*)&fname, events, 0); -} - - -int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { - uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); - return 0; -} - - -int uv_fs_event_start(uv_fs_event_t* handle, - uv_fs_event_cb cb, - const char* filename, - unsigned int flags) { - int fd, rc, i = 0, res = 0; - char cwd[PATH_MAX]; - char absolute_path[PATH_MAX]; - char fname[PATH_MAX]; - char *p; - - /* Clean all the buffers*/ - for(i = 0; i < PATH_MAX; i++) { - cwd[i] = 0; - absolute_path[i] = 0; - fname[i] = 0; - } - i = 0; - - /* Figure out whether filename is absolute or not */ - if (filename[0] == '/') { - /* We have absolute pathname, create the relative pathname*/ - sprintf(absolute_path, filename); - p = strrchr(filename, '/'); - p++; - } else { - if (filename[0] == '.' && filename[1] == '/') { - /* We have a relative pathname, compose the absolute pathname */ - sprintf(fname, filename); - snprintf(cwd, PATH_MAX-1, "/proc/%lu/cwd", (unsigned long) getpid()); - res = readlink(cwd, absolute_path, sizeof(absolute_path) - 1); - if (res < 0) - return res; - p = strrchr(absolute_path, '/'); - p++; - p++; - } else { - /* We have a relative pathname, compose the absolute pathname */ - sprintf(fname, filename); - snprintf(cwd, PATH_MAX-1, "/proc/%lu/cwd", (unsigned long) getpid()); - res = readlink(cwd, absolute_path, sizeof(absolute_path) - 1); - if (res < 0) - return res; - p = strrchr(absolute_path, '/'); - p++; - } - /* Copy to filename buffer */ - while(filename[i] != NULL) { - *p = filename[i]; - i++; - p++; - } - } - - if (uv__is_ahafs_mounted() < 0) /* /aha checks failed */ - return UV_ENOSYS; - - /* Setup ahafs */ - rc = uv__setup_ahafs((const char *)absolute_path, &fd); - if (rc != 0) - return rc; - - /* Setup/Initialize all the libuv routines */ - uv__handle_start(handle); - uv__io_init(&handle->event_watcher, uv__ahafs_event, fd); - handle->path = strdup((const char*)&absolute_path); - handle->cb = cb; - - uv__io_start(handle->loop, &handle->event_watcher, UV__POLLIN); - - return 0; -} - - -int uv_fs_event_stop(uv_fs_event_t* handle) { - - if (!uv__is_active(handle)) - return 0; - - uv__io_close(handle->loop, &handle->event_watcher); - uv__handle_stop(handle); - - if (uv__path_is_a_directory(handle->path) == 0) { - free(handle->dir_filename); - handle->dir_filename = NULL; - } - - free(handle->path); - handle->path = NULL; - uv__close(handle->event_watcher.fd); - handle->event_watcher.fd = -1; - - return 0; -} - - -void uv__fs_event_close(uv_fs_event_t* handle) { - uv_fs_event_stop(handle); -} - - -char** uv_setup_args(int argc, char** argv) { - return argv; -} - - -int uv_set_process_title(const char* title) { - return 0; -} - - -int uv_get_process_title(char* buffer, size_t size) { - if (size > 0) { - buffer[0] = '\0'; - } - return 0; -} - - -int uv_resident_set_memory(size_t* rss) { - char pp[64]; - psinfo_t psinfo; - int err; - int fd; - - snprintf(pp, sizeof(pp), "/proc/%lu/psinfo", (unsigned long) getpid()); - - fd = open(pp, O_RDONLY); - if (fd == -1) - return -errno; - - /* FIXME(bnoordhuis) Handle EINTR. */ - err = -EINVAL; - if (read(fd, &psinfo, sizeof(psinfo)) == sizeof(psinfo)) { - *rss = (size_t)psinfo.pr_rssize * 1024; - err = 0; - } - uv__close(fd); - - return err; -} - - -int uv_uptime(double* uptime) { - struct utmp *utmp_buf; - size_t entries = 0; - time_t boot_time; - - utmpname(UTMP_FILE); - - setutent(); - - while ((utmp_buf = getutent()) != NULL) { - if (utmp_buf->ut_user[0] && utmp_buf->ut_type == USER_PROCESS) - ++entries; - if (utmp_buf->ut_type == BOOT_TIME) - boot_time = utmp_buf->ut_time; - } - - endutent(); - - if (boot_time == 0) - return -ENOSYS; - - *uptime = time(NULL) - boot_time; - return 0; -} - - -int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { - uv_cpu_info_t* cpu_info; - perfstat_cpu_total_t ps_total; - perfstat_cpu_t* ps_cpus; - perfstat_id_t cpu_id; - int result, ncpus, idx = 0; - - result = perfstat_cpu_total(NULL, &ps_total, sizeof(ps_total), 1); - if (result == -1) { - return -ENOSYS; - } - - ncpus = result = perfstat_cpu(NULL, NULL, sizeof(perfstat_cpu_t), 0); - if (result == -1) { - return -ENOSYS; - } - - ps_cpus = (perfstat_cpu_t*) malloc(ncpus * sizeof(perfstat_cpu_t)); - if (!ps_cpus) { - return -ENOMEM; - } - - strcpy(cpu_id.name, FIRST_CPU); - result = perfstat_cpu(&cpu_id, ps_cpus, sizeof(perfstat_cpu_t), ncpus); - if (result == -1) { - free(ps_cpus); - return -ENOSYS; - } - - *cpu_infos = (uv_cpu_info_t*) malloc(ncpus * sizeof(uv_cpu_info_t)); - if (!*cpu_infos) { - free(ps_cpus); - return -ENOMEM; - } - - *count = ncpus; - - cpu_info = *cpu_infos; - while (idx < ncpus) { - cpu_info->speed = (int)(ps_total.processorHZ / 1000000); - cpu_info->model = strdup(ps_total.description); - cpu_info->cpu_times.user = ps_cpus[idx].user; - cpu_info->cpu_times.sys = ps_cpus[idx].sys; - cpu_info->cpu_times.idle = ps_cpus[idx].idle; - cpu_info->cpu_times.irq = ps_cpus[idx].wait; - cpu_info->cpu_times.nice = 0; - cpu_info++; - idx++; - } - - free(ps_cpus); - return 0; -} - - -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - int i; - - for (i = 0; i < count; ++i) { - free(cpu_infos[i].model); - } - - free(cpu_infos); -} - - -int uv_interface_addresses(uv_interface_address_t** addresses, - int* count) { - uv_interface_address_t* address; - int sockfd, size = 1; - struct ifconf ifc; - struct ifreq *ifr, *p, flg; - - *count = 0; - - if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) { - return -ENOSYS; - } - - if (ioctl(sockfd, SIOCGSIZIFCONF, &size) == -1) { - uv__close(sockfd); - return -ENOSYS; - } - - ifc.ifc_req = (struct ifreq*)malloc(size); - ifc.ifc_len = size; - if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) { - uv__close(sockfd); - return -ENOSYS; - } - -#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p)) - - /* Count all up and running ipv4/ipv6 addresses */ - ifr = ifc.ifc_req; - while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { - p = ifr; - ifr = (struct ifreq*) - ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); - - if (!(p->ifr_addr.sa_family == AF_INET6 || - p->ifr_addr.sa_family == AF_INET)) - continue; - - memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); - if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { - uv__close(sockfd); - return -ENOSYS; - } - - if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) - continue; - - (*count)++; - } - - /* Alloc the return interface structs */ - *addresses = (uv_interface_address_t*) - malloc(*count * sizeof(uv_interface_address_t)); - if (!(*addresses)) { - uv__close(sockfd); - return -ENOMEM; - } - address = *addresses; - - ifr = ifc.ifc_req; - while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { - p = ifr; - ifr = (struct ifreq*) - ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); - - if (!(p->ifr_addr.sa_family == AF_INET6 || - p->ifr_addr.sa_family == AF_INET)) - continue; - - memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); - if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { - uv__close(sockfd); - return -ENOSYS; - } - - if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) - continue; - - /* All conditions above must match count loop */ - - address->name = strdup(p->ifr_name); - - if (p->ifr_addr.sa_family == AF_INET6) { - address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr); - } else { - address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr); - } - - /* TODO: Retrieve netmask using SIOCGIFNETMASK ioctl */ - - address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0; - - address++; - } - -#undef ADDR_SIZE - - uv__close(sockfd); - return 0; -} - - -void uv_free_interface_addresses(uv_interface_address_t* addresses, - int count) { - int i; - - for (i = 0; i < count; ++i) { - free(addresses[i].name); - } - - free(addresses); -} - -void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { - struct pollfd* events; - uintptr_t i; - uintptr_t nfds; - - assert(loop->watchers != NULL); - - events = (struct pollfd*) loop->watchers[loop->nwatchers]; - nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; - if (events == NULL) - return; - - /* Invalidate events with same file descriptor */ - for (i = 0; i < nfds; i++) - if ((int) events[i].fd == fd) - events[i].fd = -1; -} diff --git a/libuv/src/unix/android-ifaddrs.c b/libuv/src/unix/android-ifaddrs.c deleted file mode 100644 index 3cda578..0000000 --- a/libuv/src/unix/android-ifaddrs.c +++ /dev/null @@ -1,702 +0,0 @@ -/* -Copyright (c) 2013, Kenneth MacKay -Copyright (c) 2014, Emergya (Cloud4all, FP7/2007-2013 grant agreement n° 289016) -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "android-ifaddrs.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -typedef struct NetlinkList -{ - struct NetlinkList *m_next; - struct nlmsghdr *m_data; - unsigned int m_size; -} NetlinkList; - -static int netlink_socket(void) -{ - struct sockaddr_nl l_addr; - - int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if(l_socket < 0) - { - return -1; - } - - memset(&l_addr, 0, sizeof(l_addr)); - l_addr.nl_family = AF_NETLINK; - if(bind(l_socket, (struct sockaddr *)&l_addr, sizeof(l_addr)) < 0) - { - close(l_socket); - return -1; - } - - return l_socket; -} - -static int netlink_send(int p_socket, int p_request) -{ - char l_buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))]; - - struct nlmsghdr *l_hdr; - struct rtgenmsg *l_msg; - struct sockaddr_nl l_addr; - - memset(l_buffer, 0, sizeof(l_buffer)); - - l_hdr = (struct nlmsghdr *)l_buffer; - l_msg = (struct rtgenmsg *)NLMSG_DATA(l_hdr); - - l_hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*l_msg)); - l_hdr->nlmsg_type = p_request; - l_hdr->nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; - l_hdr->nlmsg_pid = 0; - l_hdr->nlmsg_seq = p_socket; - l_msg->rtgen_family = AF_UNSPEC; - - memset(&l_addr, 0, sizeof(l_addr)); - l_addr.nl_family = AF_NETLINK; - return (sendto(p_socket, l_hdr, l_hdr->nlmsg_len, 0, (struct sockaddr *)&l_addr, sizeof(l_addr))); -} - -static int netlink_recv(int p_socket, void *p_buffer, size_t p_len) -{ - struct sockaddr_nl l_addr; - struct msghdr l_msg; - - struct iovec l_iov; - l_iov.iov_base = p_buffer; - l_iov.iov_len = p_len; - - for(;;) - { - int l_result; - l_msg.msg_name = (void *)&l_addr; - l_msg.msg_namelen = sizeof(l_addr); - l_msg.msg_iov = &l_iov; - l_msg.msg_iovlen = 1; - l_msg.msg_control = NULL; - l_msg.msg_controllen = 0; - l_msg.msg_flags = 0; - l_result = recvmsg(p_socket, &l_msg, 0); - - if(l_result < 0) - { - if(errno == EINTR) - { - continue; - } - return -2; - } - - /* Buffer was too small */ - if(l_msg.msg_flags & MSG_TRUNC) - { - return -1; - } - return l_result; - } -} - -static struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int *p_done) -{ - size_t l_size = 4096; - void *l_buffer = NULL; - - for(;;) - { - int l_read; - - free(l_buffer); - l_buffer = malloc(l_size); - if (l_buffer == NULL) - { - return NULL; - } - - l_read = netlink_recv(p_socket, l_buffer, l_size); - *p_size = l_read; - if(l_read == -2) - { - free(l_buffer); - return NULL; - } - if(l_read >= 0) - { - pid_t l_pid = getpid(); - struct nlmsghdr *l_hdr; - for(l_hdr = (struct nlmsghdr *)l_buffer; NLMSG_OK(l_hdr, (unsigned int)l_read); l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read)) - { - if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) - { - continue; - } - - if(l_hdr->nlmsg_type == NLMSG_DONE) - { - *p_done = 1; - break; - } - - if(l_hdr->nlmsg_type == NLMSG_ERROR) - { - free(l_buffer); - return NULL; - } - } - return l_buffer; - } - - l_size *= 2; - } -} - -static NetlinkList *newListItem(struct nlmsghdr *p_data, unsigned int p_size) -{ - NetlinkList *l_item = malloc(sizeof(NetlinkList)); - if (l_item == NULL) - { - return NULL; - } - - l_item->m_next = NULL; - l_item->m_data = p_data; - l_item->m_size = p_size; - return l_item; -} - -static void freeResultList(NetlinkList *p_list) -{ - NetlinkList *l_cur; - while(p_list) - { - l_cur = p_list; - p_list = p_list->m_next; - free(l_cur->m_data); - free(l_cur); - } -} - -static NetlinkList *getResultList(int p_socket, int p_request) -{ - int l_size; - int l_done; - NetlinkList *l_list; - NetlinkList *l_end; - - if(netlink_send(p_socket, p_request) < 0) - { - return NULL; - } - - l_list = NULL; - l_end = NULL; - - l_done = 0; - while(!l_done) - { - NetlinkList *l_item; - - struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, &l_size, &l_done); - /* Error */ - if(!l_hdr) - { - freeResultList(l_list); - return NULL; - } - - l_item = newListItem(l_hdr, l_size); - if (!l_item) - { - freeResultList(l_list); - return NULL; - } - if(!l_list) - { - l_list = l_item; - } - else - { - l_end->m_next = l_item; - } - l_end = l_item; - } - return l_list; -} - -static size_t maxSize(size_t a, size_t b) -{ - return (a > b ? a : b); -} - -static size_t calcAddrLen(sa_family_t p_family, int p_dataSize) -{ - switch(p_family) - { - case AF_INET: - return sizeof(struct sockaddr_in); - case AF_INET6: - return sizeof(struct sockaddr_in6); - case AF_PACKET: - return maxSize(sizeof(struct sockaddr_ll), offsetof(struct sockaddr_ll, sll_addr) + p_dataSize); - default: - return maxSize(sizeof(struct sockaddr), offsetof(struct sockaddr, sa_data) + p_dataSize); - } -} - -static void makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void *p_data, size_t p_size) -{ - switch(p_family) - { - case AF_INET: - memcpy(&((struct sockaddr_in*)p_dest)->sin_addr, p_data, p_size); - break; - case AF_INET6: - memcpy(&((struct sockaddr_in6*)p_dest)->sin6_addr, p_data, p_size); - break; - case AF_PACKET: - memcpy(((struct sockaddr_ll*)p_dest)->sll_addr, p_data, p_size); - ((struct sockaddr_ll*)p_dest)->sll_halen = p_size; - break; - default: - memcpy(p_dest->sa_data, p_data, p_size); - break; - } - p_dest->sa_family = p_family; -} - -static void addToEnd(struct ifaddrs **p_resultList, struct ifaddrs *p_entry) -{ - if(!*p_resultList) - { - *p_resultList = p_entry; - } - else - { - struct ifaddrs *l_cur = *p_resultList; - while(l_cur->ifa_next) - { - l_cur = l_cur->ifa_next; - } - l_cur->ifa_next = p_entry; - } -} - -static int interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList) -{ - struct ifaddrs *l_entry; - - char *l_index; - char *l_name; - char *l_addr; - char *l_data; - - struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(p_hdr); - - size_t l_nameSize = 0; - size_t l_addrSize = 0; - size_t l_dataSize = 0; - - size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg)); - struct rtattr *l_rta; - for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) - { - size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); - switch(l_rta->rta_type) - { - case IFLA_ADDRESS: - case IFLA_BROADCAST: - l_addrSize += NLMSG_ALIGN(calcAddrLen(AF_PACKET, l_rtaDataSize)); - break; - case IFLA_IFNAME: - l_nameSize += NLMSG_ALIGN(l_rtaSize + 1); - break; - case IFLA_STATS: - l_dataSize += NLMSG_ALIGN(l_rtaSize); - break; - default: - break; - } - } - - l_entry = malloc(sizeof(struct ifaddrs) + sizeof(int) + l_nameSize + l_addrSize + l_dataSize); - if (l_entry == NULL) - { - return -1; - } - memset(l_entry, 0, sizeof(struct ifaddrs)); - l_entry->ifa_name = ""; - - l_index = ((char *)l_entry) + sizeof(struct ifaddrs); - l_name = l_index + sizeof(int); - l_addr = l_name + l_nameSize; - l_data = l_addr + l_addrSize; - - /* Save the interface index so we can look it up when handling the - * addresses. - */ - memcpy(l_index, &l_info->ifi_index, sizeof(int)); - - l_entry->ifa_flags = l_info->ifi_flags; - - l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg)); - for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) - { - void *l_rtaData = RTA_DATA(l_rta); - size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); - switch(l_rta->rta_type) - { - case IFLA_ADDRESS: - case IFLA_BROADCAST: - { - size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize); - makeSockaddr(AF_PACKET, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize); - ((struct sockaddr_ll *)l_addr)->sll_ifindex = l_info->ifi_index; - ((struct sockaddr_ll *)l_addr)->sll_hatype = l_info->ifi_type; - if(l_rta->rta_type == IFLA_ADDRESS) - { - l_entry->ifa_addr = (struct sockaddr *)l_addr; - } - else - { - l_entry->ifa_broadaddr = (struct sockaddr *)l_addr; - } - l_addr += NLMSG_ALIGN(l_addrLen); - break; - } - case IFLA_IFNAME: - strncpy(l_name, l_rtaData, l_rtaDataSize); - l_name[l_rtaDataSize] = '\0'; - l_entry->ifa_name = l_name; - break; - case IFLA_STATS: - memcpy(l_data, l_rtaData, l_rtaDataSize); - l_entry->ifa_data = l_data; - break; - default: - break; - } - } - - addToEnd(p_resultList, l_entry); - return 0; -} - -static struct ifaddrs *findInterface(int p_index, struct ifaddrs **p_links, int p_numLinks) -{ - int l_num = 0; - struct ifaddrs *l_cur = *p_links; - while(l_cur && l_num < p_numLinks) - { - char *l_indexPtr = ((char *)l_cur) + sizeof(struct ifaddrs); - int l_index; - memcpy(&l_index, l_indexPtr, sizeof(int)); - if(l_index == p_index) - { - return l_cur; - } - - l_cur = l_cur->ifa_next; - ++l_num; - } - return NULL; -} - -static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList, int p_numLinks) -{ - struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr); - struct ifaddrs *l_interface = findInterface(l_info->ifa_index, p_resultList, p_numLinks); - - size_t l_nameSize = 0; - size_t l_addrSize = 0; - - int l_addedNetmask = 0; - - size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg)); - struct rtattr *l_rta; - struct ifaddrs *l_entry; - - char *l_name; - char *l_addr; - - for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) - { - size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); - if(l_info->ifa_family == AF_PACKET) - { - continue; - } - - switch(l_rta->rta_type) - { - case IFA_ADDRESS: - case IFA_LOCAL: - if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask) - { - /* Make room for netmask */ - l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize)); - l_addedNetmask = 1; - } - case IFA_BROADCAST: - l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize)); - break; - case IFA_LABEL: - l_nameSize += NLMSG_ALIGN(l_rtaSize + 1); - break; - default: - break; - } - } - - l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize); - if (l_entry == NULL) - { - return -1; - } - memset(l_entry, 0, sizeof(struct ifaddrs)); - l_entry->ifa_name = (l_interface ? l_interface->ifa_name : ""); - - l_name = ((char *)l_entry) + sizeof(struct ifaddrs); - l_addr = l_name + l_nameSize; - - l_entry->ifa_flags = l_info->ifa_flags; - if(l_interface) - { - l_entry->ifa_flags |= l_interface->ifa_flags; - } - - l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg)); - for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize)) - { - void *l_rtaData = RTA_DATA(l_rta); - size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); - switch(l_rta->rta_type) - { - case IFA_ADDRESS: - case IFA_BROADCAST: - case IFA_LOCAL: - { - size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize); - makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize); - if(l_info->ifa_family == AF_INET6) - { - if(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)l_rtaData) || IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr *)l_rtaData)) - { - ((struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index; - } - } - - /* Apparently in a point-to-point network IFA_ADDRESS contains - * the dest address and IFA_LOCAL contains the local address - */ - if(l_rta->rta_type == IFA_ADDRESS) - { - if(l_entry->ifa_addr) - { - l_entry->ifa_dstaddr = (struct sockaddr *)l_addr; - } - else - { - l_entry->ifa_addr = (struct sockaddr *)l_addr; - } - } - else if(l_rta->rta_type == IFA_LOCAL) - { - if(l_entry->ifa_addr) - { - l_entry->ifa_dstaddr = l_entry->ifa_addr; - } - l_entry->ifa_addr = (struct sockaddr *)l_addr; - } - else - { - l_entry->ifa_broadaddr = (struct sockaddr *)l_addr; - } - l_addr += NLMSG_ALIGN(l_addrLen); - break; - } - case IFA_LABEL: - strncpy(l_name, l_rtaData, l_rtaDataSize); - l_name[l_rtaDataSize] = '\0'; - l_entry->ifa_name = l_name; - break; - default: - break; - } - } - - if(l_entry->ifa_addr && (l_entry->ifa_addr->sa_family == AF_INET || l_entry->ifa_addr->sa_family == AF_INET6)) - { - unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128); - unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen); - char l_mask[16] = {0}; - unsigned i; - for(i=0; i<(l_prefix/8); ++i) - { - l_mask[i] = 0xff; - } - if(l_prefix % 8) - { - l_mask[i] = 0xff << (8 - (l_prefix % 8)); - } - - makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr *)l_addr, l_mask, l_maxPrefix / 8); - l_entry->ifa_netmask = (struct sockaddr *)l_addr; - } - - addToEnd(p_resultList, l_entry); - return 0; -} - -static int interpretLinks(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList) -{ - - int l_numLinks = 0; - pid_t l_pid = getpid(); - for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next) - { - unsigned int l_nlsize = p_netlinkList->m_size; - struct nlmsghdr *l_hdr; - for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize)) - { - if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) - { - continue; - } - - if(l_hdr->nlmsg_type == NLMSG_DONE) - { - break; - } - - if(l_hdr->nlmsg_type == RTM_NEWLINK) - { - if(interpretLink(l_hdr, p_resultList) == -1) - { - return -1; - } - ++l_numLinks; - } - } - } - return l_numLinks; -} - -static int interpretAddrs(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList, int p_numLinks) -{ - pid_t l_pid = getpid(); - for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next) - { - unsigned int l_nlsize = p_netlinkList->m_size; - struct nlmsghdr *l_hdr; - for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize)) - { - if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket) - { - continue; - } - - if(l_hdr->nlmsg_type == NLMSG_DONE) - { - break; - } - - if(l_hdr->nlmsg_type == RTM_NEWADDR) - { - if (interpretAddr(l_hdr, p_resultList, p_numLinks) == -1) - { - return -1; - } - } - } - } - return 0; -} - -int getifaddrs(struct ifaddrs **ifap) -{ - int l_socket; - int l_result; - int l_numLinks; - NetlinkList *l_linkResults; - NetlinkList *l_addrResults; - - if(!ifap) - { - return -1; - } - *ifap = NULL; - - l_socket = netlink_socket(); - if(l_socket < 0) - { - return -1; - } - - l_linkResults = getResultList(l_socket, RTM_GETLINK); - if(!l_linkResults) - { - close(l_socket); - return -1; - } - - l_addrResults = getResultList(l_socket, RTM_GETADDR); - if(!l_addrResults) - { - close(l_socket); - freeResultList(l_linkResults); - return -1; - } - - l_result = 0; - l_numLinks = interpretLinks(l_socket, l_linkResults, ifap); - if(l_numLinks == -1 || interpretAddrs(l_socket, l_addrResults, ifap, l_numLinks) == -1) - { - l_result = -1; - } - - freeResultList(l_linkResults); - freeResultList(l_addrResults); - close(l_socket); - return l_result; -} - -void freeifaddrs(struct ifaddrs *ifa) -{ - struct ifaddrs *l_cur; - while(ifa) - { - l_cur = ifa; - ifa = ifa->ifa_next; - free(l_cur); - } -} diff --git a/libuv/src/unix/async.c b/libuv/src/unix/async.c deleted file mode 100644 index b794ea6..0000000 --- a/libuv/src/unix/async.c +++ /dev/null @@ -1,312 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* This file contains both the uv__async internal infrastructure and the - * user-facing uv_async_t functions. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include /* snprintf() */ -#include -#include -#include -#include - -static void uv__async_event(uv_loop_t* loop, - struct uv__async* w, - unsigned int nevents); -static int uv__async_make_pending(int* pending); -static int uv__async_eventfd(void); - - -int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) { - int err; - - err = uv__async_start(loop, &loop->async_watcher, uv__async_event); - if (err) - return err; - - uv__handle_init(loop, (uv_handle_t*)handle, UV_ASYNC); - handle->async_cb = async_cb; - handle->pending = 0; - - QUEUE_INSERT_TAIL(&loop->async_handles, &handle->queue); - uv__handle_start(handle); - - return 0; -} - - -int uv_async_send(uv_async_t* handle) { - if (uv__async_make_pending(&handle->pending) == 0) - uv__async_send(&handle->loop->async_watcher); - - return 0; -} - - -void uv__async_close(uv_async_t* handle) { - QUEUE_REMOVE(&handle->queue); - uv__handle_stop(handle); -} - - -static void uv__async_event(uv_loop_t* loop, - struct uv__async* w, - unsigned int nevents) { - QUEUE* q; - uv_async_t* h; - - QUEUE_FOREACH(q, &loop->async_handles) { - h = QUEUE_DATA(q, uv_async_t, queue); - - if (h->pending == 0) - continue; - h->pending = 0; - - if (h->async_cb == NULL) - continue; - h->async_cb(h); - } -} - - -static int uv__async_make_pending(int* pending) { - /* Do a cheap read first. */ - if (ACCESS_ONCE(int, *pending) != 0) - return 1; - - /* Micro-optimization: use atomic memory operations to detect if we've been - * preempted by another thread and don't have to make an expensive syscall. - * This speeds up the heavily contended case by about 1-2% and has little - * if any impact on the non-contended case. - * - * Use XCHG instead of the CMPXCHG that __sync_val_compare_and_swap() emits - * on x86, it's about 4x faster. It probably makes zero difference in the - * grand scheme of things but I'm OCD enough not to let this one pass. - */ -#if defined(__i386__) || defined(__x86_64__) - { - unsigned int val = 1; - __asm__ __volatile__ ("xchgl %0, %1" - : "+r" (val) - : "m" (*pending)); - return val != 0; - } -#elif defined(__GNUC__) && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ > 0) - return __sync_val_compare_and_swap(pending, 0, 1) != 0; -#else - ACCESS_ONCE(int, *pending) = 1; - return 0; -#endif -} - - -static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { - struct uv__async* wa; - char buf[1024]; - unsigned n; - ssize_t r; - - n = 0; - for (;;) { - r = read(w->fd, buf, sizeof(buf)); - - if (r > 0) - n += r; - - if (r == sizeof(buf)) - continue; - - if (r != -1) - break; - - if (errno == EAGAIN || errno == EWOULDBLOCK) - break; - - if (errno == EINTR) - continue; - - abort(); - } - - wa = container_of(w, struct uv__async, io_watcher); - -#if defined(__linux__) - if (wa->wfd == -1) { - uint64_t val; - assert(n == sizeof(val)); - memcpy(&val, buf, sizeof(val)); /* Avoid alignment issues. */ - wa->cb(loop, wa, val); - return; - } -#endif - - wa->cb(loop, wa, n); -} - - -void uv__async_send(struct uv__async* wa) { - const void* buf; - ssize_t len; - int fd; - int r; - - buf = ""; - len = 1; - fd = wa->wfd; - -#if defined(__linux__) - if (fd == -1) { - static const uint64_t val = 1; - buf = &val; - len = sizeof(val); - fd = wa->io_watcher.fd; /* eventfd */ - } -#endif - - do - r = write(fd, buf, len); - while (r == -1 && errno == EINTR); - - if (r == len) - return; - - if (r == -1) - if (errno == EAGAIN || errno == EWOULDBLOCK) - return; - - abort(); -} - - -void uv__async_init(struct uv__async* wa) { - wa->io_watcher.fd = -1; - wa->wfd = -1; -} - - -int uv__async_start(uv_loop_t* loop, struct uv__async* wa, uv__async_cb cb) { - int pipefd[2]; - int err; - - if (wa->io_watcher.fd != -1) - return 0; - - err = uv__async_eventfd(); - if (err >= 0) { - pipefd[0] = err; - pipefd[1] = -1; - } - else if (err == -ENOSYS) { - err = uv__make_pipe(pipefd, UV__F_NONBLOCK); -#if defined(__linux__) - /* Save a file descriptor by opening one of the pipe descriptors as - * read/write through the procfs. That file descriptor can then - * function as both ends of the pipe. - */ - if (err == 0) { - char buf[32]; - int fd; - - snprintf(buf, sizeof(buf), "/proc/self/fd/%d", pipefd[0]); - fd = uv__open_cloexec(buf, O_RDWR); - if (fd >= 0) { - uv__close(pipefd[0]); - uv__close(pipefd[1]); - pipefd[0] = fd; - pipefd[1] = fd; - } - } -#endif - } - - if (err < 0) - return err; - - uv__io_init(&wa->io_watcher, uv__async_io, pipefd[0]); - uv__io_start(loop, &wa->io_watcher, UV__POLLIN); - wa->wfd = pipefd[1]; - wa->cb = cb; - - return 0; -} - - -void uv__async_stop(uv_loop_t* loop, struct uv__async* wa) { - if (wa->io_watcher.fd == -1) - return; - - if (wa->wfd != -1) { - if (wa->wfd != wa->io_watcher.fd) - uv__close(wa->wfd); - wa->wfd = -1; - } - - uv__io_stop(loop, &wa->io_watcher, UV__POLLIN); - uv__close(wa->io_watcher.fd); - wa->io_watcher.fd = -1; -} - - -static int uv__async_eventfd() { -#if defined(__linux__) - static int no_eventfd2; - static int no_eventfd; - int fd; - - if (no_eventfd2) - goto skip_eventfd2; - - fd = uv__eventfd2(0, UV__EFD_CLOEXEC | UV__EFD_NONBLOCK); - if (fd != -1) - return fd; - - if (errno != ENOSYS) - return -errno; - - no_eventfd2 = 1; - -skip_eventfd2: - - if (no_eventfd) - goto skip_eventfd; - - fd = uv__eventfd(0); - if (fd != -1) { - uv__cloexec(fd, 1); - uv__nonblock(fd, 1); - return fd; - } - - if (errno != ENOSYS) - return -errno; - - no_eventfd = 1; - -skip_eventfd: - -#endif - - return -ENOSYS; -} diff --git a/libuv/src/unix/atomic-ops.h b/libuv/src/unix/atomic-ops.h deleted file mode 100644 index 7e4e64b..0000000 --- a/libuv/src/unix/atomic-ops.h +++ /dev/null @@ -1,60 +0,0 @@ -/* Copyright (c) 2013, Ben Noordhuis - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef UV_ATOMIC_OPS_H_ -#define UV_ATOMIC_OPS_H_ - -#include "internal.h" /* UV_UNUSED */ - -UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)); -UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)); -UV_UNUSED(static void cpu_relax(void)); - -/* Prefer hand-rolled assembly over the gcc builtins because the latter also - * issue full memory barriers. - */ -UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) { -#if defined(__i386__) || defined(__x86_64__) - int out; - __asm__ __volatile__ ("lock; cmpxchg %2, %1;" - : "=a" (out), "+m" (*(volatile int*) ptr) - : "r" (newval), "0" (oldval) - : "memory"); - return out; -#else - return __sync_val_compare_and_swap(ptr, oldval, newval); -#endif -} - -UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)) { -#if defined(__i386__) || defined(__x86_64__) - long out; - __asm__ __volatile__ ("lock; cmpxchg %2, %1;" - : "=a" (out), "+m" (*(volatile long*) ptr) - : "r" (newval), "0" (oldval) - : "memory"); - return out; -#else - return __sync_val_compare_and_swap(ptr, oldval, newval); -#endif -} - -UV_UNUSED(static void cpu_relax(void)) { -#if defined(__i386__) || defined(__x86_64__) - __asm__ __volatile__ ("rep; nop"); /* a.k.a. PAUSE */ -#endif -} - -#endif /* UV_ATOMIC_OPS_H_ */ diff --git a/libuv/src/unix/core.c b/libuv/src/unix/core.c deleted file mode 100644 index 6f284ff..0000000 --- a/libuv/src/unix/core.c +++ /dev/null @@ -1,985 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include /* NULL */ -#include /* printf */ -#include -#include /* strerror */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* INT_MAX, PATH_MAX */ -#include /* writev */ -#include /* getrusage */ - -#ifdef __linux__ -# include -#endif - -#ifdef __sun -# include -# include -#endif - -#ifdef __APPLE__ -# include /* _NSGetExecutablePath */ -# include -# include -#endif - -#ifdef __FreeBSD__ -# include -# include -# include -# include -# define UV__O_CLOEXEC O_CLOEXEC -# if __FreeBSD__ >= 10 -# define uv__accept4 accept4 -# define UV__SOCK_NONBLOCK SOCK_NONBLOCK -# define UV__SOCK_CLOEXEC SOCK_CLOEXEC -# endif -# if !defined(F_DUP2FD_CLOEXEC) && defined(_F_DUP2FD_CLOEXEC) -# define F_DUP2FD_CLOEXEC _F_DUP2FD_CLOEXEC -# endif -#endif - -#ifdef _AIX -#include -#endif - -static int uv__run_pending(uv_loop_t* loop); - -/* Verify that uv_buf_t is ABI-compatible with struct iovec. */ -STATIC_ASSERT(sizeof(uv_buf_t) == sizeof(struct iovec)); -STATIC_ASSERT(sizeof(&((uv_buf_t*) 0)->base) == - sizeof(((struct iovec*) 0)->iov_base)); -STATIC_ASSERT(sizeof(&((uv_buf_t*) 0)->len) == - sizeof(((struct iovec*) 0)->iov_len)); -STATIC_ASSERT(offsetof(uv_buf_t, base) == offsetof(struct iovec, iov_base)); -STATIC_ASSERT(offsetof(uv_buf_t, len) == offsetof(struct iovec, iov_len)); - - -uint64_t uv_hrtime(void) { - return uv__hrtime(UV_CLOCK_PRECISE); -} - - -void uv_close(uv_handle_t* handle, uv_close_cb close_cb) { - assert(!(handle->flags & (UV_CLOSING | UV_CLOSED))); - - handle->flags |= UV_CLOSING; - handle->close_cb = close_cb; - - switch (handle->type) { - case UV_NAMED_PIPE: - uv__pipe_close((uv_pipe_t*)handle); - break; - - case UV_TTY: - uv__stream_close((uv_stream_t*)handle); - break; - - case UV_TCP: - uv__tcp_close((uv_tcp_t*)handle); - break; - - case UV_UDP: - uv__udp_close((uv_udp_t*)handle); - break; - - case UV_PREPARE: - uv__prepare_close((uv_prepare_t*)handle); - break; - - case UV_CHECK: - uv__check_close((uv_check_t*)handle); - break; - - case UV_IDLE: - uv__idle_close((uv_idle_t*)handle); - break; - - case UV_ASYNC: - uv__async_close((uv_async_t*)handle); - break; - - case UV_TIMER: - uv__timer_close((uv_timer_t*)handle); - break; - - case UV_PROCESS: - uv__process_close((uv_process_t*)handle); - break; - - case UV_FS_EVENT: - uv__fs_event_close((uv_fs_event_t*)handle); - break; - - case UV_POLL: - uv__poll_close((uv_poll_t*)handle); - break; - - case UV_FS_POLL: - uv__fs_poll_close((uv_fs_poll_t*)handle); - break; - - case UV_SIGNAL: - uv__signal_close((uv_signal_t*) handle); - /* Signal handles may not be closed immediately. The signal code will */ - /* itself close uv__make_close_pending whenever appropriate. */ - return; - - default: - assert(0); - } - - uv__make_close_pending(handle); -} - -int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) { - int r; - int fd; - socklen_t len; - - if (handle == NULL || value == NULL) - return -EINVAL; - - if (handle->type == UV_TCP || handle->type == UV_NAMED_PIPE) - fd = uv__stream_fd((uv_stream_t*) handle); - else if (handle->type == UV_UDP) - fd = ((uv_udp_t *) handle)->io_watcher.fd; - else - return -ENOTSUP; - - len = sizeof(*value); - - if (*value == 0) - r = getsockopt(fd, SOL_SOCKET, optname, value, &len); - else - r = setsockopt(fd, SOL_SOCKET, optname, (const void*) value, len); - - if (r < 0) - return -errno; - - return 0; -} - -void uv__make_close_pending(uv_handle_t* handle) { - assert(handle->flags & UV_CLOSING); - assert(!(handle->flags & UV_CLOSED)); - handle->next_closing = handle->loop->closing_handles; - handle->loop->closing_handles = handle; -} - - -static void uv__finish_close(uv_handle_t* handle) { - /* Note: while the handle is in the UV_CLOSING state now, it's still possible - * for it to be active in the sense that uv__is_active() returns true. - * A good example is when the user calls uv_shutdown(), immediately followed - * by uv_close(). The handle is considered active at this point because the - * completion of the shutdown req is still pending. - */ - assert(handle->flags & UV_CLOSING); - assert(!(handle->flags & UV_CLOSED)); - handle->flags |= UV_CLOSED; - - switch (handle->type) { - case UV_PREPARE: - case UV_CHECK: - case UV_IDLE: - case UV_ASYNC: - case UV_TIMER: - case UV_PROCESS: - case UV_FS_EVENT: - case UV_FS_POLL: - case UV_POLL: - case UV_SIGNAL: - break; - - case UV_NAMED_PIPE: - case UV_TCP: - case UV_TTY: - uv__stream_destroy((uv_stream_t*)handle); - break; - - case UV_UDP: - uv__udp_finish_close((uv_udp_t*)handle); - break; - - default: - assert(0); - break; - } - - uv__handle_unref(handle); - QUEUE_REMOVE(&handle->handle_queue); - - if (handle->close_cb) { - handle->close_cb(handle); - } -} - - -static void uv__run_closing_handles(uv_loop_t* loop) { - uv_handle_t* p; - uv_handle_t* q; - - p = loop->closing_handles; - loop->closing_handles = NULL; - - while (p) { - q = p->next_closing; - uv__finish_close(p); - p = q; - } -} - - -int uv_is_closing(const uv_handle_t* handle) { - return uv__is_closing(handle); -} - - -int uv_backend_fd(const uv_loop_t* loop) { - return loop->backend_fd; -} - - -int uv_backend_timeout(const uv_loop_t* loop) { - if (loop->stop_flag != 0) - return 0; - - if (!uv__has_active_handles(loop) && !uv__has_active_reqs(loop)) - return 0; - - if (!QUEUE_EMPTY(&loop->idle_handles)) - return 0; - - if (loop->closing_handles) - return 0; - - return uv__next_timeout(loop); -} - - -static int uv__loop_alive(const uv_loop_t* loop) { - return uv__has_active_handles(loop) || - uv__has_active_reqs(loop) || - loop->closing_handles != NULL; -} - - -int uv_loop_alive(const uv_loop_t* loop) { - return uv__loop_alive(loop); -} - - -int uv_run(uv_loop_t* loop, uv_run_mode mode) { - int timeout; - int r; - int ran_pending; - - r = uv__loop_alive(loop); - if (!r) - uv__update_time(loop); - - while (r != 0 && loop->stop_flag == 0) { - uv__update_time(loop); - uv__run_timers(loop); - ran_pending = uv__run_pending(loop); - uv__run_idle(loop); - uv__run_prepare(loop); - - timeout = 0; - if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT) - timeout = uv_backend_timeout(loop); - - uv__io_poll(loop, timeout); - uv__run_check(loop); - uv__run_closing_handles(loop); - - if (mode == UV_RUN_ONCE) { - /* UV_RUN_ONCE implies forward progress: at least one callback must have - * been invoked when it returns. uv__io_poll() can return without doing - * I/O (meaning: no callbacks) when its timeout expires - which means we - * have pending timers that satisfy the forward progress constraint. - * - * UV_RUN_NOWAIT makes no guarantees about progress so it's omitted from - * the check. - */ - uv__update_time(loop); - uv__run_timers(loop); - } - - r = uv__loop_alive(loop); - if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT) - break; - } - - /* The if statement lets gcc compile it to a conditional store. Avoids - * dirtying a cache line. - */ - if (loop->stop_flag != 0) - loop->stop_flag = 0; - - return r; -} - - -void uv_update_time(uv_loop_t* loop) { - uv__update_time(loop); -} - - -int uv_is_active(const uv_handle_t* handle) { - return uv__is_active(handle); -} - - -/* Open a socket in non-blocking close-on-exec mode, atomically if possible. */ -int uv__socket(int domain, int type, int protocol) { - int sockfd; - int err; - -#if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) - sockfd = socket(domain, type | SOCK_NONBLOCK | SOCK_CLOEXEC, protocol); - if (sockfd != -1) - return sockfd; - - if (errno != EINVAL) - return -errno; -#endif - - sockfd = socket(domain, type, protocol); - if (sockfd == -1) - return -errno; - - err = uv__nonblock(sockfd, 1); - if (err == 0) - err = uv__cloexec(sockfd, 1); - - if (err) { - uv__close(sockfd); - return err; - } - -#if defined(SO_NOSIGPIPE) - { - int on = 1; - setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on)); - } -#endif - - return sockfd; -} - - -int uv__accept(int sockfd) { - int peerfd; - int err; - - assert(sockfd >= 0); - - while (1) { -#if defined(__linux__) || __FreeBSD__ >= 10 - static int no_accept4; - - if (no_accept4) - goto skip; - - peerfd = uv__accept4(sockfd, - NULL, - NULL, - UV__SOCK_NONBLOCK|UV__SOCK_CLOEXEC); - if (peerfd != -1) - return peerfd; - - if (errno == EINTR) - continue; - - if (errno != ENOSYS) - return -errno; - - no_accept4 = 1; -skip: -#endif - - peerfd = accept(sockfd, NULL, NULL); - if (peerfd == -1) { - if (errno == EINTR) - continue; - return -errno; - } - - err = uv__cloexec(peerfd, 1); - if (err == 0) - err = uv__nonblock(peerfd, 1); - - if (err) { - uv__close(peerfd); - return err; - } - - return peerfd; - } -} - - -int uv__close(int fd) { - int saved_errno; - int rc; - - assert(fd > -1); /* Catch uninitialized io_watcher.fd bugs. */ - assert(fd > STDERR_FILENO); /* Catch stdio close bugs. */ - - saved_errno = errno; - rc = close(fd); - if (rc == -1) { - rc = -errno; - if (rc == -EINTR) - rc = -EINPROGRESS; /* For platform/libc consistency. */ - errno = saved_errno; - } - - return rc; -} - - -#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \ - defined(_AIX) - -int uv__nonblock(int fd, int set) { - int r; - - do - r = ioctl(fd, FIONBIO, &set); - while (r == -1 && errno == EINTR); - - if (r) - return -errno; - - return 0; -} - - -int uv__cloexec(int fd, int set) { - int r; - - do - r = ioctl(fd, set ? FIOCLEX : FIONCLEX); - while (r == -1 && errno == EINTR); - - if (r) - return -errno; - - return 0; -} - -#else /* !(defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)) */ - -int uv__nonblock(int fd, int set) { - int flags; - int r; - - do - r = fcntl(fd, F_GETFL); - while (r == -1 && errno == EINTR); - - if (r == -1) - return -errno; - - /* Bail out now if already set/clear. */ - if (!!(r & O_NONBLOCK) == !!set) - return 0; - - if (set) - flags = r | O_NONBLOCK; - else - flags = r & ~O_NONBLOCK; - - do - r = fcntl(fd, F_SETFL, flags); - while (r == -1 && errno == EINTR); - - if (r) - return -errno; - - return 0; -} - - -int uv__cloexec(int fd, int set) { - int flags; - int r; - - do - r = fcntl(fd, F_GETFD); - while (r == -1 && errno == EINTR); - - if (r == -1) - return -errno; - - /* Bail out now if already set/clear. */ - if (!!(r & FD_CLOEXEC) == !!set) - return 0; - - if (set) - flags = r | FD_CLOEXEC; - else - flags = r & ~FD_CLOEXEC; - - do - r = fcntl(fd, F_SETFD, flags); - while (r == -1 && errno == EINTR); - - if (r) - return -errno; - - return 0; -} - -#endif /* defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) */ - - -/* This function is not execve-safe, there is a race window - * between the call to dup() and fcntl(FD_CLOEXEC). - */ -int uv__dup(int fd) { - int err; - - fd = dup(fd); - - if (fd == -1) - return -errno; - - err = uv__cloexec(fd, 1); - if (err) { - uv__close(fd); - return err; - } - - return fd; -} - - -ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) { - struct cmsghdr* cmsg; - ssize_t rc; - int* pfd; - int* end; -#if defined(__linux__) - static int no_msg_cmsg_cloexec; - if (no_msg_cmsg_cloexec == 0) { - rc = recvmsg(fd, msg, flags | 0x40000000); /* MSG_CMSG_CLOEXEC */ - if (rc != -1) - return rc; - if (errno != EINVAL) - return -errno; - rc = recvmsg(fd, msg, flags); - if (rc == -1) - return -errno; - no_msg_cmsg_cloexec = 1; - } else { - rc = recvmsg(fd, msg, flags); - } -#else - rc = recvmsg(fd, msg, flags); -#endif - if (rc == -1) - return -errno; - if (msg->msg_controllen == 0) - return rc; - for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg)) - if (cmsg->cmsg_type == SCM_RIGHTS) - for (pfd = (int*) CMSG_DATA(cmsg), - end = (int*) ((char*) cmsg + cmsg->cmsg_len); - pfd < end; - pfd += 1) - uv__cloexec(*pfd, 1); - return rc; -} - - -int uv_cwd(char* buffer, size_t* size) { - if (buffer == NULL || size == NULL) - return -EINVAL; - - if (getcwd(buffer, *size) == NULL) - return -errno; - - *size = strlen(buffer); - if (*size > 1 && buffer[*size - 1] == '/') { - buffer[*size-1] = '\0'; - (*size)--; - } - - return 0; -} - - -int uv_chdir(const char* dir) { - if (chdir(dir)) - return -errno; - - return 0; -} - - -void uv_disable_stdio_inheritance(void) { - int fd; - - /* Set the CLOEXEC flag on all open descriptors. Unconditionally try the - * first 16 file descriptors. After that, bail out after the first error. - */ - for (fd = 0; ; fd++) - if (uv__cloexec(fd, 1) && fd > 15) - break; -} - - -int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd) { - int fd_out; - - switch (handle->type) { - case UV_TCP: - case UV_NAMED_PIPE: - case UV_TTY: - fd_out = uv__stream_fd((uv_stream_t*) handle); - break; - - case UV_UDP: - fd_out = ((uv_udp_t *) handle)->io_watcher.fd; - break; - - case UV_POLL: - fd_out = ((uv_poll_t *) handle)->io_watcher.fd; - break; - - default: - return -EINVAL; - } - - if (uv__is_closing(handle) || fd_out == -1) - return -EBADF; - - *fd = fd_out; - return 0; -} - - -static int uv__run_pending(uv_loop_t* loop) { - QUEUE* q; - uv__io_t* w; - - if (QUEUE_EMPTY(&loop->pending_queue)) - return 0; - - while (!QUEUE_EMPTY(&loop->pending_queue)) { - q = QUEUE_HEAD(&loop->pending_queue); - QUEUE_REMOVE(q); - QUEUE_INIT(q); - - w = QUEUE_DATA(q, uv__io_t, pending_queue); - w->cb(loop, w, UV__POLLOUT); - } - - return 1; -} - - -static unsigned int next_power_of_two(unsigned int val) { - val -= 1; - val |= val >> 1; - val |= val >> 2; - val |= val >> 4; - val |= val >> 8; - val |= val >> 16; - val += 1; - return val; -} - -static void maybe_resize(uv_loop_t* loop, unsigned int len) { - uv__io_t** watchers; - void* fake_watcher_list; - void* fake_watcher_count; - unsigned int nwatchers; - unsigned int i; - - if (len <= loop->nwatchers) - return; - - /* Preserve fake watcher list and count at the end of the watchers */ - if (loop->watchers != NULL) { - fake_watcher_list = loop->watchers[loop->nwatchers]; - fake_watcher_count = loop->watchers[loop->nwatchers + 1]; - } else { - fake_watcher_list = NULL; - fake_watcher_count = NULL; - } - - nwatchers = next_power_of_two(len + 2) - 2; - watchers = realloc(loop->watchers, - (nwatchers + 2) * sizeof(loop->watchers[0])); - - if (watchers == NULL) - abort(); - for (i = loop->nwatchers; i < nwatchers; i++) - watchers[i] = NULL; - watchers[nwatchers] = fake_watcher_list; - watchers[nwatchers + 1] = fake_watcher_count; - - loop->watchers = watchers; - loop->nwatchers = nwatchers; -} - - -void uv__io_init(uv__io_t* w, uv__io_cb cb, int fd) { - assert(cb != NULL); - assert(fd >= -1); - QUEUE_INIT(&w->pending_queue); - QUEUE_INIT(&w->watcher_queue); - w->cb = cb; - w->fd = fd; - w->events = 0; - w->pevents = 0; - -#if defined(UV_HAVE_KQUEUE) - w->rcount = 0; - w->wcount = 0; -#endif /* defined(UV_HAVE_KQUEUE) */ -} - - -void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) { - assert(0 == (events & ~(UV__POLLIN | UV__POLLOUT))); - assert(0 != events); - assert(w->fd >= 0); - assert(w->fd < INT_MAX); - - w->pevents |= events; - maybe_resize(loop, w->fd + 1); - -#if !defined(__sun) - /* The event ports backend needs to rearm all file descriptors on each and - * every tick of the event loop but the other backends allow us to - * short-circuit here if the event mask is unchanged. - */ - if (w->events == w->pevents) { - if (w->events == 0 && !QUEUE_EMPTY(&w->watcher_queue)) { - QUEUE_REMOVE(&w->watcher_queue); - QUEUE_INIT(&w->watcher_queue); - } - return; - } -#endif - - if (QUEUE_EMPTY(&w->watcher_queue)) - QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue); - - if (loop->watchers[w->fd] == NULL) { - loop->watchers[w->fd] = w; - loop->nfds++; - } -} - - -void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) { - assert(0 == (events & ~(UV__POLLIN | UV__POLLOUT))); - assert(0 != events); - - if (w->fd == -1) - return; - - assert(w->fd >= 0); - - /* Happens when uv__io_stop() is called on a handle that was never started. */ - if ((unsigned) w->fd >= loop->nwatchers) - return; - - w->pevents &= ~events; - - if (w->pevents == 0) { - QUEUE_REMOVE(&w->watcher_queue); - QUEUE_INIT(&w->watcher_queue); - - if (loop->watchers[w->fd] != NULL) { - assert(loop->watchers[w->fd] == w); - assert(loop->nfds > 0); - loop->watchers[w->fd] = NULL; - loop->nfds--; - w->events = 0; - } - } - else if (QUEUE_EMPTY(&w->watcher_queue)) - QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue); -} - - -void uv__io_close(uv_loop_t* loop, uv__io_t* w) { - uv__io_stop(loop, w, UV__POLLIN | UV__POLLOUT); - QUEUE_REMOVE(&w->pending_queue); - - /* Remove stale events for this file descriptor */ - uv__platform_invalidate_fd(loop, w->fd); -} - - -void uv__io_feed(uv_loop_t* loop, uv__io_t* w) { - if (QUEUE_EMPTY(&w->pending_queue)) - QUEUE_INSERT_TAIL(&loop->pending_queue, &w->pending_queue); -} - - -int uv__io_active(const uv__io_t* w, unsigned int events) { - assert(0 == (events & ~(UV__POLLIN | UV__POLLOUT))); - assert(0 != events); - return 0 != (w->pevents & events); -} - - -int uv_getrusage(uv_rusage_t* rusage) { - struct rusage usage; - - if (getrusage(RUSAGE_SELF, &usage)) - return -errno; - - rusage->ru_utime.tv_sec = usage.ru_utime.tv_sec; - rusage->ru_utime.tv_usec = usage.ru_utime.tv_usec; - - rusage->ru_stime.tv_sec = usage.ru_stime.tv_sec; - rusage->ru_stime.tv_usec = usage.ru_stime.tv_usec; - - rusage->ru_maxrss = usage.ru_maxrss; - rusage->ru_ixrss = usage.ru_ixrss; - rusage->ru_idrss = usage.ru_idrss; - rusage->ru_isrss = usage.ru_isrss; - rusage->ru_minflt = usage.ru_minflt; - rusage->ru_majflt = usage.ru_majflt; - rusage->ru_nswap = usage.ru_nswap; - rusage->ru_inblock = usage.ru_inblock; - rusage->ru_oublock = usage.ru_oublock; - rusage->ru_msgsnd = usage.ru_msgsnd; - rusage->ru_msgrcv = usage.ru_msgrcv; - rusage->ru_nsignals = usage.ru_nsignals; - rusage->ru_nvcsw = usage.ru_nvcsw; - rusage->ru_nivcsw = usage.ru_nivcsw; - - return 0; -} - - -int uv__open_cloexec(const char* path, int flags) { - int err; - int fd; - -#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 9) - static int no_cloexec; - - if (!no_cloexec) { - fd = open(path, flags | UV__O_CLOEXEC); - if (fd != -1) - return fd; - - if (errno != EINVAL) - return -errno; - - /* O_CLOEXEC not supported. */ - no_cloexec = 1; - } -#endif - - fd = open(path, flags); - if (fd == -1) - return -errno; - - err = uv__cloexec(fd, 1); - if (err) { - uv__close(fd); - return err; - } - - return fd; -} - - -int uv__dup2_cloexec(int oldfd, int newfd) { - int r; -#if defined(__FreeBSD__) && __FreeBSD__ >= 10 - do - r = dup3(oldfd, newfd, O_CLOEXEC); - while (r == -1 && errno == EINTR); - if (r == -1) - return -errno; - return r; -#elif defined(__FreeBSD__) && defined(F_DUP2FD_CLOEXEC) - do - r = fcntl(oldfd, F_DUP2FD_CLOEXEC, newfd); - while (r == -1 && errno == EINTR); - if (r != -1) - return r; - if (errno != EINVAL) - return -errno; - /* Fall through. */ -#elif defined(__linux__) - static int no_dup3; - if (!no_dup3) { - do - r = uv__dup3(oldfd, newfd, UV__O_CLOEXEC); - while (r == -1 && (errno == EINTR || errno == EBUSY)); - if (r != -1) - return r; - if (errno != ENOSYS) - return -errno; - /* Fall through. */ - no_dup3 = 1; - } -#endif - { - int err; - do - r = dup2(oldfd, newfd); -#if defined(__linux__) - while (r == -1 && (errno == EINTR || errno == EBUSY)); -#else - while (r == -1 && errno == EINTR); -#endif - - if (r == -1) - return -errno; - - err = uv__cloexec(newfd, 1); - if (err) { - uv__close(newfd); - return err; - } - - return r; - } -} diff --git a/libuv/src/unix/darwin-proctitle.c b/libuv/src/unix/darwin-proctitle.c deleted file mode 100644 index 1142311..0000000 --- a/libuv/src/unix/darwin-proctitle.c +++ /dev/null @@ -1,206 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include - -#include - -#if !TARGET_OS_IPHONE -# include -# include -#endif - - -static int uv__pthread_setname_np(const char* name) { - int (*dynamic_pthread_setname_np)(const char* name); - char namebuf[64]; /* MAXTHREADNAMESIZE */ - int err; - - /* pthread_setname_np() first appeared in OS X 10.6 and iOS 3.2. */ - *(void **)(&dynamic_pthread_setname_np) = - dlsym(RTLD_DEFAULT, "pthread_setname_np"); - - if (dynamic_pthread_setname_np == NULL) - return -ENOSYS; - - strncpy(namebuf, name, sizeof(namebuf) - 1); - namebuf[sizeof(namebuf) - 1] = '\0'; - - err = dynamic_pthread_setname_np(namebuf); - if (err) - return -err; - - return 0; -} - - -int uv__set_process_title(const char* title) { -#if TARGET_OS_IPHONE - return uv__pthread_setname_np(title); -#else - CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef, - const char*, - CFStringEncoding); - CFBundleRef (*pCFBundleGetBundleWithIdentifier)(CFStringRef); - void *(*pCFBundleGetDataPointerForName)(CFBundleRef, CFStringRef); - void *(*pCFBundleGetFunctionPointerForName)(CFBundleRef, CFStringRef); - CFTypeRef (*pLSGetCurrentApplicationASN)(void); - OSStatus (*pLSSetApplicationInformationItem)(int, - CFTypeRef, - CFStringRef, - CFStringRef, - CFDictionaryRef*); - void* application_services_handle; - void* core_foundation_handle; - CFBundleRef launch_services_bundle; - CFStringRef* display_name_key; - CFDictionaryRef (*pCFBundleGetInfoDictionary)(CFBundleRef); - CFBundleRef (*pCFBundleGetMainBundle)(void); - CFBundleRef hi_services_bundle; - OSStatus (*pSetApplicationIsDaemon)(int); - CFDictionaryRef (*pLSApplicationCheckIn)(int, CFDictionaryRef); - void (*pLSSetApplicationLaunchServicesServerConnectionStatus)(uint64_t, - void*); - CFTypeRef asn; - int err; - - err = -ENOENT; - application_services_handle = dlopen("/System/Library/Frameworks/" - "ApplicationServices.framework/" - "Versions/A/ApplicationServices", - RTLD_LAZY | RTLD_LOCAL); - core_foundation_handle = dlopen("/System/Library/Frameworks/" - "CoreFoundation.framework/" - "Versions/A/CoreFoundation", - RTLD_LAZY | RTLD_LOCAL); - - if (application_services_handle == NULL || core_foundation_handle == NULL) - goto out; - - *(void **)(&pCFStringCreateWithCString) = - dlsym(core_foundation_handle, "CFStringCreateWithCString"); - *(void **)(&pCFBundleGetBundleWithIdentifier) = - dlsym(core_foundation_handle, "CFBundleGetBundleWithIdentifier"); - *(void **)(&pCFBundleGetDataPointerForName) = - dlsym(core_foundation_handle, "CFBundleGetDataPointerForName"); - *(void **)(&pCFBundleGetFunctionPointerForName) = - dlsym(core_foundation_handle, "CFBundleGetFunctionPointerForName"); - - if (pCFStringCreateWithCString == NULL || - pCFBundleGetBundleWithIdentifier == NULL || - pCFBundleGetDataPointerForName == NULL || - pCFBundleGetFunctionPointerForName == NULL) { - goto out; - } - -#define S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8) - - launch_services_bundle = - pCFBundleGetBundleWithIdentifier(S("com.apple.LaunchServices")); - - if (launch_services_bundle == NULL) - goto out; - - *(void **)(&pLSGetCurrentApplicationASN) = - pCFBundleGetFunctionPointerForName(launch_services_bundle, - S("_LSGetCurrentApplicationASN")); - - if (pLSGetCurrentApplicationASN == NULL) - goto out; - - *(void **)(&pLSSetApplicationInformationItem) = - pCFBundleGetFunctionPointerForName(launch_services_bundle, - S("_LSSetApplicationInformationItem")); - - if (pLSSetApplicationInformationItem == NULL) - goto out; - - display_name_key = pCFBundleGetDataPointerForName(launch_services_bundle, - S("_kLSDisplayNameKey")); - - if (display_name_key == NULL || *display_name_key == NULL) - goto out; - - *(void **)(&pCFBundleGetInfoDictionary) = dlsym(core_foundation_handle, - "CFBundleGetInfoDictionary"); - *(void **)(&pCFBundleGetMainBundle) = dlsym(core_foundation_handle, - "CFBundleGetMainBundle"); - if (pCFBundleGetInfoDictionary == NULL || pCFBundleGetMainBundle == NULL) - goto out; - - /* Black 10.9 magic, to remove (Not responding) mark in Activity Monitor */ - hi_services_bundle = - pCFBundleGetBundleWithIdentifier(S("com.apple.HIServices")); - err = -ENOENT; - if (hi_services_bundle == NULL) - goto out; - - *(void **)(&pSetApplicationIsDaemon) = pCFBundleGetFunctionPointerForName( - hi_services_bundle, - S("SetApplicationIsDaemon")); - *(void **)(&pLSApplicationCheckIn) = pCFBundleGetFunctionPointerForName( - launch_services_bundle, - S("_LSApplicationCheckIn")); - *(void **)(&pLSSetApplicationLaunchServicesServerConnectionStatus) = - pCFBundleGetFunctionPointerForName( - launch_services_bundle, - S("_LSSetApplicationLaunchServicesServerConnectionStatus")); - if (pSetApplicationIsDaemon == NULL || - pLSApplicationCheckIn == NULL || - pLSSetApplicationLaunchServicesServerConnectionStatus == NULL) { - goto out; - } - - if (pSetApplicationIsDaemon(1) != noErr) - goto out; - - pLSSetApplicationLaunchServicesServerConnectionStatus(0, NULL); - - /* Check into process manager?! */ - pLSApplicationCheckIn(-2, - pCFBundleGetInfoDictionary(pCFBundleGetMainBundle())); - - asn = pLSGetCurrentApplicationASN(); - - err = -EINVAL; - if (pLSSetApplicationInformationItem(-2, /* Magic value. */ - asn, - *display_name_key, - S(title), - NULL) != noErr) { - goto out; - } - - uv__pthread_setname_np(title); /* Don't care if it fails. */ - err = 0; - -out: - if (core_foundation_handle != NULL) - dlclose(core_foundation_handle); - - if (application_services_handle != NULL) - dlclose(application_services_handle); - - return err; -#endif /* !TARGET_OS_IPHONE */ -} diff --git a/libuv/src/unix/darwin.c b/libuv/src/unix/darwin.c deleted file mode 100644 index d276ada..0000000 --- a/libuv/src/unix/darwin.c +++ /dev/null @@ -1,331 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include /* _NSGetExecutablePath */ -#include -#include -#include /* sysconf */ - - -int uv__platform_loop_init(uv_loop_t* loop) { - loop->cf_state = NULL; - - if (uv__kqueue_init(loop)) - return -errno; - - return 0; -} - - -void uv__platform_loop_delete(uv_loop_t* loop) { - uv__fsevents_loop_delete(loop); -} - - -uint64_t uv__hrtime(uv_clocktype_t type) { - static mach_timebase_info_data_t info; - - if ((ACCESS_ONCE(uint32_t, info.numer) == 0 || - ACCESS_ONCE(uint32_t, info.denom) == 0) && - mach_timebase_info(&info) != KERN_SUCCESS) - abort(); - - return mach_absolute_time() * info.numer / info.denom; -} - - -int uv_exepath(char* buffer, size_t* size) { - /* realpath(exepath) may be > PATH_MAX so double it to be on the safe side. */ - char abspath[PATH_MAX * 2 + 1]; - char exepath[PATH_MAX + 1]; - uint32_t exepath_size; - size_t abspath_size; - - if (buffer == NULL || size == NULL || *size == 0) - return -EINVAL; - - exepath_size = sizeof(exepath); - if (_NSGetExecutablePath(exepath, &exepath_size)) - return -EIO; - - if (realpath(exepath, abspath) != abspath) - return -errno; - - abspath_size = strlen(abspath); - if (abspath_size == 0) - return -EIO; - - *size -= 1; - if (*size > abspath_size) - *size = abspath_size; - - memcpy(buffer, abspath, *size); - buffer[*size] = '\0'; - - return 0; -} - - -uint64_t uv_get_free_memory(void) { - vm_statistics_data_t info; - mach_msg_type_number_t count = sizeof(info) / sizeof(integer_t); - - if (host_statistics(mach_host_self(), HOST_VM_INFO, - (host_info_t)&info, &count) != KERN_SUCCESS) { - return -EINVAL; /* FIXME(bnoordhuis) Translate error. */ - } - - return (uint64_t) info.free_count * sysconf(_SC_PAGESIZE); -} - - -uint64_t uv_get_total_memory(void) { - uint64_t info; - int which[] = {CTL_HW, HW_MEMSIZE}; - size_t size = sizeof(info); - - if (sysctl(which, 2, &info, &size, NULL, 0)) - return -errno; - - return (uint64_t) info; -} - - -void uv_loadavg(double avg[3]) { - struct loadavg info; - size_t size = sizeof(info); - int which[] = {CTL_VM, VM_LOADAVG}; - - if (sysctl(which, 2, &info, &size, NULL, 0) < 0) return; - - avg[0] = (double) info.ldavg[0] / info.fscale; - avg[1] = (double) info.ldavg[1] / info.fscale; - avg[2] = (double) info.ldavg[2] / info.fscale; -} - - -int uv_resident_set_memory(size_t* rss) { - mach_msg_type_number_t count; - task_basic_info_data_t info; - kern_return_t err; - - count = TASK_BASIC_INFO_COUNT; - err = task_info(mach_task_self(), - TASK_BASIC_INFO, - (task_info_t) &info, - &count); - (void) &err; - /* task_info(TASK_BASIC_INFO) cannot really fail. Anything other than - * KERN_SUCCESS implies a libuv bug. - */ - assert(err == KERN_SUCCESS); - *rss = info.resident_size; - - return 0; -} - - -int uv_uptime(double* uptime) { - time_t now; - struct timeval info; - size_t size = sizeof(info); - static int which[] = {CTL_KERN, KERN_BOOTTIME}; - - if (sysctl(which, 2, &info, &size, NULL, 0)) - return -errno; - - now = time(NULL); - *uptime = now - info.tv_sec; - - return 0; -} - -int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { - unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK), - multiplier = ((uint64_t)1000L / ticks); - char model[512]; - uint64_t cpuspeed; - size_t size; - unsigned int i; - natural_t numcpus; - mach_msg_type_number_t msg_type; - processor_cpu_load_info_data_t *info; - uv_cpu_info_t* cpu_info; - - size = sizeof(model); - if (sysctlbyname("machdep.cpu.brand_string", &model, &size, NULL, 0) && - sysctlbyname("hw.model", &model, &size, NULL, 0)) { - return -errno; - } - - size = sizeof(cpuspeed); - if (sysctlbyname("hw.cpufrequency", &cpuspeed, &size, NULL, 0)) - return -errno; - - if (host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numcpus, - (processor_info_array_t*)&info, - &msg_type) != KERN_SUCCESS) { - return -EINVAL; /* FIXME(bnoordhuis) Translate error. */ - } - - *cpu_infos = malloc(numcpus * sizeof(**cpu_infos)); - if (!(*cpu_infos)) - return -ENOMEM; /* FIXME(bnoordhuis) Deallocate info? */ - - *count = numcpus; - - for (i = 0; i < numcpus; i++) { - cpu_info = &(*cpu_infos)[i]; - - cpu_info->cpu_times.user = (uint64_t)(info[i].cpu_ticks[0]) * multiplier; - cpu_info->cpu_times.nice = (uint64_t)(info[i].cpu_ticks[3]) * multiplier; - cpu_info->cpu_times.sys = (uint64_t)(info[i].cpu_ticks[1]) * multiplier; - cpu_info->cpu_times.idle = (uint64_t)(info[i].cpu_ticks[2]) * multiplier; - cpu_info->cpu_times.irq = 0; - - cpu_info->model = strdup(model); - cpu_info->speed = cpuspeed/1000000; - } - vm_deallocate(mach_task_self(), (vm_address_t)info, msg_type); - - return 0; -} - - -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - int i; - - for (i = 0; i < count; i++) { - free(cpu_infos[i].model); - } - - free(cpu_infos); -} - - -int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { - struct ifaddrs *addrs, *ent; - uv_interface_address_t* address; - int i; - struct sockaddr_dl *sa_addr; - - if (getifaddrs(&addrs)) - return -errno; - - *count = 0; - - /* Count the number of interfaces */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family == AF_LINK)) { - continue; - } - - (*count)++; - } - - *addresses = malloc(*count * sizeof(**addresses)); - if (!(*addresses)) - return -ENOMEM; - - address = *addresses; - - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) - continue; - - if (ent->ifa_addr == NULL) - continue; - - /* - * On Mac OS X getifaddrs returns information related to Mac Addresses for - * various devices, such as firewire, etc. These are not relevant here. - */ - if (ent->ifa_addr->sa_family == AF_LINK) - continue; - - address->name = strdup(ent->ifa_name); - - if (ent->ifa_addr->sa_family == AF_INET6) { - address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr); - } else { - address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr); - } - - if (ent->ifa_netmask->sa_family == AF_INET6) { - address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask); - } else { - address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask); - } - - address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK); - - address++; - } - - /* Fill in physical addresses for each interface */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family != AF_LINK)) { - continue; - } - - address = *addresses; - - for (i = 0; i < (*count); i++) { - if (strcmp(address->name, ent->ifa_name) == 0) { - sa_addr = (struct sockaddr_dl*)(ent->ifa_addr); - memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); - } - address++; - } - } - - freeifaddrs(addrs); - - return 0; -} - - -void uv_free_interface_addresses(uv_interface_address_t* addresses, - int count) { - int i; - - for (i = 0; i < count; i++) { - free(addresses[i].name); - } - - free(addresses); -} diff --git a/libuv/src/unix/dl.c b/libuv/src/unix/dl.c deleted file mode 100644 index ad45fc8..0000000 --- a/libuv/src/unix/dl.c +++ /dev/null @@ -1,83 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include - -static int uv__dlerror(uv_lib_t* lib); - - -int uv_dlopen(const char* filename, uv_lib_t* lib) { - dlerror(); /* Reset error status. */ - lib->errmsg = NULL; - lib->handle = dlopen(filename, RTLD_LAZY); - return lib->handle ? 0 : uv__dlerror(lib); -} - - -void uv_dlclose(uv_lib_t* lib) { - if (lib->errmsg) { - free(lib->errmsg); - lib->errmsg = NULL; - } - - if (lib->handle) { - /* Ignore errors. No good way to signal them without leaking memory. */ - dlclose(lib->handle); - lib->handle = NULL; - } -} - - -int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr) { - dlerror(); /* Reset error status. */ - *ptr = dlsym(lib->handle, name); - return uv__dlerror(lib); -} - - -const char* uv_dlerror(const uv_lib_t* lib) { - return lib->errmsg ? lib->errmsg : "no error"; -} - - -static int uv__dlerror(uv_lib_t* lib) { - const char* errmsg; - - if (lib->errmsg) - free(lib->errmsg); - - errmsg = dlerror(); - - if (errmsg) { - lib->errmsg = strdup(errmsg); - return -1; - } - else { - lib->errmsg = NULL; - return 0; - } -} diff --git a/libuv/src/unix/freebsd.c b/libuv/src/unix/freebsd.c deleted file mode 100644 index 2dbb1ec..0000000 --- a/libuv/src/unix/freebsd.c +++ /dev/null @@ -1,435 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include /* VM_LOADAVG */ -#include -#include -#include /* sysconf */ -#include - -#undef NANOSEC -#define NANOSEC ((uint64_t) 1e9) - -#ifndef CPUSTATES -# define CPUSTATES 5U -#endif -#ifndef CP_USER -# define CP_USER 0 -# define CP_NICE 1 -# define CP_SYS 2 -# define CP_IDLE 3 -# define CP_INTR 4 -#endif - -static char *process_title; - - -int uv__platform_loop_init(uv_loop_t* loop) { - return uv__kqueue_init(loop); -} - - -void uv__platform_loop_delete(uv_loop_t* loop) { -} - - -uint64_t uv__hrtime(uv_clocktype_t type) { - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec); -} - - -int uv_exepath(char* buffer, size_t* size) { - char abspath[PATH_MAX * 2 + 1]; - int mib[4]; - size_t abspath_size; - - if (buffer == NULL || size == NULL || *size == 0) - return -EINVAL; - -#ifdef __DragonFly__ - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_ARGS; - mib[3] = getpid(); -#else - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PATHNAME; - mib[3] = -1; -#endif - - abspath_size = sizeof abspath;; - if (sysctl(mib, 4, abspath, &abspath_size, NULL, 0)) - return -errno; - - assert(abspath_size > 0); - abspath_size -= 1; - *size -= 1; - - if (*size > abspath_size) - *size = abspath_size; - - memcpy(buffer, abspath, *size); - buffer[*size] = '\0'; - - return 0; -} - - -uint64_t uv_get_free_memory(void) { - int freecount; - size_t size = sizeof(freecount); - - if (sysctlbyname("vm.stats.vm.v_free_count", &freecount, &size, NULL, 0)) - return -errno; - - return (uint64_t) freecount * sysconf(_SC_PAGESIZE); - -} - - -uint64_t uv_get_total_memory(void) { - unsigned long info; - int which[] = {CTL_HW, HW_PHYSMEM}; - - size_t size = sizeof(info); - - if (sysctl(which, 2, &info, &size, NULL, 0)) - return -errno; - - return (uint64_t) info; -} - - -void uv_loadavg(double avg[3]) { - struct loadavg info; - size_t size = sizeof(info); - int which[] = {CTL_VM, VM_LOADAVG}; - - if (sysctl(which, 2, &info, &size, NULL, 0) < 0) return; - - avg[0] = (double) info.ldavg[0] / info.fscale; - avg[1] = (double) info.ldavg[1] / info.fscale; - avg[2] = (double) info.ldavg[2] / info.fscale; -} - - -char** uv_setup_args(int argc, char** argv) { - process_title = argc ? strdup(argv[0]) : NULL; - return argv; -} - - -int uv_set_process_title(const char* title) { - int oid[4]; - - if (process_title) free(process_title); - process_title = strdup(title); - - oid[0] = CTL_KERN; - oid[1] = KERN_PROC; - oid[2] = KERN_PROC_ARGS; - oid[3] = getpid(); - - sysctl(oid, - ARRAY_SIZE(oid), - NULL, - NULL, - process_title, - strlen(process_title) + 1); - - return 0; -} - - -int uv_get_process_title(char* buffer, size_t size) { - if (process_title) { - strncpy(buffer, process_title, size); - } else { - if (size > 0) { - buffer[0] = '\0'; - } - } - - return 0; -} - - -int uv_resident_set_memory(size_t* rss) { - kvm_t *kd = NULL; - struct kinfo_proc *kinfo = NULL; - pid_t pid; - int nprocs; - size_t page_size = getpagesize(); - - pid = getpid(); - - kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "kvm_open"); - if (kd == NULL) goto error; - - kinfo = kvm_getprocs(kd, KERN_PROC_PID, pid, &nprocs); - if (kinfo == NULL) goto error; - -#ifdef __DragonFly__ - *rss = kinfo->kp_vm_rssize * page_size; -#else - *rss = kinfo->ki_rssize * page_size; -#endif - - kvm_close(kd); - - return 0; - -error: - if (kd) kvm_close(kd); - return -EPERM; -} - - -int uv_uptime(double* uptime) { - time_t now; - struct timeval info; - size_t size = sizeof(info); - static int which[] = {CTL_KERN, KERN_BOOTTIME}; - - if (sysctl(which, 2, &info, &size, NULL, 0)) - return -errno; - - now = time(NULL); - - *uptime = (double)(now - info.tv_sec); - return 0; -} - - -int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { - unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK), - multiplier = ((uint64_t)1000L / ticks), cpuspeed, maxcpus, - cur = 0; - uv_cpu_info_t* cpu_info; - const char* maxcpus_key; - const char* cptimes_key; - char model[512]; - long* cp_times; - int numcpus; - size_t size; - int i; - -#if defined(__DragonFly__) - /* This is not quite correct but DragonFlyBSD doesn't seem to have anything - * comparable to kern.smp.maxcpus or kern.cp_times (kern.cp_time is a total, - * not per CPU). At least this stops uv_cpu_info() from failing completely. - */ - maxcpus_key = "hw.ncpu"; - cptimes_key = "kern.cp_time"; -#else - maxcpus_key = "kern.smp.maxcpus"; - cptimes_key = "kern.cp_times"; -#endif - - size = sizeof(model); - if (sysctlbyname("hw.model", &model, &size, NULL, 0)) - return -errno; - - size = sizeof(numcpus); - if (sysctlbyname("hw.ncpu", &numcpus, &size, NULL, 0)) - return -errno; - - *cpu_infos = malloc(numcpus * sizeof(**cpu_infos)); - if (!(*cpu_infos)) - return -ENOMEM; - - *count = numcpus; - - size = sizeof(cpuspeed); - if (sysctlbyname("hw.clockrate", &cpuspeed, &size, NULL, 0)) { - SAVE_ERRNO(free(*cpu_infos)); - return -errno; - } - - /* kern.cp_times on FreeBSD i386 gives an array up to maxcpus instead of - * ncpu. - */ - size = sizeof(maxcpus); - if (sysctlbyname(maxcpus_key, &maxcpus, &size, NULL, 0)) { - SAVE_ERRNO(free(*cpu_infos)); - return -errno; - } - - size = maxcpus * CPUSTATES * sizeof(long); - - cp_times = malloc(size); - if (cp_times == NULL) { - free(*cpu_infos); - return -ENOMEM; - } - - if (sysctlbyname(cptimes_key, cp_times, &size, NULL, 0)) { - SAVE_ERRNO(free(cp_times)); - SAVE_ERRNO(free(*cpu_infos)); - return -errno; - } - - for (i = 0; i < numcpus; i++) { - cpu_info = &(*cpu_infos)[i]; - - cpu_info->cpu_times.user = (uint64_t)(cp_times[CP_USER+cur]) * multiplier; - cpu_info->cpu_times.nice = (uint64_t)(cp_times[CP_NICE+cur]) * multiplier; - cpu_info->cpu_times.sys = (uint64_t)(cp_times[CP_SYS+cur]) * multiplier; - cpu_info->cpu_times.idle = (uint64_t)(cp_times[CP_IDLE+cur]) * multiplier; - cpu_info->cpu_times.irq = (uint64_t)(cp_times[CP_INTR+cur]) * multiplier; - - cpu_info->model = strdup(model); - cpu_info->speed = cpuspeed; - - cur+=CPUSTATES; - } - - free(cp_times); - return 0; -} - - -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - int i; - - for (i = 0; i < count; i++) { - free(cpu_infos[i].model); - } - - free(cpu_infos); -} - - -int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { - struct ifaddrs *addrs, *ent; - uv_interface_address_t* address; - int i; - struct sockaddr_dl *sa_addr; - - if (getifaddrs(&addrs)) - return -errno; - - *count = 0; - - /* Count the number of interfaces */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family == AF_LINK)) { - continue; - } - - (*count)++; - } - - *addresses = malloc(*count * sizeof(**addresses)); - if (!(*addresses)) - return -ENOMEM; - - address = *addresses; - - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) - continue; - - if (ent->ifa_addr == NULL) - continue; - - /* - * On FreeBSD getifaddrs returns information related to the raw underlying - * devices. We're not interested in this information yet. - */ - if (ent->ifa_addr->sa_family == AF_LINK) - continue; - - address->name = strdup(ent->ifa_name); - - if (ent->ifa_addr->sa_family == AF_INET6) { - address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr); - } else { - address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr); - } - - if (ent->ifa_netmask->sa_family == AF_INET6) { - address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask); - } else { - address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask); - } - - address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK); - - address++; - } - - /* Fill in physical addresses for each interface */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family != AF_LINK)) { - continue; - } - - address = *addresses; - - for (i = 0; i < (*count); i++) { - if (strcmp(address->name, ent->ifa_name) == 0) { - sa_addr = (struct sockaddr_dl*)(ent->ifa_addr); - memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); - } - address++; - } - } - - freeifaddrs(addrs); - - return 0; -} - - -void uv_free_interface_addresses(uv_interface_address_t* addresses, - int count) { - int i; - - for (i = 0; i < count; i++) { - free(addresses[i].name); - } - - free(addresses); -} diff --git a/libuv/src/unix/fs.c b/libuv/src/unix/fs.c deleted file mode 100644 index e7eee2f..0000000 --- a/libuv/src/unix/fs.c +++ /dev/null @@ -1,1170 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* Caveat emptor: this file deviates from the libuv convention of returning - * negated errno codes. Most uv_fs_*() functions map directly to the system - * call of the same name. For more complex wrappers, it's easier to just - * return -1 with errno set. The dispatcher in uv__fs_work() takes care of - * getting the errno to the right place (req->result or as the return value.) - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(__DragonFly__) || \ - defined(__FreeBSD__) || \ - defined(__OpenBSD__) || \ - defined(__NetBSD__) -# define HAVE_PREADV 1 -#else -# define HAVE_PREADV 0 -#endif - -#if defined(__linux__) || defined(__sun) -# include -#endif - -#define INIT(type) \ - do { \ - uv__req_init((loop), (req), UV_FS); \ - (req)->fs_type = UV_FS_ ## type; \ - (req)->result = 0; \ - (req)->ptr = NULL; \ - (req)->loop = loop; \ - (req)->path = NULL; \ - (req)->new_path = NULL; \ - (req)->cb = (cb); \ - } \ - while (0) - -#define PATH \ - do { \ - (req)->path = strdup(path); \ - if ((req)->path == NULL) \ - return -ENOMEM; \ - } \ - while (0) - -#define PATH2 \ - do { \ - size_t path_len; \ - size_t new_path_len; \ - path_len = strlen((path)) + 1; \ - new_path_len = strlen((new_path)) + 1; \ - (req)->path = malloc(path_len + new_path_len); \ - if ((req)->path == NULL) \ - return -ENOMEM; \ - (req)->new_path = (req)->path + path_len; \ - memcpy((void*) (req)->path, (path), path_len); \ - memcpy((void*) (req)->new_path, (new_path), new_path_len); \ - } \ - while (0) - -#define POST \ - do { \ - if ((cb) != NULL) { \ - uv__work_submit((loop), &(req)->work_req, uv__fs_work, uv__fs_done); \ - return 0; \ - } \ - else { \ - uv__fs_work(&(req)->work_req); \ - uv__fs_done(&(req)->work_req, 0); \ - return (req)->result; \ - } \ - } \ - while (0) - - -static ssize_t uv__fs_fdatasync(uv_fs_t* req) { -#if defined(__linux__) || defined(__sun) || defined(__NetBSD__) - return fdatasync(req->file); -#elif defined(__APPLE__) && defined(F_FULLFSYNC) - return fcntl(req->file, F_FULLFSYNC); -#else - return fsync(req->file); -#endif -} - - -static ssize_t uv__fs_futime(uv_fs_t* req) { -#if defined(__linux__) - /* utimesat() has nanosecond resolution but we stick to microseconds - * for the sake of consistency with other platforms. - */ - static int no_utimesat; - struct timespec ts[2]; - struct timeval tv[2]; - char path[sizeof("/proc/self/fd/") + 3 * sizeof(int)]; - int r; - - if (no_utimesat) - goto skip; - - ts[0].tv_sec = req->atime; - ts[0].tv_nsec = (unsigned long)(req->atime * 1000000) % 1000000 * 1000; - ts[1].tv_sec = req->mtime; - ts[1].tv_nsec = (unsigned long)(req->mtime * 1000000) % 1000000 * 1000; - - r = uv__utimesat(req->file, NULL, ts, 0); - if (r == 0) - return r; - - if (errno != ENOSYS) - return r; - - no_utimesat = 1; - -skip: - - tv[0].tv_sec = req->atime; - tv[0].tv_usec = (unsigned long)(req->atime * 1000000) % 1000000; - tv[1].tv_sec = req->mtime; - tv[1].tv_usec = (unsigned long)(req->mtime * 1000000) % 1000000; - snprintf(path, sizeof(path), "/proc/self/fd/%d", (int) req->file); - - r = utimes(path, tv); - if (r == 0) - return r; - - switch (errno) { - case ENOENT: - if (fcntl(req->file, F_GETFL) == -1 && errno == EBADF) - break; - /* Fall through. */ - - case EACCES: - case ENOTDIR: - errno = ENOSYS; - break; - } - - return r; - -#elif defined(__APPLE__) \ - || defined(__DragonFly__) \ - || defined(__FreeBSD__) \ - || defined(__NetBSD__) \ - || defined(__OpenBSD__) \ - || defined(__sun) - struct timeval tv[2]; - tv[0].tv_sec = req->atime; - tv[0].tv_usec = (unsigned long)(req->atime * 1000000) % 1000000; - tv[1].tv_sec = req->mtime; - tv[1].tv_usec = (unsigned long)(req->mtime * 1000000) % 1000000; -# if defined(__sun) - return futimesat(req->file, NULL, tv); -# else - return futimes(req->file, tv); -# endif -#else - errno = ENOSYS; - return -1; -#endif -} - - -static ssize_t uv__fs_mkdtemp(uv_fs_t* req) { - return mkdtemp((char*) req->path) ? 0 : -1; -} - - -static ssize_t uv__fs_read(uv_fs_t* req) { -#if defined(__linux__) - static int no_preadv; -#endif - ssize_t result; - -#if defined(_AIX) - struct stat buf; - if(fstat(req->file, &buf)) - return -1; - if(S_ISDIR(buf.st_mode)) { - errno = EISDIR; - return -1; - } -#endif /* defined(_AIX) */ - if (req->off < 0) { - if (req->nbufs == 1) - result = read(req->file, req->bufs[0].base, req->bufs[0].len); - else - result = readv(req->file, (struct iovec*) req->bufs, req->nbufs); - } else { - if (req->nbufs == 1) { - result = pread(req->file, req->bufs[0].base, req->bufs[0].len, req->off); - goto done; - } - -#if HAVE_PREADV - result = preadv(req->file, (struct iovec*) req->bufs, req->nbufs, req->off); -#else -# if defined(__linux__) - if (no_preadv) retry: -# endif - { - off_t nread; - size_t index; - - nread = 0; - index = 0; - result = 1; - do { - if (req->bufs[index].len > 0) { - result = pread(req->file, - req->bufs[index].base, - req->bufs[index].len, - req->off + nread); - if (result > 0) - nread += result; - } - index++; - } while (index < req->nbufs && result > 0); - if (nread > 0) - result = nread; - } -# if defined(__linux__) - else { - result = uv__preadv(req->file, - (struct iovec*)req->bufs, - req->nbufs, - req->off); - if (result == -1 && errno == ENOSYS) { - no_preadv = 1; - goto retry; - } - } -# endif -#endif - } - -done: - if (req->bufs != req->bufsml) - free(req->bufs); - return result; -} - - -#if defined(__OpenBSD__) || (defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_8)) -static int uv__fs_scandir_filter(uv__dirent_t* dent) { -#else -static int uv__fs_scandir_filter(const uv__dirent_t* dent) { -#endif - return strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0; -} - - -static ssize_t uv__fs_scandir(uv_fs_t* req) { - uv__dirent_t **dents; - int saved_errno; - int n; - - dents = NULL; - n = scandir(req->path, &dents, uv__fs_scandir_filter, alphasort); - - /* NOTE: We will use nbufs as an index field */ - req->nbufs = 0; - - if (n == 0) - goto out; /* osx still needs to deallocate some memory */ - else if (n == -1) - return n; - - req->ptr = dents; - - return n; - -out: - saved_errno = errno; - if (dents != NULL) { - int i; - - for (i = 0; i < n; i++) - free(dents[i]); - free(dents); - } - errno = saved_errno; - - req->ptr = NULL; - - return n; -} - - -static ssize_t uv__fs_readlink(uv_fs_t* req) { - ssize_t len; - char* buf; - - len = pathconf(req->path, _PC_PATH_MAX); - - if (len == -1) { -#if defined(PATH_MAX) - len = PATH_MAX; -#else - len = 4096; -#endif - } - - buf = malloc(len + 1); - - if (buf == NULL) { - errno = ENOMEM; - return -1; - } - - len = readlink(req->path, buf, len); - - if (len == -1) { - free(buf); - return -1; - } - - buf[len] = '\0'; - req->ptr = buf; - - return 0; -} - - -static ssize_t uv__fs_sendfile_emul(uv_fs_t* req) { - struct pollfd pfd; - int use_pread; - off_t offset; - ssize_t nsent; - ssize_t nread; - ssize_t nwritten; - size_t buflen; - size_t len; - ssize_t n; - int in_fd; - int out_fd; - char buf[8192]; - - len = req->bufsml[0].len; - in_fd = req->flags; - out_fd = req->file; - offset = req->off; - use_pread = 1; - - /* Here are the rules regarding errors: - * - * 1. Read errors are reported only if nsent==0, otherwise we return nsent. - * The user needs to know that some data has already been sent, to stop - * them from sending it twice. - * - * 2. Write errors are always reported. Write errors are bad because they - * mean data loss: we've read data but now we can't write it out. - * - * We try to use pread() and fall back to regular read() if the source fd - * doesn't support positional reads, for example when it's a pipe fd. - * - * If we get EAGAIN when writing to the target fd, we poll() on it until - * it becomes writable again. - * - * FIXME: If we get a write error when use_pread==1, it should be safe to - * return the number of sent bytes instead of an error because pread() - * is, in theory, idempotent. However, special files in /dev or /proc - * may support pread() but not necessarily return the same data on - * successive reads. - * - * FIXME: There is no way now to signal that we managed to send *some* data - * before a write error. - */ - for (nsent = 0; (size_t) nsent < len; ) { - buflen = len - nsent; - - if (buflen > sizeof(buf)) - buflen = sizeof(buf); - - do - if (use_pread) - nread = pread(in_fd, buf, buflen, offset); - else - nread = read(in_fd, buf, buflen); - while (nread == -1 && errno == EINTR); - - if (nread == 0) - goto out; - - if (nread == -1) { - if (use_pread && nsent == 0 && (errno == EIO || errno == ESPIPE)) { - use_pread = 0; - continue; - } - - if (nsent == 0) - nsent = -1; - - goto out; - } - - for (nwritten = 0; nwritten < nread; ) { - do - n = write(out_fd, buf + nwritten, nread - nwritten); - while (n == -1 && errno == EINTR); - - if (n != -1) { - nwritten += n; - continue; - } - - if (errno != EAGAIN && errno != EWOULDBLOCK) { - nsent = -1; - goto out; - } - - pfd.fd = out_fd; - pfd.events = POLLOUT; - pfd.revents = 0; - - do - n = poll(&pfd, 1, -1); - while (n == -1 && errno == EINTR); - - if (n == -1 || (pfd.revents & ~POLLOUT) != 0) { - errno = EIO; - nsent = -1; - goto out; - } - } - - offset += nread; - nsent += nread; - } - -out: - if (nsent != -1) - req->off = offset; - - return nsent; -} - - -static ssize_t uv__fs_sendfile(uv_fs_t* req) { - int in_fd; - int out_fd; - - in_fd = req->flags; - out_fd = req->file; - -#if defined(__linux__) || defined(__sun) - { - off_t off; - ssize_t r; - - off = req->off; - r = sendfile(out_fd, in_fd, &off, req->bufsml[0].len); - - /* sendfile() on SunOS returns EINVAL if the target fd is not a socket but - * it still writes out data. Fortunately, we can detect it by checking if - * the offset has been updated. - */ - if (r != -1 || off > req->off) { - r = off - req->off; - req->off = off; - return r; - } - - if (errno == EINVAL || - errno == EIO || - errno == ENOTSOCK || - errno == EXDEV) { - errno = 0; - return uv__fs_sendfile_emul(req); - } - - return -1; - } -#elif defined(__FreeBSD__) || defined(__APPLE__) - { - off_t len; - ssize_t r; - - /* sendfile() on FreeBSD and Darwin returns EAGAIN if the target fd is in - * non-blocking mode and not all data could be written. If a non-zero - * number of bytes have been sent, we don't consider it an error. - */ - -#if defined(__FreeBSD__) - len = 0; - r = sendfile(in_fd, out_fd, req->off, req->bufsml[0].len, NULL, &len, 0); -#else - /* The darwin sendfile takes len as an input for the length to send, - * so make sure to initialize it with the caller's value. */ - len = req->bufsml[0].len; - r = sendfile(in_fd, out_fd, req->off, &len, NULL, 0); -#endif - - if (r != -1 || len != 0) { - req->off += len; - return (ssize_t) len; - } - - if (errno == EINVAL || - errno == EIO || - errno == ENOTSOCK || - errno == EXDEV) { - errno = 0; - return uv__fs_sendfile_emul(req); - } - - return -1; - } -#else - /* Squelch compiler warnings. */ - (void) &in_fd; - (void) &out_fd; - - return uv__fs_sendfile_emul(req); -#endif -} - - -static ssize_t uv__fs_utime(uv_fs_t* req) { - struct utimbuf buf; - buf.actime = req->atime; - buf.modtime = req->mtime; - return utime(req->path, &buf); /* TODO use utimes() where available */ -} - - -static ssize_t uv__fs_write(uv_fs_t* req) { -#if defined(__linux__) - static int no_pwritev; -#endif - ssize_t r; - - /* Serialize writes on OS X, concurrent write() and pwrite() calls result in - * data loss. We can't use a per-file descriptor lock, the descriptor may be - * a dup(). - */ -#if defined(__APPLE__) - static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; - pthread_mutex_lock(&lock); -#endif - - if (req->off < 0) { - if (req->nbufs == 1) - r = write(req->file, req->bufs[0].base, req->bufs[0].len); - else - r = writev(req->file, (struct iovec*) req->bufs, req->nbufs); - } else { - if (req->nbufs == 1) { - r = pwrite(req->file, req->bufs[0].base, req->bufs[0].len, req->off); - goto done; - } -#if HAVE_PREADV - r = pwritev(req->file, (struct iovec*) req->bufs, req->nbufs, req->off); -#else -# if defined(__linux__) - if (no_pwritev) retry: -# endif - { - off_t written; - size_t index; - - written = 0; - index = 0; - r = 0; - do { - if (req->bufs[index].len > 0) { - r = pwrite(req->file, - req->bufs[index].base, - req->bufs[index].len, - req->off + written); - if (r > 0) - written += r; - } - index++; - } while (index < req->nbufs && r >= 0); - if (written > 0) - r = written; - } -# if defined(__linux__) - else { - r = uv__pwritev(req->file, - (struct iovec*) req->bufs, - req->nbufs, - req->off); - if (r == -1 && errno == ENOSYS) { - no_pwritev = 1; - goto retry; - } - } -# endif -#endif - } - -done: -#if defined(__APPLE__) - pthread_mutex_unlock(&lock); -#endif - - if (req->bufs != req->bufsml) - free(req->bufs); - - return r; -} - -static void uv__to_stat(struct stat* src, uv_stat_t* dst) { - dst->st_dev = src->st_dev; - dst->st_mode = src->st_mode; - dst->st_nlink = src->st_nlink; - dst->st_uid = src->st_uid; - dst->st_gid = src->st_gid; - dst->st_rdev = src->st_rdev; - dst->st_ino = src->st_ino; - dst->st_size = src->st_size; - dst->st_blksize = src->st_blksize; - dst->st_blocks = src->st_blocks; - -#if defined(__APPLE__) - dst->st_atim.tv_sec = src->st_atimespec.tv_sec; - dst->st_atim.tv_nsec = src->st_atimespec.tv_nsec; - dst->st_mtim.tv_sec = src->st_mtimespec.tv_sec; - dst->st_mtim.tv_nsec = src->st_mtimespec.tv_nsec; - dst->st_ctim.tv_sec = src->st_ctimespec.tv_sec; - dst->st_ctim.tv_nsec = src->st_ctimespec.tv_nsec; - dst->st_birthtim.tv_sec = src->st_birthtimespec.tv_sec; - dst->st_birthtim.tv_nsec = src->st_birthtimespec.tv_nsec; - dst->st_flags = src->st_flags; - dst->st_gen = src->st_gen; -#elif !defined(_AIX) && \ - (defined(_BSD_SOURCE) || defined(_SVID_SOURCE) || defined(_XOPEN_SOURCE)) - dst->st_atim.tv_sec = src->st_atim.tv_sec; - dst->st_atim.tv_nsec = src->st_atim.tv_nsec; - dst->st_mtim.tv_sec = src->st_mtim.tv_sec; - dst->st_mtim.tv_nsec = src->st_mtim.tv_nsec; - dst->st_ctim.tv_sec = src->st_ctim.tv_sec; - dst->st_ctim.tv_nsec = src->st_ctim.tv_nsec; -# if defined(__DragonFly__) || \ - defined(__FreeBSD__) || \ - defined(__OpenBSD__) || \ - defined(__NetBSD__) - dst->st_birthtim.tv_sec = src->st_birthtim.tv_sec; - dst->st_birthtim.tv_nsec = src->st_birthtim.tv_nsec; - dst->st_flags = src->st_flags; - dst->st_gen = src->st_gen; -# else - dst->st_birthtim.tv_sec = src->st_ctim.tv_sec; - dst->st_birthtim.tv_nsec = src->st_ctim.tv_nsec; - dst->st_flags = 0; - dst->st_gen = 0; -# endif -#else - dst->st_atim.tv_sec = src->st_atime; - dst->st_atim.tv_nsec = 0; - dst->st_mtim.tv_sec = src->st_mtime; - dst->st_mtim.tv_nsec = 0; - dst->st_ctim.tv_sec = src->st_ctime; - dst->st_ctim.tv_nsec = 0; - dst->st_birthtim.tv_sec = src->st_ctime; - dst->st_birthtim.tv_nsec = 0; - dst->st_flags = 0; - dst->st_gen = 0; -#endif -} - - -static int uv__fs_stat(const char *path, uv_stat_t *buf) { - struct stat pbuf; - int ret; - ret = stat(path, &pbuf); - uv__to_stat(&pbuf, buf); - return ret; -} - - -static int uv__fs_lstat(const char *path, uv_stat_t *buf) { - struct stat pbuf; - int ret; - ret = lstat(path, &pbuf); - uv__to_stat(&pbuf, buf); - return ret; -} - - -static int uv__fs_fstat(int fd, uv_stat_t *buf) { - struct stat pbuf; - int ret; - ret = fstat(fd, &pbuf); - uv__to_stat(&pbuf, buf); - return ret; -} - - -static void uv__fs_work(struct uv__work* w) { - int retry_on_eintr; - uv_fs_t* req; - ssize_t r; -#ifdef O_CLOEXEC - static int no_cloexec_support; -#endif /* O_CLOEXEC */ - - req = container_of(w, uv_fs_t, work_req); - retry_on_eintr = !(req->fs_type == UV_FS_CLOSE); - - do { - errno = 0; - -#define X(type, action) \ - case UV_FS_ ## type: \ - r = action; \ - break; - - switch (req->fs_type) { - X(ACCESS, access(req->path, req->flags)); - X(CHMOD, chmod(req->path, req->mode)); - X(CHOWN, chown(req->path, req->uid, req->gid)); - X(CLOSE, close(req->file)); - X(FCHMOD, fchmod(req->file, req->mode)); - X(FCHOWN, fchown(req->file, req->uid, req->gid)); - X(FDATASYNC, uv__fs_fdatasync(req)); - X(FSTAT, uv__fs_fstat(req->file, &req->statbuf)); - X(FSYNC, fsync(req->file)); - X(FTRUNCATE, ftruncate(req->file, req->off)); - X(FUTIME, uv__fs_futime(req)); - X(LSTAT, uv__fs_lstat(req->path, &req->statbuf)); - X(LINK, link(req->path, req->new_path)); - X(MKDIR, mkdir(req->path, req->mode)); - X(MKDTEMP, uv__fs_mkdtemp(req)); - X(READ, uv__fs_read(req)); - X(SCANDIR, uv__fs_scandir(req)); - X(READLINK, uv__fs_readlink(req)); - X(RENAME, rename(req->path, req->new_path)); - X(RMDIR, rmdir(req->path)); - X(SENDFILE, uv__fs_sendfile(req)); - X(STAT, uv__fs_stat(req->path, &req->statbuf)); - X(SYMLINK, symlink(req->path, req->new_path)); - X(UNLINK, unlink(req->path)); - X(UTIME, uv__fs_utime(req)); - X(WRITE, uv__fs_write(req)); - case UV_FS_OPEN: -#ifdef O_CLOEXEC - /* Try O_CLOEXEC before entering locks */ - if (!no_cloexec_support) { - r = open(req->path, req->flags | O_CLOEXEC, req->mode); - if (r >= 0) - break; - if (errno != EINVAL) - break; - no_cloexec_support = 1; - } -#endif /* O_CLOEXEC */ - if (req->cb != NULL) - uv_rwlock_rdlock(&req->loop->cloexec_lock); - r = open(req->path, req->flags, req->mode); - - /* - * In case of failure `uv__cloexec` will leave error in `errno`, - * so it is enough to just set `r` to `-1`. - */ - if (r >= 0 && uv__cloexec(r, 1) != 0) { - r = uv__close(r); - if (r != 0 && r != -EINPROGRESS) - abort(); - r = -1; - } - if (req->cb != NULL) - uv_rwlock_rdunlock(&req->loop->cloexec_lock); - break; - default: abort(); - } - -#undef X - } - while (r == -1 && errno == EINTR && retry_on_eintr); - - if (r == -1) - req->result = -errno; - else - req->result = r; - - if (r == 0 && (req->fs_type == UV_FS_STAT || - req->fs_type == UV_FS_FSTAT || - req->fs_type == UV_FS_LSTAT)) { - req->ptr = &req->statbuf; - } -} - - -static void uv__fs_done(struct uv__work* w, int status) { - uv_fs_t* req; - - req = container_of(w, uv_fs_t, work_req); - uv__req_unregister(req->loop, req); - - if (status == -ECANCELED) { - assert(req->result == 0); - req->result = -ECANCELED; - } - - if (req->cb != NULL) - req->cb(req); -} - - -int uv_fs_access(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - int flags, - uv_fs_cb cb) { - INIT(ACCESS); - PATH; - req->flags = flags; - POST; -} - - -int uv_fs_chmod(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - int mode, - uv_fs_cb cb) { - INIT(CHMOD); - PATH; - req->mode = mode; - POST; -} - - -int uv_fs_chown(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - uv_uid_t uid, - uv_gid_t gid, - uv_fs_cb cb) { - INIT(CHOWN); - PATH; - req->uid = uid; - req->gid = gid; - POST; -} - - -int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) { - INIT(CLOSE); - req->file = file; - POST; -} - - -int uv_fs_fchmod(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - int mode, - uv_fs_cb cb) { - INIT(FCHMOD); - req->file = file; - req->mode = mode; - POST; -} - - -int uv_fs_fchown(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - uv_uid_t uid, - uv_gid_t gid, - uv_fs_cb cb) { - INIT(FCHOWN); - req->file = file; - req->uid = uid; - req->gid = gid; - POST; -} - - -int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) { - INIT(FDATASYNC); - req->file = file; - POST; -} - - -int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) { - INIT(FSTAT); - req->file = file; - POST; -} - - -int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) { - INIT(FSYNC); - req->file = file; - POST; -} - - -int uv_fs_ftruncate(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - int64_t off, - uv_fs_cb cb) { - INIT(FTRUNCATE); - req->file = file; - req->off = off; - POST; -} - - -int uv_fs_futime(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - double atime, - double mtime, - uv_fs_cb cb) { - INIT(FUTIME); - req->file = file; - req->atime = atime; - req->mtime = mtime; - POST; -} - - -int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { - INIT(LSTAT); - PATH; - POST; -} - - -int uv_fs_link(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - const char* new_path, - uv_fs_cb cb) { - INIT(LINK); - PATH2; - POST; -} - - -int uv_fs_mkdir(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - int mode, - uv_fs_cb cb) { - INIT(MKDIR); - PATH; - req->mode = mode; - POST; -} - - -int uv_fs_mkdtemp(uv_loop_t* loop, - uv_fs_t* req, - const char* tpl, - uv_fs_cb cb) { - INIT(MKDTEMP); - req->path = strdup(tpl); - if (req->path == NULL) - return -ENOMEM; - POST; -} - - -int uv_fs_open(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - int flags, - int mode, - uv_fs_cb cb) { - INIT(OPEN); - PATH; - req->flags = flags; - req->mode = mode; - POST; -} - - -int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, - uv_file file, - const uv_buf_t bufs[], - unsigned int nbufs, - int64_t off, - uv_fs_cb cb) { - INIT(READ); - req->file = file; - - req->nbufs = nbufs; - req->bufs = req->bufsml; - if (nbufs > ARRAY_SIZE(req->bufsml)) - req->bufs = malloc(nbufs * sizeof(*bufs)); - - if (req->bufs == NULL) - return -ENOMEM; - - memcpy(req->bufs, bufs, nbufs * sizeof(*bufs)); - - req->off = off; - POST; -} - - -int uv_fs_scandir(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - int flags, - uv_fs_cb cb) { - INIT(SCANDIR); - PATH; - req->flags = flags; - POST; -} - - -int uv_fs_readlink(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - uv_fs_cb cb) { - INIT(READLINK); - PATH; - POST; -} - - -int uv_fs_rename(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - const char* new_path, - uv_fs_cb cb) { - INIT(RENAME); - PATH2; - POST; -} - - -int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { - INIT(RMDIR); - PATH; - POST; -} - - -int uv_fs_sendfile(uv_loop_t* loop, - uv_fs_t* req, - uv_file out_fd, - uv_file in_fd, - int64_t off, - size_t len, - uv_fs_cb cb) { - INIT(SENDFILE); - req->flags = in_fd; /* hack */ - req->file = out_fd; - req->off = off; - req->bufsml[0].len = len; - POST; -} - - -int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { - INIT(STAT); - PATH; - POST; -} - - -int uv_fs_symlink(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - const char* new_path, - int flags, - uv_fs_cb cb) { - INIT(SYMLINK); - PATH2; - req->flags = flags; - POST; -} - - -int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { - INIT(UNLINK); - PATH; - POST; -} - - -int uv_fs_utime(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - double atime, - double mtime, - uv_fs_cb cb) { - INIT(UTIME); - PATH; - req->atime = atime; - req->mtime = mtime; - POST; -} - - -int uv_fs_write(uv_loop_t* loop, - uv_fs_t* req, - uv_file file, - const uv_buf_t bufs[], - unsigned int nbufs, - int64_t off, - uv_fs_cb cb) { - INIT(WRITE); - req->file = file; - - req->nbufs = nbufs; - req->bufs = req->bufsml; - if (nbufs > ARRAY_SIZE(req->bufsml)) - req->bufs = malloc(nbufs * sizeof(*bufs)); - - if (req->bufs == NULL) - return -ENOMEM; - - memcpy(req->bufs, bufs, nbufs * sizeof(*bufs)); - - req->off = off; - POST; -} - - -void uv_fs_req_cleanup(uv_fs_t* req) { - free((void*) req->path); - req->path = NULL; - req->new_path = NULL; - - if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL) - uv__fs_scandir_cleanup(req); - - if (req->ptr != &req->statbuf) - free(req->ptr); - req->ptr = NULL; -} diff --git a/libuv/src/unix/fsevents.c b/libuv/src/unix/fsevents.c deleted file mode 100644 index 4908530..0000000 --- a/libuv/src/unix/fsevents.c +++ /dev/null @@ -1,899 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#if TARGET_OS_IPHONE - -/* iOS (currently) doesn't provide the FSEvents-API (nor CoreServices) */ - -int uv__fsevents_init(uv_fs_event_t* handle) { - return 0; -} - - -int uv__fsevents_close(uv_fs_event_t* handle) { - return 0; -} - - -void uv__fsevents_loop_delete(uv_loop_t* loop) { -} - -#else /* TARGET_OS_IPHONE */ - -#include -#include -#include -#include - -#include -#include - -/* These are macros to avoid "initializer element is not constant" errors - * with old versions of gcc. - */ -#define kFSEventsModified (kFSEventStreamEventFlagItemFinderInfoMod | \ - kFSEventStreamEventFlagItemModified | \ - kFSEventStreamEventFlagItemInodeMetaMod | \ - kFSEventStreamEventFlagItemChangeOwner | \ - kFSEventStreamEventFlagItemXattrMod) - -#define kFSEventsRenamed (kFSEventStreamEventFlagItemCreated | \ - kFSEventStreamEventFlagItemRemoved | \ - kFSEventStreamEventFlagItemRenamed) - -#define kFSEventsSystem (kFSEventStreamEventFlagUserDropped | \ - kFSEventStreamEventFlagKernelDropped | \ - kFSEventStreamEventFlagEventIdsWrapped | \ - kFSEventStreamEventFlagHistoryDone | \ - kFSEventStreamEventFlagMount | \ - kFSEventStreamEventFlagUnmount | \ - kFSEventStreamEventFlagRootChanged) - -typedef struct uv__fsevents_event_s uv__fsevents_event_t; -typedef struct uv__cf_loop_signal_s uv__cf_loop_signal_t; -typedef struct uv__cf_loop_state_s uv__cf_loop_state_t; - -struct uv__cf_loop_signal_s { - QUEUE member; - uv_fs_event_t* handle; -}; - -struct uv__fsevents_event_s { - QUEUE member; - int events; - char path[1]; -}; - -struct uv__cf_loop_state_s { - CFRunLoopRef loop; - CFRunLoopSourceRef signal_source; - int fsevent_need_reschedule; - FSEventStreamRef fsevent_stream; - uv_sem_t fsevent_sem; - uv_mutex_t fsevent_mutex; - void* fsevent_handles[2]; - unsigned int fsevent_handle_count; -}; - -/* Forward declarations */ -static void uv__cf_loop_cb(void* arg); -static void* uv__cf_loop_runner(void* arg); -static int uv__cf_loop_signal(uv_loop_t* loop, uv_fs_event_t* handle); - -/* Lazy-loaded by uv__fsevents_global_init(). */ -static CFArrayRef (*pCFArrayCreate)(CFAllocatorRef, - const void**, - CFIndex, - const CFArrayCallBacks*); -static void (*pCFRelease)(CFTypeRef); -static void (*pCFRunLoopAddSource)(CFRunLoopRef, - CFRunLoopSourceRef, - CFStringRef); -static CFRunLoopRef (*pCFRunLoopGetCurrent)(void); -static void (*pCFRunLoopRemoveSource)(CFRunLoopRef, - CFRunLoopSourceRef, - CFStringRef); -static void (*pCFRunLoopRun)(void); -static CFRunLoopSourceRef (*pCFRunLoopSourceCreate)(CFAllocatorRef, - CFIndex, - CFRunLoopSourceContext*); -static void (*pCFRunLoopSourceSignal)(CFRunLoopSourceRef); -static void (*pCFRunLoopStop)(CFRunLoopRef); -static void (*pCFRunLoopWakeUp)(CFRunLoopRef); -static CFStringRef (*pCFStringCreateWithFileSystemRepresentation)( - CFAllocatorRef, - const char*); -static CFStringEncoding (*pCFStringGetSystemEncoding)(void); -static CFStringRef (*pkCFRunLoopDefaultMode); -static FSEventStreamRef (*pFSEventStreamCreate)(CFAllocatorRef, - FSEventStreamCallback, - FSEventStreamContext*, - CFArrayRef, - FSEventStreamEventId, - CFTimeInterval, - FSEventStreamCreateFlags); -static void (*pFSEventStreamFlushSync)(FSEventStreamRef); -static void (*pFSEventStreamInvalidate)(FSEventStreamRef); -static void (*pFSEventStreamRelease)(FSEventStreamRef); -static void (*pFSEventStreamScheduleWithRunLoop)(FSEventStreamRef, - CFRunLoopRef, - CFStringRef); -static Boolean (*pFSEventStreamStart)(FSEventStreamRef); -static void (*pFSEventStreamStop)(FSEventStreamRef); - -#define UV__FSEVENTS_PROCESS(handle, block) \ - do { \ - QUEUE events; \ - QUEUE* q; \ - uv__fsevents_event_t* event; \ - int err; \ - uv_mutex_lock(&(handle)->cf_mutex); \ - /* Split-off all events and empty original queue */ \ - QUEUE_INIT(&events); \ - if (!QUEUE_EMPTY(&(handle)->cf_events)) { \ - q = QUEUE_HEAD(&(handle)->cf_events); \ - QUEUE_SPLIT(&(handle)->cf_events, q, &events); \ - } \ - /* Get error (if any) and zero original one */ \ - err = (handle)->cf_error; \ - (handle)->cf_error = 0; \ - uv_mutex_unlock(&(handle)->cf_mutex); \ - /* Loop through events, deallocating each after processing */ \ - while (!QUEUE_EMPTY(&events)) { \ - q = QUEUE_HEAD(&events); \ - event = QUEUE_DATA(q, uv__fsevents_event_t, member); \ - QUEUE_REMOVE(q); \ - /* NOTE: Checking uv__is_active() is required here, because handle \ - * callback may close handle and invoking it after it will lead to \ - * incorrect behaviour */ \ - if (!uv__is_closing((handle)) && uv__is_active((handle))) \ - block \ - /* Free allocated data */ \ - free(event); \ - } \ - if (err != 0 && !uv__is_closing((handle)) && uv__is_active((handle))) \ - (handle)->cb((handle), NULL, 0, err); \ - } while (0) - - -/* Runs in UV loop's thread, when there're events to report to handle */ -static void uv__fsevents_cb(uv_async_t* cb) { - uv_fs_event_t* handle; - - handle = cb->data; - - UV__FSEVENTS_PROCESS(handle, { - handle->cb(handle, event->path[0] ? event->path : NULL, event->events, 0); - }); -} - - -/* Runs in CF thread, pushed event into handle's event list */ -static void uv__fsevents_push_event(uv_fs_event_t* handle, - QUEUE* events, - int err) { - assert(events != NULL || err != 0); - uv_mutex_lock(&handle->cf_mutex); - - /* Concatenate two queues */ - if (events != NULL) - QUEUE_ADD(&handle->cf_events, events); - - /* Propagate error */ - if (err != 0) - handle->cf_error = err; - uv_mutex_unlock(&handle->cf_mutex); - - uv_async_send(handle->cf_cb); -} - - -/* Runs in CF thread, when there're events in FSEventStream */ -static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef, - void* info, - size_t numEvents, - void* eventPaths, - const FSEventStreamEventFlags eventFlags[], - const FSEventStreamEventId eventIds[]) { - size_t i; - int len; - char** paths; - char* path; - char* pos; - uv_fs_event_t* handle; - QUEUE* q; - uv_loop_t* loop; - uv__cf_loop_state_t* state; - uv__fsevents_event_t* event; - QUEUE head; - - loop = info; - state = loop->cf_state; - assert(state != NULL); - paths = eventPaths; - - /* For each handle */ - uv_mutex_lock(&state->fsevent_mutex); - QUEUE_FOREACH(q, &state->fsevent_handles) { - handle = QUEUE_DATA(q, uv_fs_event_t, cf_member); - QUEUE_INIT(&head); - - /* Process and filter out events */ - for (i = 0; i < numEvents; i++) { - /* Ignore system events */ - if (eventFlags[i] & kFSEventsSystem) - continue; - - path = paths[i]; - len = strlen(path); - - /* Filter out paths that are outside handle's request */ - if (strncmp(path, handle->realpath, handle->realpath_len) != 0) - continue; - - if (handle->realpath_len > 1 || *handle->realpath != '/') { - path += handle->realpath_len; - len -= handle->realpath_len; - - /* Skip forward slash */ - if (*path != '\0') { - path++; - len--; - } - } - -#ifdef MAC_OS_X_VERSION_10_7 - /* Ignore events with path equal to directory itself */ - if (len == 0) - continue; -#endif /* MAC_OS_X_VERSION_10_7 */ - - /* Do not emit events from subdirectories (without option set) */ - if ((handle->cf_flags & UV_FS_EVENT_RECURSIVE) == 0 && *path != 0) { - pos = strchr(path + 1, '/'); - if (pos != NULL) - continue; - } - -#ifndef MAC_OS_X_VERSION_10_7 - path = ""; - len = 0; -#endif /* MAC_OS_X_VERSION_10_7 */ - - event = malloc(sizeof(*event) + len); - if (event == NULL) - break; - - memset(event, 0, sizeof(*event)); - memcpy(event->path, path, len + 1); - - if ((eventFlags[i] & kFSEventsModified) != 0 && - (eventFlags[i] & kFSEventsRenamed) == 0) - event->events = UV_CHANGE; - else - event->events = UV_RENAME; - - QUEUE_INSERT_TAIL(&head, &event->member); - } - - if (!QUEUE_EMPTY(&head)) - uv__fsevents_push_event(handle, &head, 0); - } - uv_mutex_unlock(&state->fsevent_mutex); -} - - -/* Runs in CF thread */ -static int uv__fsevents_create_stream(uv_loop_t* loop, CFArrayRef paths) { - uv__cf_loop_state_t* state; - FSEventStreamContext ctx; - FSEventStreamRef ref; - CFAbsoluteTime latency; - FSEventStreamCreateFlags flags; - - /* Initialize context */ - ctx.version = 0; - ctx.info = loop; - ctx.retain = NULL; - ctx.release = NULL; - ctx.copyDescription = NULL; - - latency = 0.05; - - /* Explanation of selected flags: - * 1. NoDefer - without this flag, events that are happening continuously - * (i.e. each event is happening after time interval less than `latency`, - * counted from previous event), will be deferred and passed to callback - * once they'll either fill whole OS buffer, or when this continuous stream - * will stop (i.e. there'll be delay between events, bigger than - * `latency`). - * Specifying this flag will invoke callback after `latency` time passed - * since event. - * 2. FileEvents - fire callback for file changes too (by default it is firing - * it only for directory changes). - */ - flags = kFSEventStreamCreateFlagNoDefer | kFSEventStreamCreateFlagFileEvents; - - /* - * NOTE: It might sound like a good idea to remember last seen StreamEventId, - * but in reality one dir might have last StreamEventId less than, the other, - * that is being watched now. Which will cause FSEventStream API to report - * changes to files from the past. - */ - ref = pFSEventStreamCreate(NULL, - &uv__fsevents_event_cb, - &ctx, - paths, - kFSEventStreamEventIdSinceNow, - latency, - flags); - assert(ref != NULL); - - state = loop->cf_state; - pFSEventStreamScheduleWithRunLoop(ref, - state->loop, - *pkCFRunLoopDefaultMode); - if (!pFSEventStreamStart(ref)) { - pFSEventStreamInvalidate(ref); - pFSEventStreamRelease(ref); - return -EMFILE; - } - - state->fsevent_stream = ref; - return 0; -} - - -/* Runs in CF thread */ -static void uv__fsevents_destroy_stream(uv_loop_t* loop) { - uv__cf_loop_state_t* state; - - state = loop->cf_state; - - if (state->fsevent_stream == NULL) - return; - - /* Flush all accumulated events */ - pFSEventStreamFlushSync(state->fsevent_stream); - - /* Stop emitting events */ - pFSEventStreamStop(state->fsevent_stream); - - /* Release stream */ - pFSEventStreamInvalidate(state->fsevent_stream); - pFSEventStreamRelease(state->fsevent_stream); - state->fsevent_stream = NULL; -} - - -/* Runs in CF thread, when there're new fsevent handles to add to stream */ -static void uv__fsevents_reschedule(uv_fs_event_t* handle) { - uv__cf_loop_state_t* state; - QUEUE* q; - uv_fs_event_t* curr; - CFArrayRef cf_paths; - CFStringRef* paths; - unsigned int i; - int err; - unsigned int path_count; - - state = handle->loop->cf_state; - paths = NULL; - cf_paths = NULL; - err = 0; - /* NOTE: `i` is used in deallocation loop below */ - i = 0; - - /* Optimization to prevent O(n^2) time spent when starting to watch - * many files simultaneously - */ - uv_mutex_lock(&state->fsevent_mutex); - if (state->fsevent_need_reschedule == 0) { - uv_mutex_unlock(&state->fsevent_mutex); - goto final; - } - state->fsevent_need_reschedule = 0; - uv_mutex_unlock(&state->fsevent_mutex); - - /* Destroy previous FSEventStream */ - uv__fsevents_destroy_stream(handle->loop); - - /* Any failure below will be a memory failure */ - err = -ENOMEM; - - /* Create list of all watched paths */ - uv_mutex_lock(&state->fsevent_mutex); - path_count = state->fsevent_handle_count; - if (path_count != 0) { - paths = malloc(sizeof(*paths) * path_count); - if (paths == NULL) { - uv_mutex_unlock(&state->fsevent_mutex); - goto final; - } - - q = &state->fsevent_handles; - for (; i < path_count; i++) { - q = QUEUE_NEXT(q); - assert(q != &state->fsevent_handles); - curr = QUEUE_DATA(q, uv_fs_event_t, cf_member); - - assert(curr->realpath != NULL); - paths[i] = - pCFStringCreateWithFileSystemRepresentation(NULL, curr->realpath); - if (paths[i] == NULL) { - uv_mutex_unlock(&state->fsevent_mutex); - goto final; - } - } - } - uv_mutex_unlock(&state->fsevent_mutex); - err = 0; - - if (path_count != 0) { - /* Create new FSEventStream */ - cf_paths = pCFArrayCreate(NULL, (const void**) paths, path_count, NULL); - if (cf_paths == NULL) { - err = -ENOMEM; - goto final; - } - err = uv__fsevents_create_stream(handle->loop, cf_paths); - } - -final: - /* Deallocate all paths in case of failure */ - if (err != 0) { - if (cf_paths == NULL) { - while (i != 0) - pCFRelease(paths[--i]); - free(paths); - } else { - /* CFArray takes ownership of both strings and original C-array */ - pCFRelease(cf_paths); - } - - /* Broadcast error to all handles */ - uv_mutex_lock(&state->fsevent_mutex); - QUEUE_FOREACH(q, &state->fsevent_handles) { - curr = QUEUE_DATA(q, uv_fs_event_t, cf_member); - uv__fsevents_push_event(curr, NULL, err); - } - uv_mutex_unlock(&state->fsevent_mutex); - } - - /* - * Main thread will block until the removal of handle from the list, - * we must tell it when we're ready. - * - * NOTE: This is coupled with `uv_sem_wait()` in `uv__fsevents_close` - */ - if (!uv__is_active(handle)) - uv_sem_post(&state->fsevent_sem); -} - - -static int uv__fsevents_global_init(void) { - static pthread_mutex_t global_init_mutex = PTHREAD_MUTEX_INITIALIZER; - static void* core_foundation_handle; - static void* core_services_handle; - int err; - - err = 0; - pthread_mutex_lock(&global_init_mutex); - if (core_foundation_handle != NULL) - goto out; - - /* The libraries are never unloaded because we currently don't have a good - * mechanism for keeping a reference count. It's unlikely to be an issue - * but if it ever becomes one, we can turn the dynamic library handles into - * per-event loop properties and have the dynamic linker keep track for us. - */ - err = -ENOSYS; - core_foundation_handle = dlopen("/System/Library/Frameworks/" - "CoreFoundation.framework/" - "Versions/A/CoreFoundation", - RTLD_LAZY | RTLD_LOCAL); - if (core_foundation_handle == NULL) - goto out; - - core_services_handle = dlopen("/System/Library/Frameworks/" - "CoreServices.framework/" - "Versions/A/CoreServices", - RTLD_LAZY | RTLD_LOCAL); - if (core_services_handle == NULL) - goto out; - - err = -ENOENT; -#define V(handle, symbol) \ - do { \ - *(void **)(&p ## symbol) = dlsym((handle), #symbol); \ - if (p ## symbol == NULL) \ - goto out; \ - } \ - while (0) - V(core_foundation_handle, CFArrayCreate); - V(core_foundation_handle, CFRelease); - V(core_foundation_handle, CFRunLoopAddSource); - V(core_foundation_handle, CFRunLoopGetCurrent); - V(core_foundation_handle, CFRunLoopRemoveSource); - V(core_foundation_handle, CFRunLoopRun); - V(core_foundation_handle, CFRunLoopSourceCreate); - V(core_foundation_handle, CFRunLoopSourceSignal); - V(core_foundation_handle, CFRunLoopStop); - V(core_foundation_handle, CFRunLoopWakeUp); - V(core_foundation_handle, CFStringCreateWithFileSystemRepresentation); - V(core_foundation_handle, CFStringGetSystemEncoding); - V(core_foundation_handle, kCFRunLoopDefaultMode); - V(core_services_handle, FSEventStreamCreate); - V(core_services_handle, FSEventStreamFlushSync); - V(core_services_handle, FSEventStreamInvalidate); - V(core_services_handle, FSEventStreamRelease); - V(core_services_handle, FSEventStreamScheduleWithRunLoop); - V(core_services_handle, FSEventStreamStart); - V(core_services_handle, FSEventStreamStop); -#undef V - err = 0; - -out: - if (err && core_services_handle != NULL) { - dlclose(core_services_handle); - core_services_handle = NULL; - } - - if (err && core_foundation_handle != NULL) { - dlclose(core_foundation_handle); - core_foundation_handle = NULL; - } - - pthread_mutex_unlock(&global_init_mutex); - return err; -} - - -/* Runs in UV loop */ -static int uv__fsevents_loop_init(uv_loop_t* loop) { - CFRunLoopSourceContext ctx; - uv__cf_loop_state_t* state; - pthread_attr_t attr_storage; - pthread_attr_t* attr; - int err; - - if (loop->cf_state != NULL) - return 0; - - err = uv__fsevents_global_init(); - if (err) - return err; - - state = calloc(1, sizeof(*state)); - if (state == NULL) - return -ENOMEM; - - err = uv_mutex_init(&loop->cf_mutex); - if (err) - goto fail_mutex_init; - - err = uv_sem_init(&loop->cf_sem, 0); - if (err) - goto fail_sem_init; - - QUEUE_INIT(&loop->cf_signals); - - err = uv_sem_init(&state->fsevent_sem, 0); - if (err) - goto fail_fsevent_sem_init; - - err = uv_mutex_init(&state->fsevent_mutex); - if (err) - goto fail_fsevent_mutex_init; - - QUEUE_INIT(&state->fsevent_handles); - state->fsevent_need_reschedule = 0; - state->fsevent_handle_count = 0; - - memset(&ctx, 0, sizeof(ctx)); - ctx.info = loop; - ctx.perform = uv__cf_loop_cb; - state->signal_source = pCFRunLoopSourceCreate(NULL, 0, &ctx); - if (state->signal_source == NULL) { - err = -ENOMEM; - goto fail_signal_source_create; - } - - /* In the unlikely event that pthread_attr_init() fails, create the thread - * with the default stack size. We'll use a little more address space but - * that in itself is not a fatal error. - */ - attr = &attr_storage; - if (pthread_attr_init(attr)) - attr = NULL; - - if (attr != NULL) - if (pthread_attr_setstacksize(attr, 4 * PTHREAD_STACK_MIN)) - abort(); - - loop->cf_state = state; - - /* uv_thread_t is an alias for pthread_t. */ - err = -pthread_create(&loop->cf_thread, attr, uv__cf_loop_runner, loop); - - if (attr != NULL) - pthread_attr_destroy(attr); - - if (err) - goto fail_thread_create; - - /* Synchronize threads */ - uv_sem_wait(&loop->cf_sem); - return 0; - -fail_thread_create: - loop->cf_state = NULL; - -fail_signal_source_create: - uv_mutex_destroy(&state->fsevent_mutex); - -fail_fsevent_mutex_init: - uv_sem_destroy(&state->fsevent_sem); - -fail_fsevent_sem_init: - uv_sem_destroy(&loop->cf_sem); - -fail_sem_init: - uv_mutex_destroy(&loop->cf_mutex); - -fail_mutex_init: - free(state); - return err; -} - - -/* Runs in UV loop */ -void uv__fsevents_loop_delete(uv_loop_t* loop) { - uv__cf_loop_signal_t* s; - uv__cf_loop_state_t* state; - QUEUE* q; - - if (loop->cf_state == NULL) - return; - - if (uv__cf_loop_signal(loop, NULL) != 0) - abort(); - - uv_thread_join(&loop->cf_thread); - uv_sem_destroy(&loop->cf_sem); - uv_mutex_destroy(&loop->cf_mutex); - - /* Free any remaining data */ - while (!QUEUE_EMPTY(&loop->cf_signals)) { - q = QUEUE_HEAD(&loop->cf_signals); - s = QUEUE_DATA(q, uv__cf_loop_signal_t, member); - QUEUE_REMOVE(q); - free(s); - } - - /* Destroy state */ - state = loop->cf_state; - uv_sem_destroy(&state->fsevent_sem); - uv_mutex_destroy(&state->fsevent_mutex); - pCFRelease(state->signal_source); - free(state); - loop->cf_state = NULL; -} - - -/* Runs in CF thread. This is the CF loop's body */ -static void* uv__cf_loop_runner(void* arg) { - uv_loop_t* loop; - uv__cf_loop_state_t* state; - - loop = arg; - state = loop->cf_state; - state->loop = pCFRunLoopGetCurrent(); - - pCFRunLoopAddSource(state->loop, - state->signal_source, - *pkCFRunLoopDefaultMode); - - uv_sem_post(&loop->cf_sem); - - pCFRunLoopRun(); - pCFRunLoopRemoveSource(state->loop, - state->signal_source, - *pkCFRunLoopDefaultMode); - - return NULL; -} - - -/* Runs in CF thread, executed after `uv__cf_loop_signal()` */ -static void uv__cf_loop_cb(void* arg) { - uv_loop_t* loop; - uv__cf_loop_state_t* state; - QUEUE* item; - QUEUE split_head; - uv__cf_loop_signal_t* s; - - loop = arg; - state = loop->cf_state; - QUEUE_INIT(&split_head); - - uv_mutex_lock(&loop->cf_mutex); - if (!QUEUE_EMPTY(&loop->cf_signals)) { - QUEUE* split_pos = QUEUE_HEAD(&loop->cf_signals); - QUEUE_SPLIT(&loop->cf_signals, split_pos, &split_head); - } - uv_mutex_unlock(&loop->cf_mutex); - - while (!QUEUE_EMPTY(&split_head)) { - item = QUEUE_HEAD(&split_head); - - s = QUEUE_DATA(item, uv__cf_loop_signal_t, member); - - /* This was a termination signal */ - if (s->handle == NULL) - pCFRunLoopStop(state->loop); - else - uv__fsevents_reschedule(s->handle); - - QUEUE_REMOVE(item); - free(s); - } -} - - -/* Runs in UV loop to notify CF thread */ -int uv__cf_loop_signal(uv_loop_t* loop, uv_fs_event_t* handle) { - uv__cf_loop_signal_t* item; - uv__cf_loop_state_t* state; - - item = malloc(sizeof(*item)); - if (item == NULL) - return -ENOMEM; - - item->handle = handle; - - uv_mutex_lock(&loop->cf_mutex); - QUEUE_INSERT_TAIL(&loop->cf_signals, &item->member); - uv_mutex_unlock(&loop->cf_mutex); - - state = loop->cf_state; - assert(state != NULL); - pCFRunLoopSourceSignal(state->signal_source); - pCFRunLoopWakeUp(state->loop); - - return 0; -} - - -/* Runs in UV loop to initialize handle */ -int uv__fsevents_init(uv_fs_event_t* handle) { - int err; - uv__cf_loop_state_t* state; - - err = uv__fsevents_loop_init(handle->loop); - if (err) - return err; - - /* Get absolute path to file */ - handle->realpath = realpath(handle->path, NULL); - if (handle->realpath == NULL) - return -errno; - handle->realpath_len = strlen(handle->realpath); - - /* Initialize event queue */ - QUEUE_INIT(&handle->cf_events); - handle->cf_error = 0; - - /* - * Events will occur in other thread. - * Initialize callback for getting them back into event loop's thread - */ - handle->cf_cb = malloc(sizeof(*handle->cf_cb)); - if (handle->cf_cb == NULL) { - err = -ENOMEM; - goto fail_cf_cb_malloc; - } - - handle->cf_cb->data = handle; - uv_async_init(handle->loop, handle->cf_cb, uv__fsevents_cb); - handle->cf_cb->flags |= UV__HANDLE_INTERNAL; - uv_unref((uv_handle_t*) handle->cf_cb); - - err = uv_mutex_init(&handle->cf_mutex); - if (err) - goto fail_cf_mutex_init; - - /* Insert handle into the list */ - state = handle->loop->cf_state; - uv_mutex_lock(&state->fsevent_mutex); - QUEUE_INSERT_TAIL(&state->fsevent_handles, &handle->cf_member); - state->fsevent_handle_count++; - state->fsevent_need_reschedule = 1; - uv_mutex_unlock(&state->fsevent_mutex); - - /* Reschedule FSEventStream */ - assert(handle != NULL); - err = uv__cf_loop_signal(handle->loop, handle); - if (err) - goto fail_loop_signal; - - return 0; - -fail_loop_signal: - uv_mutex_destroy(&handle->cf_mutex); - -fail_cf_mutex_init: - free(handle->cf_cb); - handle->cf_cb = NULL; - -fail_cf_cb_malloc: - free(handle->realpath); - handle->realpath = NULL; - handle->realpath_len = 0; - - return err; -} - - -/* Runs in UV loop to de-initialize handle */ -int uv__fsevents_close(uv_fs_event_t* handle) { - int err; - uv__cf_loop_state_t* state; - - if (handle->cf_cb == NULL) - return -EINVAL; - - /* Remove handle from the list */ - state = handle->loop->cf_state; - uv_mutex_lock(&state->fsevent_mutex); - QUEUE_REMOVE(&handle->cf_member); - state->fsevent_handle_count--; - state->fsevent_need_reschedule = 1; - uv_mutex_unlock(&state->fsevent_mutex); - - /* Reschedule FSEventStream */ - assert(handle != NULL); - err = uv__cf_loop_signal(handle->loop, handle); - if (err) - return -err; - - /* Wait for deinitialization */ - uv_sem_wait(&state->fsevent_sem); - - uv_close((uv_handle_t*) handle->cf_cb, (uv_close_cb) free); - handle->cf_cb = NULL; - - /* Free data in queue */ - UV__FSEVENTS_PROCESS(handle, { - /* NOP */ - }); - - uv_mutex_destroy(&handle->cf_mutex); - free(handle->realpath); - handle->realpath = NULL; - handle->realpath_len = 0; - - return 0; -} - -#endif /* TARGET_OS_IPHONE */ diff --git a/libuv/src/unix/getaddrinfo.c b/libuv/src/unix/getaddrinfo.c deleted file mode 100644 index 0d684e2..0000000 --- a/libuv/src/unix/getaddrinfo.c +++ /dev/null @@ -1,202 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* Expose glibc-specific EAI_* error codes. Needs to be defined before we - * include any headers. - */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif - -#include "uv.h" -#include "internal.h" - -#include -#include /* NULL */ -#include -#include - -/* EAI_* constants. */ -#include - - -int uv__getaddrinfo_translate_error(int sys_err) { - switch (sys_err) { - case 0: return 0; -#if defined(EAI_ADDRFAMILY) - case EAI_ADDRFAMILY: return UV_EAI_ADDRFAMILY; -#endif -#if defined(EAI_AGAIN) - case EAI_AGAIN: return UV_EAI_AGAIN; -#endif -#if defined(EAI_BADFLAGS) - case EAI_BADFLAGS: return UV_EAI_BADFLAGS; -#endif -#if defined(EAI_BADHINTS) - case EAI_BADHINTS: return UV_EAI_BADHINTS; -#endif -#if defined(EAI_CANCELED) - case EAI_CANCELED: return UV_EAI_CANCELED; -#endif -#if defined(EAI_FAIL) - case EAI_FAIL: return UV_EAI_FAIL; -#endif -#if defined(EAI_FAMILY) - case EAI_FAMILY: return UV_EAI_FAMILY; -#endif -#if defined(EAI_MEMORY) - case EAI_MEMORY: return UV_EAI_MEMORY; -#endif -#if defined(EAI_NODATA) - case EAI_NODATA: return UV_EAI_NODATA; -#endif -#if defined(EAI_NONAME) -# if !defined(EAI_NODATA) || EAI_NODATA != EAI_NONAME - case EAI_NONAME: return UV_EAI_NONAME; -# endif -#endif -#if defined(EAI_OVERFLOW) - case EAI_OVERFLOW: return UV_EAI_OVERFLOW; -#endif -#if defined(EAI_PROTOCOL) - case EAI_PROTOCOL: return UV_EAI_PROTOCOL; -#endif -#if defined(EAI_SERVICE) - case EAI_SERVICE: return UV_EAI_SERVICE; -#endif -#if defined(EAI_SOCKTYPE) - case EAI_SOCKTYPE: return UV_EAI_SOCKTYPE; -#endif -#if defined(EAI_SYSTEM) - case EAI_SYSTEM: return -errno; -#endif - } - assert(!"unknown EAI_* error code"); - abort(); - return 0; /* Pacify compiler. */ -} - - -static void uv__getaddrinfo_work(struct uv__work* w) { - uv_getaddrinfo_t* req; - int err; - - req = container_of(w, uv_getaddrinfo_t, work_req); - err = getaddrinfo(req->hostname, req->service, req->hints, &req->addrinfo); - req->retcode = uv__getaddrinfo_translate_error(err); -} - - -static void uv__getaddrinfo_done(struct uv__work* w, int status) { - uv_getaddrinfo_t* req; - - req = container_of(w, uv_getaddrinfo_t, work_req); - uv__req_unregister(req->loop, req); - - /* See initialization in uv_getaddrinfo(). */ - if (req->hints) - free(req->hints); - else if (req->service) - free(req->service); - else if (req->hostname) - free(req->hostname); - else - assert(0); - - req->hints = NULL; - req->service = NULL; - req->hostname = NULL; - - if (status == -ECANCELED) { - assert(req->retcode == 0); - req->retcode = UV_EAI_CANCELED; - } - - if (req->cb) - req->cb(req, req->retcode, req->addrinfo); -} - - -int uv_getaddrinfo(uv_loop_t* loop, - uv_getaddrinfo_t* req, - uv_getaddrinfo_cb cb, - const char* hostname, - const char* service, - const struct addrinfo* hints) { - size_t hostname_len; - size_t service_len; - size_t hints_len; - size_t len; - char* buf; - - if (req == NULL || (hostname == NULL && service == NULL)) - return -EINVAL; - - hostname_len = hostname ? strlen(hostname) + 1 : 0; - service_len = service ? strlen(service) + 1 : 0; - hints_len = hints ? sizeof(*hints) : 0; - buf = malloc(hostname_len + service_len + hints_len); - - if (buf == NULL) - return -ENOMEM; - - uv__req_init(loop, req, UV_GETADDRINFO); - req->loop = loop; - req->cb = cb; - req->addrinfo = NULL; - req->hints = NULL; - req->service = NULL; - req->hostname = NULL; - req->retcode = 0; - - /* order matters, see uv_getaddrinfo_done() */ - len = 0; - - if (hints) { - req->hints = memcpy(buf + len, hints, sizeof(*hints)); - len += sizeof(*hints); - } - - if (service) { - req->service = memcpy(buf + len, service, service_len); - len += service_len; - } - - if (hostname) - req->hostname = memcpy(buf + len, hostname, hostname_len); - - if (cb) { - uv__work_submit(loop, - &req->work_req, - uv__getaddrinfo_work, - uv__getaddrinfo_done); - return 0; - } else { - uv__getaddrinfo_work(&req->work_req); - uv__getaddrinfo_done(&req->work_req, 0); - return req->retcode; - } -} - - -void uv_freeaddrinfo(struct addrinfo* ai) { - if (ai) - freeaddrinfo(ai); -} diff --git a/libuv/src/unix/getnameinfo.c b/libuv/src/unix/getnameinfo.c deleted file mode 100644 index daa798a..0000000 --- a/libuv/src/unix/getnameinfo.c +++ /dev/null @@ -1,120 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to -* deal in the Software without restriction, including without limitation the -* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -* sell copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -* IN THE SOFTWARE. -*/ - -#include -#include -#include -#include - -#include "uv.h" -#include "internal.h" - - -static void uv__getnameinfo_work(struct uv__work* w) { - uv_getnameinfo_t* req; - int err; - socklen_t salen; - - req = container_of(w, uv_getnameinfo_t, work_req); - - if (req->storage.ss_family == AF_INET) - salen = sizeof(struct sockaddr_in); - else if (req->storage.ss_family == AF_INET6) - salen = sizeof(struct sockaddr_in6); - else - abort(); - - err = getnameinfo((struct sockaddr*) &req->storage, - salen, - req->host, - sizeof(req->host), - req->service, - sizeof(req->service), - req->flags); - req->retcode = uv__getaddrinfo_translate_error(err); -} - -static void uv__getnameinfo_done(struct uv__work* w, int status) { - uv_getnameinfo_t* req; - char* host; - char* service; - - req = container_of(w, uv_getnameinfo_t, work_req); - uv__req_unregister(req->loop, req); - host = service = NULL; - - if (status == -ECANCELED) { - assert(req->retcode == 0); - req->retcode = UV_EAI_CANCELED; - } else if (req->retcode == 0) { - host = req->host; - service = req->service; - } - - if (req->getnameinfo_cb) - req->getnameinfo_cb(req, req->retcode, host, service); -} - -/* -* Entry point for getnameinfo -* return 0 if a callback will be made -* return error code if validation fails -*/ -int uv_getnameinfo(uv_loop_t* loop, - uv_getnameinfo_t* req, - uv_getnameinfo_cb getnameinfo_cb, - const struct sockaddr* addr, - int flags) { - if (req == NULL || addr == NULL) - return UV_EINVAL; - - if (addr->sa_family == AF_INET) { - memcpy(&req->storage, - addr, - sizeof(struct sockaddr_in)); - } else if (addr->sa_family == AF_INET6) { - memcpy(&req->storage, - addr, - sizeof(struct sockaddr_in6)); - } else { - return UV_EINVAL; - } - - uv__req_init(loop, (uv_req_t*)req, UV_GETNAMEINFO); - - req->getnameinfo_cb = getnameinfo_cb; - req->flags = flags; - req->type = UV_GETNAMEINFO; - req->loop = loop; - req->retcode = 0; - - if (getnameinfo_cb) { - uv__work_submit(loop, - &req->work_req, - uv__getnameinfo_work, - uv__getnameinfo_done); - return 0; - } else { - uv__getnameinfo_work(&req->work_req); - uv__getnameinfo_done(&req->work_req, 0); - return req->retcode; - } -} diff --git a/libuv/src/unix/internal.h b/libuv/src/unix/internal.h deleted file mode 100644 index 101dc74..0000000 --- a/libuv/src/unix/internal.h +++ /dev/null @@ -1,311 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_UNIX_INTERNAL_H_ -#define UV_UNIX_INTERNAL_H_ - -#include "uv-common.h" - -#include -#include /* abort */ -#include /* strrchr */ -#include /* O_CLOEXEC, may be */ - -#if defined(__STRICT_ANSI__) -# define inline __inline -#endif - -#if defined(__linux__) -# include "linux-syscalls.h" -#endif /* __linux__ */ - -#if defined(__sun) -# include -# include -#endif /* __sun */ - -#if defined(_AIX) -#define reqevents events -#define rtnevents revents -#include -#endif /* _AIX */ - -#if defined(__APPLE__) && !TARGET_OS_IPHONE -# include -#endif - -#define ACCESS_ONCE(type, var) \ - (*(volatile type*) &(var)) - -#define UNREACHABLE() \ - do { \ - assert(0 && "unreachable code"); \ - abort(); \ - } \ - while (0) - -#define SAVE_ERRNO(block) \ - do { \ - int _saved_errno = errno; \ - do { block; } while (0); \ - errno = _saved_errno; \ - } \ - while (0) - -/* The __clang__ and __INTEL_COMPILER checks are superfluous because they - * define __GNUC__. They are here to convey to you, dear reader, that these - * macros are enabled when compiling with clang or icc. - */ -#if defined(__clang__) || \ - defined(__GNUC__) || \ - defined(__INTEL_COMPILER) || \ - defined(__SUNPRO_C) -# define UV_DESTRUCTOR(declaration) __attribute__((destructor)) declaration -# define UV_UNUSED(declaration) __attribute__((unused)) declaration -#else -# define UV_DESTRUCTOR(declaration) declaration -# define UV_UNUSED(declaration) declaration -#endif - -#if defined(__linux__) -# define UV__POLLIN UV__EPOLLIN -# define UV__POLLOUT UV__EPOLLOUT -# define UV__POLLERR UV__EPOLLERR -# define UV__POLLHUP UV__EPOLLHUP -#endif - -#if defined(__sun) || defined(_AIX) -# define UV__POLLIN POLLIN -# define UV__POLLOUT POLLOUT -# define UV__POLLERR POLLERR -# define UV__POLLHUP POLLHUP -#endif - -#ifndef UV__POLLIN -# define UV__POLLIN 1 -#endif - -#ifndef UV__POLLOUT -# define UV__POLLOUT 2 -#endif - -#ifndef UV__POLLERR -# define UV__POLLERR 4 -#endif - -#ifndef UV__POLLHUP -# define UV__POLLHUP 8 -#endif - -#if !defined(O_CLOEXEC) && defined(__FreeBSD__) -/* - * It may be that we are just missing `__POSIX_VISIBLE >= 200809`. - * Try using fixed value const and give up, if it doesn't work - */ -# define O_CLOEXEC 0x00100000 -#endif - -typedef struct uv__stream_queued_fds_s uv__stream_queued_fds_t; - -/* handle flags */ -enum { - UV_CLOSING = 0x01, /* uv_close() called but not finished. */ - UV_CLOSED = 0x02, /* close(2) finished. */ - UV_STREAM_READING = 0x04, /* uv_read_start() called. */ - UV_STREAM_SHUTTING = 0x08, /* uv_shutdown() called but not complete. */ - UV_STREAM_SHUT = 0x10, /* Write side closed. */ - UV_STREAM_READABLE = 0x20, /* The stream is readable */ - UV_STREAM_WRITABLE = 0x40, /* The stream is writable */ - UV_STREAM_BLOCKING = 0x80, /* Synchronous writes. */ - UV_STREAM_READ_PARTIAL = 0x100, /* read(2) read less than requested. */ - UV_STREAM_READ_EOF = 0x200, /* read(2) read EOF. */ - UV_TCP_NODELAY = 0x400, /* Disable Nagle. */ - UV_TCP_KEEPALIVE = 0x800, /* Turn on keep-alive. */ - UV_TCP_SINGLE_ACCEPT = 0x1000, /* Only accept() when idle. */ - UV_HANDLE_IPV6 = 0x10000 /* Handle is bound to a IPv6 socket. */ -}; - -/* loop flags */ -enum { - UV_LOOP_BLOCK_SIGPROF = 1 -}; - -typedef enum { - UV_CLOCK_PRECISE = 0, /* Use the highest resolution clock available. */ - UV_CLOCK_FAST = 1 /* Use the fastest clock with <= 1ms granularity. */ -} uv_clocktype_t; - -struct uv__stream_queued_fds_s { - unsigned int size; - unsigned int offset; - int fds[1]; -}; - - -/* core */ -int uv__nonblock(int fd, int set); -int uv__close(int fd); -int uv__cloexec(int fd, int set); -int uv__socket(int domain, int type, int protocol); -int uv__dup(int fd); -ssize_t uv__recvmsg(int fd, struct msghdr *msg, int flags); -void uv__make_close_pending(uv_handle_t* handle); - -void uv__io_init(uv__io_t* w, uv__io_cb cb, int fd); -void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events); -void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events); -void uv__io_close(uv_loop_t* loop, uv__io_t* w); -void uv__io_feed(uv_loop_t* loop, uv__io_t* w); -int uv__io_active(const uv__io_t* w, unsigned int events); -void uv__io_poll(uv_loop_t* loop, int timeout); /* in milliseconds or -1 */ - -/* async */ -void uv__async_send(struct uv__async* wa); -void uv__async_init(struct uv__async* wa); -int uv__async_start(uv_loop_t* loop, struct uv__async* wa, uv__async_cb cb); -void uv__async_stop(uv_loop_t* loop, struct uv__async* wa); - -/* loop */ -void uv__run_idle(uv_loop_t* loop); -void uv__run_check(uv_loop_t* loop); -void uv__run_prepare(uv_loop_t* loop); - -/* stream */ -void uv__stream_init(uv_loop_t* loop, uv_stream_t* stream, - uv_handle_type type); -int uv__stream_open(uv_stream_t*, int fd, int flags); -void uv__stream_destroy(uv_stream_t* stream); -#if defined(__APPLE__) -int uv__stream_try_select(uv_stream_t* stream, int* fd); -#endif /* defined(__APPLE__) */ -void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events); -int uv__accept(int sockfd); -int uv__dup2_cloexec(int oldfd, int newfd); -int uv__open_cloexec(const char* path, int flags); - -/* tcp */ -int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb); -int uv__tcp_nodelay(int fd, int on); -int uv__tcp_keepalive(int fd, int on, unsigned int delay); - -/* pipe */ -int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb); - -/* timer */ -void uv__run_timers(uv_loop_t* loop); -int uv__next_timeout(const uv_loop_t* loop); - -/* signal */ -void uv__signal_close(uv_signal_t* handle); -void uv__signal_global_once_init(void); -void uv__signal_loop_cleanup(uv_loop_t* loop); - -/* platform specific */ -uint64_t uv__hrtime(uv_clocktype_t type); -int uv__kqueue_init(uv_loop_t* loop); -int uv__platform_loop_init(uv_loop_t* loop); -void uv__platform_loop_delete(uv_loop_t* loop); -void uv__platform_invalidate_fd(uv_loop_t* loop, int fd); - -/* various */ -void uv__async_close(uv_async_t* handle); -void uv__check_close(uv_check_t* handle); -void uv__fs_event_close(uv_fs_event_t* handle); -void uv__idle_close(uv_idle_t* handle); -void uv__pipe_close(uv_pipe_t* handle); -void uv__poll_close(uv_poll_t* handle); -void uv__prepare_close(uv_prepare_t* handle); -void uv__process_close(uv_process_t* handle); -void uv__stream_close(uv_stream_t* handle); -void uv__tcp_close(uv_tcp_t* handle); -void uv__timer_close(uv_timer_t* handle); -void uv__udp_close(uv_udp_t* handle); -void uv__udp_finish_close(uv_udp_t* handle); -uv_handle_type uv__handle_type(int fd); - -#if defined(__APPLE__) -int uv___stream_fd(const uv_stream_t* handle); -#define uv__stream_fd(handle) (uv___stream_fd((const uv_stream_t*) (handle))) -#else -#define uv__stream_fd(handle) ((handle)->io_watcher.fd) -#endif /* defined(__APPLE__) */ - -#ifdef UV__O_NONBLOCK -# define UV__F_NONBLOCK UV__O_NONBLOCK -#else -# define UV__F_NONBLOCK 1 -#endif - -int uv__make_socketpair(int fds[2], int flags); -int uv__make_pipe(int fds[2], int flags); - -#if defined(__APPLE__) - -int uv__fsevents_init(uv_fs_event_t* handle); -int uv__fsevents_close(uv_fs_event_t* handle); -void uv__fsevents_loop_delete(uv_loop_t* loop); - -/* OSX < 10.7 has no file events, polyfill them */ -#ifndef MAC_OS_X_VERSION_10_7 - -static const int kFSEventStreamCreateFlagFileEvents = 0x00000010; -static const int kFSEventStreamEventFlagItemCreated = 0x00000100; -static const int kFSEventStreamEventFlagItemRemoved = 0x00000200; -static const int kFSEventStreamEventFlagItemInodeMetaMod = 0x00000400; -static const int kFSEventStreamEventFlagItemRenamed = 0x00000800; -static const int kFSEventStreamEventFlagItemModified = 0x00001000; -static const int kFSEventStreamEventFlagItemFinderInfoMod = 0x00002000; -static const int kFSEventStreamEventFlagItemChangeOwner = 0x00004000; -static const int kFSEventStreamEventFlagItemXattrMod = 0x00008000; -static const int kFSEventStreamEventFlagItemIsFile = 0x00010000; -static const int kFSEventStreamEventFlagItemIsDir = 0x00020000; -static const int kFSEventStreamEventFlagItemIsSymlink = 0x00040000; - -#endif /* __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070 */ - -#endif /* defined(__APPLE__) */ - -UV_UNUSED(static void uv__req_init(uv_loop_t* loop, - uv_req_t* req, - uv_req_type type)) { - req->type = type; - uv__req_register(loop, req); -} -#define uv__req_init(loop, req, type) \ - uv__req_init((loop), (uv_req_t*)(req), (type)) - -UV_UNUSED(static void uv__update_time(uv_loop_t* loop)) { - /* Use a fast time source if available. We only need millisecond precision. - */ - loop->time = uv__hrtime(UV_CLOCK_FAST) / 1000000; -} - -UV_UNUSED(static char* uv__basename_r(const char* path)) { - char* s; - - s = strrchr(path, '/'); - if (s == NULL) - return (char*) path; - - return s + 1; -} - -#endif /* UV_UNIX_INTERNAL_H_ */ diff --git a/libuv/src/unix/kqueue.c b/libuv/src/unix/kqueue.c deleted file mode 100644 index aaadcd8..0000000 --- a/libuv/src/unix/kqueue.c +++ /dev/null @@ -1,418 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -static void uv__fs_event(uv_loop_t* loop, uv__io_t* w, unsigned int fflags); - - -int uv__kqueue_init(uv_loop_t* loop) { - loop->backend_fd = kqueue(); - if (loop->backend_fd == -1) - return -errno; - - uv__cloexec(loop->backend_fd, 1); - - return 0; -} - - -void uv__io_poll(uv_loop_t* loop, int timeout) { - struct kevent events[1024]; - struct kevent* ev; - struct timespec spec; - unsigned int nevents; - unsigned int revents; - QUEUE* q; - uv__io_t* w; - sigset_t* pset; - sigset_t set; - uint64_t base; - uint64_t diff; - int filter; - int fflags; - int count; - int nfds; - int fd; - int op; - int i; - - if (loop->nfds == 0) { - assert(QUEUE_EMPTY(&loop->watcher_queue)); - return; - } - - nevents = 0; - - while (!QUEUE_EMPTY(&loop->watcher_queue)) { - q = QUEUE_HEAD(&loop->watcher_queue); - QUEUE_REMOVE(q); - QUEUE_INIT(q); - - w = QUEUE_DATA(q, uv__io_t, watcher_queue); - assert(w->pevents != 0); - assert(w->fd >= 0); - assert(w->fd < (int) loop->nwatchers); - - if ((w->events & UV__POLLIN) == 0 && (w->pevents & UV__POLLIN) != 0) { - filter = EVFILT_READ; - fflags = 0; - op = EV_ADD; - - if (w->cb == uv__fs_event) { - filter = EVFILT_VNODE; - fflags = NOTE_ATTRIB | NOTE_WRITE | NOTE_RENAME - | NOTE_DELETE | NOTE_EXTEND | NOTE_REVOKE; - op = EV_ADD | EV_ONESHOT; /* Stop the event from firing repeatedly. */ - } - - EV_SET(events + nevents, w->fd, filter, op, fflags, 0, 0); - - if (++nevents == ARRAY_SIZE(events)) { - if (kevent(loop->backend_fd, events, nevents, NULL, 0, NULL)) - abort(); - nevents = 0; - } - } - - if ((w->events & UV__POLLOUT) == 0 && (w->pevents & UV__POLLOUT) != 0) { - EV_SET(events + nevents, w->fd, EVFILT_WRITE, EV_ADD, 0, 0, 0); - - if (++nevents == ARRAY_SIZE(events)) { - if (kevent(loop->backend_fd, events, nevents, NULL, 0, NULL)) - abort(); - nevents = 0; - } - } - - w->events = w->pevents; - } - - pset = NULL; - if (loop->flags & UV_LOOP_BLOCK_SIGPROF) { - pset = &set; - sigemptyset(pset); - sigaddset(pset, SIGPROF); - } - - assert(timeout >= -1); - base = loop->time; - count = 48; /* Benchmarks suggest this gives the best throughput. */ - - for (;; nevents = 0) { - if (timeout != -1) { - spec.tv_sec = timeout / 1000; - spec.tv_nsec = (timeout % 1000) * 1000000; - } - - if (pset != NULL) - pthread_sigmask(SIG_BLOCK, pset, NULL); - - nfds = kevent(loop->backend_fd, - events, - nevents, - events, - ARRAY_SIZE(events), - timeout == -1 ? NULL : &spec); - - if (pset != NULL) - pthread_sigmask(SIG_UNBLOCK, pset, NULL); - - /* Update loop->time unconditionally. It's tempting to skip the update when - * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the - * operating system didn't reschedule our process while in the syscall. - */ - SAVE_ERRNO(uv__update_time(loop)); - - if (nfds == 0) { - assert(timeout != -1); - return; - } - - if (nfds == -1) { - if (errno != EINTR) - abort(); - - if (timeout == 0) - return; - - if (timeout == -1) - continue; - - /* Interrupted by a signal. Update timeout and poll again. */ - goto update_timeout; - } - - nevents = 0; - - assert(loop->watchers != NULL); - loop->watchers[loop->nwatchers] = (void*) events; - loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds; - for (i = 0; i < nfds; i++) { - ev = events + i; - fd = ev->ident; - /* Skip invalidated events, see uv__platform_invalidate_fd */ - if (fd == -1) - continue; - w = loop->watchers[fd]; - - if (w == NULL) { - /* File descriptor that we've stopped watching, disarm it. */ - /* TODO batch up */ - struct kevent events[1]; - - EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0); - if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL)) - if (errno != EBADF && errno != ENOENT) - abort(); - - continue; - } - - if (ev->filter == EVFILT_VNODE) { - assert(w->events == UV__POLLIN); - assert(w->pevents == UV__POLLIN); - w->cb(loop, w, ev->fflags); /* XXX always uv__fs_event() */ - nevents++; - continue; - } - - revents = 0; - - if (ev->filter == EVFILT_READ) { - if (w->pevents & UV__POLLIN) { - revents |= UV__POLLIN; - w->rcount = ev->data; - } else { - /* TODO batch up */ - struct kevent events[1]; - EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0); - if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL)) - if (errno != ENOENT) - abort(); - } - } - - if (ev->filter == EVFILT_WRITE) { - if (w->pevents & UV__POLLOUT) { - revents |= UV__POLLOUT; - w->wcount = ev->data; - } else { - /* TODO batch up */ - struct kevent events[1]; - EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0); - if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL)) - if (errno != ENOENT) - abort(); - } - } - - if (ev->flags & EV_ERROR) - revents |= UV__POLLERR; - - if (revents == 0) - continue; - - w->cb(loop, w, revents); - nevents++; - } - loop->watchers[loop->nwatchers] = NULL; - loop->watchers[loop->nwatchers + 1] = NULL; - - if (nevents != 0) { - if (nfds == ARRAY_SIZE(events) && --count != 0) { - /* Poll for more events but don't block this time. */ - timeout = 0; - continue; - } - return; - } - - if (timeout == 0) - return; - - if (timeout == -1) - continue; - -update_timeout: - assert(timeout > 0); - - diff = loop->time - base; - if (diff >= (uint64_t) timeout) - return; - - timeout -= diff; - } -} - - -void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { - struct kevent* events; - uintptr_t i; - uintptr_t nfds; - - assert(loop->watchers != NULL); - - events = (struct kevent*) loop->watchers[loop->nwatchers]; - nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; - if (events == NULL) - return; - - /* Invalidate events with same file descriptor */ - for (i = 0; i < nfds; i++) - if ((int) events[i].ident == fd) - events[i].ident = -1; -} - - -static void uv__fs_event(uv_loop_t* loop, uv__io_t* w, unsigned int fflags) { - uv_fs_event_t* handle; - struct kevent ev; - int events; - const char* path; -#if defined(F_GETPATH) - /* MAXPATHLEN == PATH_MAX but the former is what XNU calls it internally. */ - char pathbuf[MAXPATHLEN]; -#endif - - handle = container_of(w, uv_fs_event_t, event_watcher); - - if (fflags & (NOTE_ATTRIB | NOTE_EXTEND)) - events = UV_CHANGE; - else - events = UV_RENAME; - - path = NULL; -#if defined(F_GETPATH) - /* Also works when the file has been unlinked from the file system. Passing - * in the path when the file has been deleted is arguably a little strange - * but it's consistent with what the inotify backend does. - */ - if (fcntl(handle->event_watcher.fd, F_GETPATH, pathbuf) == 0) - path = uv__basename_r(pathbuf); -#endif - handle->cb(handle, path, events, 0); - - if (handle->event_watcher.fd == -1) - return; - - /* Watcher operates in one-shot mode, re-arm it. */ - fflags = NOTE_ATTRIB | NOTE_WRITE | NOTE_RENAME - | NOTE_DELETE | NOTE_EXTEND | NOTE_REVOKE; - - EV_SET(&ev, w->fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, fflags, 0, 0); - - if (kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL)) - abort(); -} - - -int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { - uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); - return 0; -} - - -int uv_fs_event_start(uv_fs_event_t* handle, - uv_fs_event_cb cb, - const char* path, - unsigned int flags) { -#if defined(__APPLE__) - struct stat statbuf; -#endif /* defined(__APPLE__) */ - int fd; - - if (uv__is_active(handle)) - return -EINVAL; - - /* TODO open asynchronously - but how do we report back errors? */ - fd = open(path, O_RDONLY); - if (fd == -1) - return -errno; - - uv__handle_start(handle); - uv__io_init(&handle->event_watcher, uv__fs_event, fd); - handle->path = strdup(path); - handle->cb = cb; - -#if defined(__APPLE__) - /* Nullify field to perform checks later */ - handle->cf_cb = NULL; - handle->realpath = NULL; - handle->realpath_len = 0; - handle->cf_flags = flags; - - if (fstat(fd, &statbuf)) - goto fallback; - /* FSEvents works only with directories */ - if (!(statbuf.st_mode & S_IFDIR)) - goto fallback; - - return uv__fsevents_init(handle); - -fallback: -#endif /* defined(__APPLE__) */ - - uv__io_start(handle->loop, &handle->event_watcher, UV__POLLIN); - - return 0; -} - - -int uv_fs_event_stop(uv_fs_event_t* handle) { - if (!uv__is_active(handle)) - return 0; - - uv__handle_stop(handle); - -#if defined(__APPLE__) - if (uv__fsevents_close(handle)) -#endif /* defined(__APPLE__) */ - { - uv__io_close(handle->loop, &handle->event_watcher); - } - - free(handle->path); - handle->path = NULL; - - uv__close(handle->event_watcher.fd); - handle->event_watcher.fd = -1; - - return 0; -} - - -void uv__fs_event_close(uv_fs_event_t* handle) { - uv_fs_event_stop(handle); -} diff --git a/libuv/src/unix/linux-core.c b/libuv/src/unix/linux-core.c deleted file mode 100644 index c1be21a..0000000 --- a/libuv/src/unix/linux-core.c +++ /dev/null @@ -1,871 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#define HAVE_IFADDRS_H 1 - -#ifdef __UCLIBC__ -# if __UCLIBC_MAJOR__ < 0 || __UCLIBC_MINOR__ < 9 || __UCLIBC_SUBLEVEL__ < 32 -# undef HAVE_IFADDRS_H -# endif -#endif - -#ifdef HAVE_IFADDRS_H -# if defined(__ANDROID__) -# include "android-ifaddrs.h" -# else -# include -# endif -# include -# include -# include -#endif /* HAVE_IFADDRS_H */ - -/* Available from 2.6.32 onwards. */ -#ifndef CLOCK_MONOTONIC_COARSE -# define CLOCK_MONOTONIC_COARSE 6 -#endif - -/* This is rather annoying: CLOCK_BOOTTIME lives in but we can't - * include that file because it conflicts with . We'll just have to - * define it ourselves. - */ -#ifndef CLOCK_BOOTTIME -# define CLOCK_BOOTTIME 7 -#endif - -static int read_models(unsigned int numcpus, uv_cpu_info_t* ci); -static int read_times(unsigned int numcpus, uv_cpu_info_t* ci); -static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci); -static unsigned long read_cpufreq(unsigned int cpunum); - - -int uv__platform_loop_init(uv_loop_t* loop) { - int fd; - - fd = uv__epoll_create1(UV__EPOLL_CLOEXEC); - - /* epoll_create1() can fail either because it's not implemented (old kernel) - * or because it doesn't understand the EPOLL_CLOEXEC flag. - */ - if (fd == -1 && (errno == ENOSYS || errno == EINVAL)) { - fd = uv__epoll_create(256); - - if (fd != -1) - uv__cloexec(fd, 1); - } - - loop->backend_fd = fd; - loop->inotify_fd = -1; - loop->inotify_watchers = NULL; - - if (fd == -1) - return -errno; - - return 0; -} - - -void uv__platform_loop_delete(uv_loop_t* loop) { - if (loop->inotify_fd == -1) return; - uv__io_stop(loop, &loop->inotify_read_watcher, UV__POLLIN); - uv__close(loop->inotify_fd); - loop->inotify_fd = -1; -} - - -void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { - struct uv__epoll_event* events; - struct uv__epoll_event dummy; - uintptr_t i; - uintptr_t nfds; - - assert(loop->watchers != NULL); - - events = (struct uv__epoll_event*) loop->watchers[loop->nwatchers]; - nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; - if (events != NULL) - /* Invalidate events with same file descriptor */ - for (i = 0; i < nfds; i++) - if ((int) events[i].data == fd) - events[i].data = -1; - - /* Remove the file descriptor from the epoll. - * This avoids a problem where the same file description remains open - * in another process, causing repeated junk epoll events. - * - * We pass in a dummy epoll_event, to work around a bug in old kernels. - */ - if (loop->backend_fd >= 0) - uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_DEL, fd, &dummy); -} - - -void uv__io_poll(uv_loop_t* loop, int timeout) { - static int no_epoll_pwait; - static int no_epoll_wait; - struct uv__epoll_event events[1024]; - struct uv__epoll_event* pe; - struct uv__epoll_event e; - QUEUE* q; - uv__io_t* w; - sigset_t sigset; - uint64_t sigmask; - uint64_t base; - uint64_t diff; - int nevents; - int count; - int nfds; - int fd; - int op; - int i; - - if (loop->nfds == 0) { - assert(QUEUE_EMPTY(&loop->watcher_queue)); - return; - } - - while (!QUEUE_EMPTY(&loop->watcher_queue)) { - q = QUEUE_HEAD(&loop->watcher_queue); - QUEUE_REMOVE(q); - QUEUE_INIT(q); - - w = QUEUE_DATA(q, uv__io_t, watcher_queue); - assert(w->pevents != 0); - assert(w->fd >= 0); - assert(w->fd < (int) loop->nwatchers); - - e.events = w->pevents; - e.data = w->fd; - - if (w->events == 0) - op = UV__EPOLL_CTL_ADD; - else - op = UV__EPOLL_CTL_MOD; - - /* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching - * events, skip the syscall and squelch the events after epoll_wait(). - */ - if (uv__epoll_ctl(loop->backend_fd, op, w->fd, &e)) { - if (errno != EEXIST) - abort(); - - assert(op == UV__EPOLL_CTL_ADD); - - /* We've reactivated a file descriptor that's been watched before. */ - if (uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_MOD, w->fd, &e)) - abort(); - } - - w->events = w->pevents; - } - - sigmask = 0; - if (loop->flags & UV_LOOP_BLOCK_SIGPROF) { - sigemptyset(&sigset); - sigaddset(&sigset, SIGPROF); - sigmask |= 1 << (SIGPROF - 1); - } - - assert(timeout >= -1); - base = loop->time; - count = 48; /* Benchmarks suggest this gives the best throughput. */ - - for (;;) { - if (sigmask != 0 && no_epoll_pwait != 0) - if (pthread_sigmask(SIG_BLOCK, &sigset, NULL)) - abort(); - - if (sigmask != 0 && no_epoll_pwait == 0) { - nfds = uv__epoll_pwait(loop->backend_fd, - events, - ARRAY_SIZE(events), - timeout, - sigmask); - if (nfds == -1 && errno == ENOSYS) - no_epoll_pwait = 1; - } else { - nfds = uv__epoll_wait(loop->backend_fd, - events, - ARRAY_SIZE(events), - timeout); - if (nfds == -1 && errno == ENOSYS) - no_epoll_wait = 1; - } - - if (sigmask != 0 && no_epoll_pwait != 0) - if (pthread_sigmask(SIG_UNBLOCK, &sigset, NULL)) - abort(); - - /* Update loop->time unconditionally. It's tempting to skip the update when - * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the - * operating system didn't reschedule our process while in the syscall. - */ - SAVE_ERRNO(uv__update_time(loop)); - - if (nfds == 0) { - assert(timeout != -1); - return; - } - - if (nfds == -1) { - if (errno == ENOSYS) { - /* epoll_wait() or epoll_pwait() failed, try the other system call. */ - assert(no_epoll_wait == 0 || no_epoll_pwait == 0); - continue; - } - - if (errno != EINTR) - abort(); - - if (timeout == -1) - continue; - - if (timeout == 0) - return; - - /* Interrupted by a signal. Update timeout and poll again. */ - goto update_timeout; - } - - nevents = 0; - - assert(loop->watchers != NULL); - loop->watchers[loop->nwatchers] = (void*) events; - loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds; - for (i = 0; i < nfds; i++) { - pe = events + i; - fd = pe->data; - - /* Skip invalidated events, see uv__platform_invalidate_fd */ - if (fd == -1) - continue; - - assert(fd >= 0); - assert((unsigned) fd < loop->nwatchers); - - w = loop->watchers[fd]; - - if (w == NULL) { - /* File descriptor that we've stopped watching, disarm it. - * - * Ignore all errors because we may be racing with another thread - * when the file descriptor is closed. - */ - uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_DEL, fd, pe); - continue; - } - - /* Give users only events they're interested in. Prevents spurious - * callbacks when previous callback invocation in this loop has stopped - * the current watcher. Also, filters out events that users has not - * requested us to watch. - */ - pe->events &= w->pevents | UV__POLLERR | UV__POLLHUP; - - /* Work around an epoll quirk where it sometimes reports just the - * EPOLLERR or EPOLLHUP event. In order to force the event loop to - * move forward, we merge in the read/write events that the watcher - * is interested in; uv__read() and uv__write() will then deal with - * the error or hangup in the usual fashion. - * - * Note to self: happens when epoll reports EPOLLIN|EPOLLHUP, the user - * reads the available data, calls uv_read_stop(), then sometime later - * calls uv_read_start() again. By then, libuv has forgotten about the - * hangup and the kernel won't report EPOLLIN again because there's - * nothing left to read. If anything, libuv is to blame here. The - * current hack is just a quick bandaid; to properly fix it, libuv - * needs to remember the error/hangup event. We should get that for - * free when we switch over to edge-triggered I/O. - */ - if (pe->events == UV__EPOLLERR || pe->events == UV__EPOLLHUP) - pe->events |= w->pevents & (UV__EPOLLIN | UV__EPOLLOUT); - - if (pe->events != 0) { - w->cb(loop, w, pe->events); - nevents++; - } - } - loop->watchers[loop->nwatchers] = NULL; - loop->watchers[loop->nwatchers + 1] = NULL; - - if (nevents != 0) { - if (nfds == ARRAY_SIZE(events) && --count != 0) { - /* Poll for more events but don't block this time. */ - timeout = 0; - continue; - } - return; - } - - if (timeout == 0) - return; - - if (timeout == -1) - continue; - -update_timeout: - assert(timeout > 0); - - diff = loop->time - base; - if (diff >= (uint64_t) timeout) - return; - - timeout -= diff; - } -} - - -uint64_t uv__hrtime(uv_clocktype_t type) { - static clock_t fast_clock_id = -1; - struct timespec t; - clock_t clock_id; - - /* Prefer CLOCK_MONOTONIC_COARSE if available but only when it has - * millisecond granularity or better. CLOCK_MONOTONIC_COARSE is - * serviced entirely from the vDSO, whereas CLOCK_MONOTONIC may - * decide to make a costly system call. - */ - /* TODO(bnoordhuis) Use CLOCK_MONOTONIC_COARSE for UV_CLOCK_PRECISE - * when it has microsecond granularity or better (unlikely). - */ - if (type == UV_CLOCK_FAST && fast_clock_id == -1) { - if (clock_getres(CLOCK_MONOTONIC_COARSE, &t) == 0 && - t.tv_nsec <= 1 * 1000 * 1000) { - fast_clock_id = CLOCK_MONOTONIC_COARSE; - } else { - fast_clock_id = CLOCK_MONOTONIC; - } - } - - clock_id = CLOCK_MONOTONIC; - if (type == UV_CLOCK_FAST) - clock_id = fast_clock_id; - - if (clock_gettime(clock_id, &t)) - return 0; /* Not really possible. */ - - return t.tv_sec * (uint64_t) 1e9 + t.tv_nsec; -} - - -void uv_loadavg(double avg[3]) { - struct sysinfo info; - - if (sysinfo(&info) < 0) return; - - avg[0] = (double) info.loads[0] / 65536.0; - avg[1] = (double) info.loads[1] / 65536.0; - avg[2] = (double) info.loads[2] / 65536.0; -} - - -int uv_exepath(char* buffer, size_t* size) { - ssize_t n; - - if (buffer == NULL || size == NULL || *size == 0) - return -EINVAL; - - n = *size - 1; - if (n > 0) - n = readlink("/proc/self/exe", buffer, n); - - if (n == -1) - return -errno; - - buffer[n] = '\0'; - *size = n; - - return 0; -} - - -uint64_t uv_get_free_memory(void) { - return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_AVPHYS_PAGES); -} - - -uint64_t uv_get_total_memory(void) { - return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_PHYS_PAGES); -} - - -int uv_resident_set_memory(size_t* rss) { - char buf[1024]; - const char* s; - ssize_t n; - long val; - int fd; - int i; - - do - fd = open("/proc/self/stat", O_RDONLY); - while (fd == -1 && errno == EINTR); - - if (fd == -1) - return -errno; - - do - n = read(fd, buf, sizeof(buf) - 1); - while (n == -1 && errno == EINTR); - - uv__close(fd); - if (n == -1) - return -errno; - buf[n] = '\0'; - - s = strchr(buf, ' '); - if (s == NULL) - goto err; - - s += 1; - if (*s != '(') - goto err; - - s = strchr(s, ')'); - if (s == NULL) - goto err; - - for (i = 1; i <= 22; i++) { - s = strchr(s + 1, ' '); - if (s == NULL) - goto err; - } - - errno = 0; - val = strtol(s, NULL, 10); - if (errno != 0) - goto err; - if (val < 0) - goto err; - - *rss = val * getpagesize(); - return 0; - -err: - return -EINVAL; -} - - -int uv_uptime(double* uptime) { - static volatile int no_clock_boottime; - struct timespec now; - int r; - - /* Try CLOCK_BOOTTIME first, fall back to CLOCK_MONOTONIC if not available - * (pre-2.6.39 kernels). CLOCK_MONOTONIC doesn't increase when the system - * is suspended. - */ - if (no_clock_boottime) { - retry: r = clock_gettime(CLOCK_MONOTONIC, &now); - } - else if ((r = clock_gettime(CLOCK_BOOTTIME, &now)) && errno == EINVAL) { - no_clock_boottime = 1; - goto retry; - } - - if (r) - return -errno; - - *uptime = now.tv_sec; - return 0; -} - - -int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { - unsigned int numcpus; - uv_cpu_info_t* ci; - int err; - - *cpu_infos = NULL; - *count = 0; - - numcpus = sysconf(_SC_NPROCESSORS_ONLN); - assert(numcpus != (unsigned int) -1); - assert(numcpus != 0); - - ci = calloc(numcpus, sizeof(*ci)); - if (ci == NULL) - return -ENOMEM; - - err = read_models(numcpus, ci); - if (err == 0) - err = read_times(numcpus, ci); - - if (err) { - uv_free_cpu_info(ci, numcpus); - return err; - } - - /* read_models() on x86 also reads the CPU speed from /proc/cpuinfo. - * We don't check for errors here. Worst case, the field is left zero. - */ - if (ci[0].speed == 0) - read_speeds(numcpus, ci); - - *cpu_infos = ci; - *count = numcpus; - - return 0; -} - - -static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci) { - unsigned int num; - - for (num = 0; num < numcpus; num++) - ci[num].speed = read_cpufreq(num) / 1000; -} - - -/* Also reads the CPU frequency on x86. The other architectures only have - * a BogoMIPS field, which may not be very accurate. - * - * Note: Simply returns on error, uv_cpu_info() takes care of the cleanup. - */ -static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) { - static const char model_marker[] = "model name\t: "; - static const char speed_marker[] = "cpu MHz\t\t: "; - const char* inferred_model; - unsigned int model_idx; - unsigned int speed_idx; - char buf[1024]; - char* model; - FILE* fp; - - /* Most are unused on non-ARM, non-MIPS and non-x86 architectures. */ - (void) &model_marker; - (void) &speed_marker; - (void) &speed_idx; - (void) &model; - (void) &buf; - (void) &fp; - - model_idx = 0; - speed_idx = 0; - -#if defined(__arm__) || \ - defined(__i386__) || \ - defined(__mips__) || \ - defined(__x86_64__) - fp = fopen("/proc/cpuinfo", "r"); - if (fp == NULL) - return -errno; - - while (fgets(buf, sizeof(buf), fp)) { - if (model_idx < numcpus) { - if (strncmp(buf, model_marker, sizeof(model_marker) - 1) == 0) { - model = buf + sizeof(model_marker) - 1; - model = strndup(model, strlen(model) - 1); /* Strip newline. */ - if (model == NULL) { - fclose(fp); - return -ENOMEM; - } - ci[model_idx++].model = model; - continue; - } - } -#if defined(__arm__) || defined(__mips__) - if (model_idx < numcpus) { -#if defined(__arm__) - /* Fallback for pre-3.8 kernels. */ - static const char model_marker[] = "Processor\t: "; -#else /* defined(__mips__) */ - static const char model_marker[] = "cpu model\t\t: "; -#endif - if (strncmp(buf, model_marker, sizeof(model_marker) - 1) == 0) { - model = buf + sizeof(model_marker) - 1; - model = strndup(model, strlen(model) - 1); /* Strip newline. */ - if (model == NULL) { - fclose(fp); - return -ENOMEM; - } - ci[model_idx++].model = model; - continue; - } - } -#else /* !__arm__ && !__mips__ */ - if (speed_idx < numcpus) { - if (strncmp(buf, speed_marker, sizeof(speed_marker) - 1) == 0) { - ci[speed_idx++].speed = atoi(buf + sizeof(speed_marker) - 1); - continue; - } - } -#endif /* __arm__ || __mips__ */ - } - - fclose(fp); -#endif /* __arm__ || __i386__ || __mips__ || __x86_64__ */ - - /* Now we want to make sure that all the models contain *something* because - * it's not safe to leave them as null. Copy the last entry unless there - * isn't one, in that case we simply put "unknown" into everything. - */ - inferred_model = "unknown"; - if (model_idx > 0) - inferred_model = ci[model_idx - 1].model; - - while (model_idx < numcpus) { - model = strndup(inferred_model, strlen(inferred_model)); - if (model == NULL) - return -ENOMEM; - ci[model_idx++].model = model; - } - - return 0; -} - - -static int read_times(unsigned int numcpus, uv_cpu_info_t* ci) { - unsigned long clock_ticks; - struct uv_cpu_times_s ts; - unsigned long user; - unsigned long nice; - unsigned long sys; - unsigned long idle; - unsigned long dummy; - unsigned long irq; - unsigned int num; - unsigned int len; - char buf[1024]; - FILE* fp; - - clock_ticks = sysconf(_SC_CLK_TCK); - assert(clock_ticks != (unsigned long) -1); - assert(clock_ticks != 0); - - fp = fopen("/proc/stat", "r"); - if (fp == NULL) - return -errno; - - if (!fgets(buf, sizeof(buf), fp)) - abort(); - - num = 0; - - while (fgets(buf, sizeof(buf), fp)) { - if (num >= numcpus) - break; - - if (strncmp(buf, "cpu", 3)) - break; - - /* skip "cpu " marker */ - { - unsigned int n; - int r = sscanf(buf, "cpu%u ", &n); - assert(r == 1); - (void) r; /* silence build warning */ - for (len = sizeof("cpu0"); n /= 10; len++); - } - - /* Line contains user, nice, system, idle, iowait, irq, softirq, steal, - * guest, guest_nice but we're only interested in the first four + irq. - * - * Don't use %*s to skip fields or %ll to read straight into the uint64_t - * fields, they're not allowed in C89 mode. - */ - if (6 != sscanf(buf + len, - "%lu %lu %lu %lu %lu %lu", - &user, - &nice, - &sys, - &idle, - &dummy, - &irq)) - abort(); - - ts.user = clock_ticks * user; - ts.nice = clock_ticks * nice; - ts.sys = clock_ticks * sys; - ts.idle = clock_ticks * idle; - ts.irq = clock_ticks * irq; - ci[num++].cpu_times = ts; - } - fclose(fp); - assert(num == numcpus); - - return 0; -} - - -static unsigned long read_cpufreq(unsigned int cpunum) { - unsigned long val; - char buf[1024]; - FILE* fp; - - snprintf(buf, - sizeof(buf), - "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_cur_freq", - cpunum); - - fp = fopen(buf, "r"); - if (fp == NULL) - return 0; - - if (fscanf(fp, "%lu", &val) != 1) - val = 0; - - fclose(fp); - - return val; -} - - -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - int i; - - for (i = 0; i < count; i++) { - free(cpu_infos[i].model); - } - - free(cpu_infos); -} - - -int uv_interface_addresses(uv_interface_address_t** addresses, - int* count) { -#ifndef HAVE_IFADDRS_H - return -ENOSYS; -#else - struct ifaddrs *addrs, *ent; - uv_interface_address_t* address; - int i; - struct sockaddr_ll *sll; - - if (getifaddrs(&addrs)) - return -errno; - - *count = 0; - *addresses = NULL; - - /* Count the number of interfaces */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family == PF_PACKET)) { - continue; - } - - (*count)++; - } - - if (*count == 0) - return 0; - - *addresses = malloc(*count * sizeof(**addresses)); - if (!(*addresses)) - return -ENOMEM; - - address = *addresses; - - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) - continue; - - if (ent->ifa_addr == NULL) - continue; - - /* - * On Linux getifaddrs returns information related to the raw underlying - * devices. We're not interested in this information yet. - */ - if (ent->ifa_addr->sa_family == PF_PACKET) - continue; - - address->name = strdup(ent->ifa_name); - - if (ent->ifa_addr->sa_family == AF_INET6) { - address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr); - } else { - address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr); - } - - if (ent->ifa_netmask->sa_family == AF_INET6) { - address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask); - } else { - address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask); - } - - address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK); - - address++; - } - - /* Fill in physical addresses for each interface */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family != PF_PACKET)) { - continue; - } - - address = *addresses; - - for (i = 0; i < (*count); i++) { - if (strcmp(address->name, ent->ifa_name) == 0) { - sll = (struct sockaddr_ll*)ent->ifa_addr; - memcpy(address->phys_addr, sll->sll_addr, sizeof(address->phys_addr)); - } - address++; - } - } - - freeifaddrs(addrs); - - return 0; -#endif -} - - -void uv_free_interface_addresses(uv_interface_address_t* addresses, - int count) { - int i; - - for (i = 0; i < count; i++) { - free(addresses[i].name); - } - - free(addresses); -} - - -void uv__set_process_title(const char* title) { -#if defined(PR_SET_NAME) - prctl(PR_SET_NAME, title); /* Only copies first 16 characters. */ -#endif -} diff --git a/libuv/src/unix/linux-inotify.c b/libuv/src/unix/linux-inotify.c deleted file mode 100644 index 2ecc5eb..0000000 --- a/libuv/src/unix/linux-inotify.c +++ /dev/null @@ -1,257 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "tree.h" -#include "internal.h" - -#include -#include -#include -#include -#include -#include - -#include -#include - -struct watcher_list { - RB_ENTRY(watcher_list) entry; - QUEUE watchers; - char* path; - int wd; -}; - -struct watcher_root { - struct watcher_list* rbh_root; -}; -#define CAST(p) ((struct watcher_root*)(p)) - - -static int compare_watchers(const struct watcher_list* a, - const struct watcher_list* b) { - if (a->wd < b->wd) return -1; - if (a->wd > b->wd) return 1; - return 0; -} - - -RB_GENERATE_STATIC(watcher_root, watcher_list, entry, compare_watchers) - - -static void uv__inotify_read(uv_loop_t* loop, - uv__io_t* w, - unsigned int revents); - - -static int new_inotify_fd(void) { - int err; - int fd; - - fd = uv__inotify_init1(UV__IN_NONBLOCK | UV__IN_CLOEXEC); - if (fd != -1) - return fd; - - if (errno != ENOSYS) - return -errno; - - fd = uv__inotify_init(); - if (fd == -1) - return -errno; - - err = uv__cloexec(fd, 1); - if (err == 0) - err = uv__nonblock(fd, 1); - - if (err) { - uv__close(fd); - return err; - } - - return fd; -} - - -static int init_inotify(uv_loop_t* loop) { - int err; - - if (loop->inotify_fd != -1) - return 0; - - err = new_inotify_fd(); - if (err < 0) - return err; - - loop->inotify_fd = err; - uv__io_init(&loop->inotify_read_watcher, uv__inotify_read, loop->inotify_fd); - uv__io_start(loop, &loop->inotify_read_watcher, UV__POLLIN); - - return 0; -} - - -static struct watcher_list* find_watcher(uv_loop_t* loop, int wd) { - struct watcher_list w; - w.wd = wd; - return RB_FIND(watcher_root, CAST(&loop->inotify_watchers), &w); -} - - -static void uv__inotify_read(uv_loop_t* loop, - uv__io_t* dummy, - unsigned int events) { - const struct uv__inotify_event* e; - struct watcher_list* w; - uv_fs_event_t* h; - QUEUE* q; - const char* path; - ssize_t size; - const char *p; - /* needs to be large enough for sizeof(inotify_event) + strlen(path) */ - char buf[4096]; - - while (1) { - do - size = read(loop->inotify_fd, buf, sizeof(buf)); - while (size == -1 && errno == EINTR); - - if (size == -1) { - assert(errno == EAGAIN || errno == EWOULDBLOCK); - break; - } - - assert(size > 0); /* pre-2.6.21 thing, size=0 == read buffer too small */ - - /* Now we have one or more inotify_event structs. */ - for (p = buf; p < buf + size; p += sizeof(*e) + e->len) { - e = (const struct uv__inotify_event*)p; - - events = 0; - if (e->mask & (UV__IN_ATTRIB|UV__IN_MODIFY)) - events |= UV_CHANGE; - if (e->mask & ~(UV__IN_ATTRIB|UV__IN_MODIFY)) - events |= UV_RENAME; - - w = find_watcher(loop, e->wd); - if (w == NULL) - continue; /* Stale event, no watchers left. */ - - /* inotify does not return the filename when monitoring a single file - * for modifications. Repurpose the filename for API compatibility. - * I'm not convinced this is a good thing, maybe it should go. - */ - path = e->len ? (const char*) (e + 1) : uv__basename_r(w->path); - - QUEUE_FOREACH(q, &w->watchers) { - h = QUEUE_DATA(q, uv_fs_event_t, watchers); - h->cb(h, path, events, 0); - } - } - } -} - - -int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { - uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); - return 0; -} - - -int uv_fs_event_start(uv_fs_event_t* handle, - uv_fs_event_cb cb, - const char* path, - unsigned int flags) { - struct watcher_list* w; - int events; - int err; - int wd; - - if (uv__is_active(handle)) - return -EINVAL; - - err = init_inotify(handle->loop); - if (err) - return err; - - events = UV__IN_ATTRIB - | UV__IN_CREATE - | UV__IN_MODIFY - | UV__IN_DELETE - | UV__IN_DELETE_SELF - | UV__IN_MOVE_SELF - | UV__IN_MOVED_FROM - | UV__IN_MOVED_TO; - - wd = uv__inotify_add_watch(handle->loop->inotify_fd, path, events); - if (wd == -1) - return -errno; - - w = find_watcher(handle->loop, wd); - if (w) - goto no_insert; - - w = malloc(sizeof(*w) + strlen(path) + 1); - if (w == NULL) - return -ENOMEM; - - w->wd = wd; - w->path = strcpy((char*)(w + 1), path); - QUEUE_INIT(&w->watchers); - RB_INSERT(watcher_root, CAST(&handle->loop->inotify_watchers), w); - -no_insert: - uv__handle_start(handle); - QUEUE_INSERT_TAIL(&w->watchers, &handle->watchers); - handle->path = w->path; - handle->cb = cb; - handle->wd = wd; - - return 0; -} - - -int uv_fs_event_stop(uv_fs_event_t* handle) { - struct watcher_list* w; - - if (!uv__is_active(handle)) - return 0; - - w = find_watcher(handle->loop, handle->wd); - assert(w != NULL); - - handle->wd = -1; - handle->path = NULL; - uv__handle_stop(handle); - QUEUE_REMOVE(&handle->watchers); - - if (QUEUE_EMPTY(&w->watchers)) { - /* No watchers left for this path. Clean up. */ - RB_REMOVE(watcher_root, CAST(&handle->loop->inotify_watchers), w); - uv__inotify_rm_watch(handle->loop->inotify_fd, w->wd); - free(w); - } - - return 0; -} - - -void uv__fs_event_close(uv_fs_event_t* handle) { - uv_fs_event_stop(handle); -} diff --git a/libuv/src/unix/linux-syscalls.c b/libuv/src/unix/linux-syscalls.c deleted file mode 100644 index 7bf2c0f..0000000 --- a/libuv/src/unix/linux-syscalls.c +++ /dev/null @@ -1,446 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "linux-syscalls.h" -#include -#include -#include -#include -#include - -#if defined(__i386__) -# ifndef __NR_socketcall -# define __NR_socketcall 102 -# endif -#endif - -#if defined(__arm__) -# if defined(__thumb__) || defined(__ARM_EABI__) -# define UV_SYSCALL_BASE 0 -# else -# define UV_SYSCALL_BASE 0x900000 -# endif -#endif /* __arm__ */ - -#ifndef __NR_accept4 -# if defined(__x86_64__) -# define __NR_accept4 288 -# elif defined(__i386__) - /* Nothing. Handled through socketcall(). */ -# elif defined(__arm__) -# define __NR_accept4 (UV_SYSCALL_BASE + 366) -# endif -#endif /* __NR_accept4 */ - -#ifndef __NR_eventfd -# if defined(__x86_64__) -# define __NR_eventfd 284 -# elif defined(__i386__) -# define __NR_eventfd 323 -# elif defined(__arm__) -# define __NR_eventfd (UV_SYSCALL_BASE + 351) -# endif -#endif /* __NR_eventfd */ - -#ifndef __NR_eventfd2 -# if defined(__x86_64__) -# define __NR_eventfd2 290 -# elif defined(__i386__) -# define __NR_eventfd2 328 -# elif defined(__arm__) -# define __NR_eventfd2 (UV_SYSCALL_BASE + 356) -# endif -#endif /* __NR_eventfd2 */ - -#ifndef __NR_epoll_create -# if defined(__x86_64__) -# define __NR_epoll_create 213 -# elif defined(__i386__) -# define __NR_epoll_create 254 -# elif defined(__arm__) -# define __NR_epoll_create (UV_SYSCALL_BASE + 250) -# endif -#endif /* __NR_epoll_create */ - -#ifndef __NR_epoll_create1 -# if defined(__x86_64__) -# define __NR_epoll_create1 291 -# elif defined(__i386__) -# define __NR_epoll_create1 329 -# elif defined(__arm__) -# define __NR_epoll_create1 (UV_SYSCALL_BASE + 357) -# endif -#endif /* __NR_epoll_create1 */ - -#ifndef __NR_epoll_ctl -# if defined(__x86_64__) -# define __NR_epoll_ctl 233 /* used to be 214 */ -# elif defined(__i386__) -# define __NR_epoll_ctl 255 -# elif defined(__arm__) -# define __NR_epoll_ctl (UV_SYSCALL_BASE + 251) -# endif -#endif /* __NR_epoll_ctl */ - -#ifndef __NR_epoll_wait -# if defined(__x86_64__) -# define __NR_epoll_wait 232 /* used to be 215 */ -# elif defined(__i386__) -# define __NR_epoll_wait 256 -# elif defined(__arm__) -# define __NR_epoll_wait (UV_SYSCALL_BASE + 252) -# endif -#endif /* __NR_epoll_wait */ - -#ifndef __NR_epoll_pwait -# if defined(__x86_64__) -# define __NR_epoll_pwait 281 -# elif defined(__i386__) -# define __NR_epoll_pwait 319 -# elif defined(__arm__) -# define __NR_epoll_pwait (UV_SYSCALL_BASE + 346) -# endif -#endif /* __NR_epoll_pwait */ - -#ifndef __NR_inotify_init -# if defined(__x86_64__) -# define __NR_inotify_init 253 -# elif defined(__i386__) -# define __NR_inotify_init 291 -# elif defined(__arm__) -# define __NR_inotify_init (UV_SYSCALL_BASE + 316) -# endif -#endif /* __NR_inotify_init */ - -#ifndef __NR_inotify_init1 -# if defined(__x86_64__) -# define __NR_inotify_init1 294 -# elif defined(__i386__) -# define __NR_inotify_init1 332 -# elif defined(__arm__) -# define __NR_inotify_init1 (UV_SYSCALL_BASE + 360) -# endif -#endif /* __NR_inotify_init1 */ - -#ifndef __NR_inotify_add_watch -# if defined(__x86_64__) -# define __NR_inotify_add_watch 254 -# elif defined(__i386__) -# define __NR_inotify_add_watch 292 -# elif defined(__arm__) -# define __NR_inotify_add_watch (UV_SYSCALL_BASE + 317) -# endif -#endif /* __NR_inotify_add_watch */ - -#ifndef __NR_inotify_rm_watch -# if defined(__x86_64__) -# define __NR_inotify_rm_watch 255 -# elif defined(__i386__) -# define __NR_inotify_rm_watch 293 -# elif defined(__arm__) -# define __NR_inotify_rm_watch (UV_SYSCALL_BASE + 318) -# endif -#endif /* __NR_inotify_rm_watch */ - -#ifndef __NR_pipe2 -# if defined(__x86_64__) -# define __NR_pipe2 293 -# elif defined(__i386__) -# define __NR_pipe2 331 -# elif defined(__arm__) -# define __NR_pipe2 (UV_SYSCALL_BASE + 359) -# endif -#endif /* __NR_pipe2 */ - -#ifndef __NR_recvmmsg -# if defined(__x86_64__) -# define __NR_recvmmsg 299 -# elif defined(__i386__) -# define __NR_recvmmsg 337 -# elif defined(__arm__) -# define __NR_recvmmsg (UV_SYSCALL_BASE + 365) -# endif -#endif /* __NR_recvmsg */ - -#ifndef __NR_sendmmsg -# if defined(__x86_64__) -# define __NR_sendmmsg 307 -# elif defined(__i386__) -# define __NR_sendmmsg 345 -# elif defined(__arm__) -# define __NR_sendmmsg (UV_SYSCALL_BASE + 374) -# endif -#endif /* __NR_sendmmsg */ - -#ifndef __NR_utimensat -# if defined(__x86_64__) -# define __NR_utimensat 280 -# elif defined(__i386__) -# define __NR_utimensat 320 -# elif defined(__arm__) -# define __NR_utimensat (UV_SYSCALL_BASE + 348) -# endif -#endif /* __NR_utimensat */ - -#ifndef __NR_preadv -# if defined(__x86_64__) -# define __NR_preadv 295 -# elif defined(__i386__) -# define __NR_preadv 333 -# elif defined(__arm__) -# define __NR_preadv (UV_SYSCALL_BASE + 361) -# endif -#endif /* __NR_preadv */ - -#ifndef __NR_pwritev -# if defined(__x86_64__) -# define __NR_pwritev 296 -# elif defined(__i386__) -# define __NR_pwritev 334 -# elif defined(__arm__) -# define __NR_pwritev (UV_SYSCALL_BASE + 362) -# endif -#endif /* __NR_pwritev */ - -#ifndef __NR_dup3 -# if defined(__x86_64__) -# define __NR_dup3 292 -# elif defined(__i386__) -# define __NR_dup3 330 -# elif defined(__arm__) -# define __NR_dup3 (UV_SYSCALL_BASE + 358) -# endif -#endif /* __NR_pwritev */ - - -int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) { -#if defined(__i386__) - unsigned long args[4]; - int r; - - args[0] = (unsigned long) fd; - args[1] = (unsigned long) addr; - args[2] = (unsigned long) addrlen; - args[3] = (unsigned long) flags; - - r = syscall(__NR_socketcall, 18 /* SYS_ACCEPT4 */, args); - - /* socketcall() raises EINVAL when SYS_ACCEPT4 is not supported but so does - * a bad flags argument. Try to distinguish between the two cases. - */ - if (r == -1) - if (errno == EINVAL) - if ((flags & ~(UV__SOCK_CLOEXEC|UV__SOCK_NONBLOCK)) == 0) - errno = ENOSYS; - - return r; -#elif defined(__NR_accept4) - return syscall(__NR_accept4, fd, addr, addrlen, flags); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__eventfd(unsigned int count) { -#if defined(__NR_eventfd) - return syscall(__NR_eventfd, count); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__eventfd2(unsigned int count, int flags) { -#if defined(__NR_eventfd2) - return syscall(__NR_eventfd2, count, flags); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__epoll_create(int size) { -#if defined(__NR_epoll_create) - return syscall(__NR_epoll_create, size); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__epoll_create1(int flags) { -#if defined(__NR_epoll_create1) - return syscall(__NR_epoll_create1, flags); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__epoll_ctl(int epfd, int op, int fd, struct uv__epoll_event* events) { -#if defined(__NR_epoll_ctl) - return syscall(__NR_epoll_ctl, epfd, op, fd, events); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__epoll_wait(int epfd, - struct uv__epoll_event* events, - int nevents, - int timeout) { -#if defined(__NR_epoll_wait) - return syscall(__NR_epoll_wait, epfd, events, nevents, timeout); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__epoll_pwait(int epfd, - struct uv__epoll_event* events, - int nevents, - int timeout, - uint64_t sigmask) { -#if defined(__NR_epoll_pwait) - return syscall(__NR_epoll_pwait, - epfd, - events, - nevents, - timeout, - &sigmask, - sizeof(sigmask)); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__inotify_init(void) { -#if defined(__NR_inotify_init) - return syscall(__NR_inotify_init); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__inotify_init1(int flags) { -#if defined(__NR_inotify_init1) - return syscall(__NR_inotify_init1, flags); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__inotify_add_watch(int fd, const char* path, uint32_t mask) { -#if defined(__NR_inotify_add_watch) - return syscall(__NR_inotify_add_watch, fd, path, mask); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__inotify_rm_watch(int fd, int32_t wd) { -#if defined(__NR_inotify_rm_watch) - return syscall(__NR_inotify_rm_watch, fd, wd); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__pipe2(int pipefd[2], int flags) { -#if defined(__NR_pipe2) - return syscall(__NR_pipe2, pipefd, flags); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__sendmmsg(int fd, - struct uv__mmsghdr* mmsg, - unsigned int vlen, - unsigned int flags) { -#if defined(__NR_sendmmsg) - return syscall(__NR_sendmmsg, fd, mmsg, vlen, flags); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__recvmmsg(int fd, - struct uv__mmsghdr* mmsg, - unsigned int vlen, - unsigned int flags, - struct timespec* timeout) { -#if defined(__NR_recvmmsg) - return syscall(__NR_recvmmsg, fd, mmsg, vlen, flags, timeout); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__utimesat(int dirfd, - const char* path, - const struct timespec times[2], - int flags) -{ -#if defined(__NR_utimensat) - return syscall(__NR_utimensat, dirfd, path, times, flags); -#else - return errno = ENOSYS, -1; -#endif -} - - -ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset) { -#if defined(__NR_preadv) - return syscall(__NR_preadv, fd, iov, iovcnt, offset); -#else - return errno = ENOSYS, -1; -#endif -} - - -ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset) { -#if defined(__NR_pwritev) - return syscall(__NR_pwritev, fd, iov, iovcnt, offset); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__dup3(int oldfd, int newfd, int flags) { -#if defined(__NR_dup3) - return syscall(__NR_dup3, oldfd, newfd, flags); -#else - return errno = ENOSYS, -1; -#endif -} diff --git a/libuv/src/unix/linux-syscalls.h b/libuv/src/unix/linux-syscalls.h deleted file mode 100644 index 6f249b7..0000000 --- a/libuv/src/unix/linux-syscalls.h +++ /dev/null @@ -1,158 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_LINUX_SYSCALL_H_ -#define UV_LINUX_SYSCALL_H_ - -#undef _GNU_SOURCE -#define _GNU_SOURCE - -#include -#include -#include -#include -#include - -#if defined(__alpha__) -# define UV__O_CLOEXEC 0x200000 -#elif defined(__hppa__) -# define UV__O_CLOEXEC 0x200000 -#elif defined(__sparc__) -# define UV__O_CLOEXEC 0x400000 -#else -# define UV__O_CLOEXEC 0x80000 -#endif - -#if defined(__alpha__) -# define UV__O_NONBLOCK 0x4 -#elif defined(__hppa__) -# define UV__O_NONBLOCK O_NONBLOCK -#elif defined(__mips__) -# define UV__O_NONBLOCK 0x80 -#elif defined(__sparc__) -# define UV__O_NONBLOCK 0x4000 -#else -# define UV__O_NONBLOCK 0x800 -#endif - -#define UV__EFD_CLOEXEC UV__O_CLOEXEC -#define UV__EFD_NONBLOCK UV__O_NONBLOCK - -#define UV__IN_CLOEXEC UV__O_CLOEXEC -#define UV__IN_NONBLOCK UV__O_NONBLOCK - -#define UV__SOCK_CLOEXEC UV__O_CLOEXEC -#if defined(SOCK_NONBLOCK) -# define UV__SOCK_NONBLOCK SOCK_NONBLOCK -#else -# define UV__SOCK_NONBLOCK UV__O_NONBLOCK -#endif - -/* epoll flags */ -#define UV__EPOLL_CLOEXEC UV__O_CLOEXEC -#define UV__EPOLL_CTL_ADD 1 -#define UV__EPOLL_CTL_DEL 2 -#define UV__EPOLL_CTL_MOD 3 - -#define UV__EPOLLIN 1 -#define UV__EPOLLOUT 4 -#define UV__EPOLLERR 8 -#define UV__EPOLLHUP 16 -#define UV__EPOLLONESHOT 0x40000000 -#define UV__EPOLLET 0x80000000 - -/* inotify flags */ -#define UV__IN_ACCESS 0x001 -#define UV__IN_MODIFY 0x002 -#define UV__IN_ATTRIB 0x004 -#define UV__IN_CLOSE_WRITE 0x008 -#define UV__IN_CLOSE_NOWRITE 0x010 -#define UV__IN_OPEN 0x020 -#define UV__IN_MOVED_FROM 0x040 -#define UV__IN_MOVED_TO 0x080 -#define UV__IN_CREATE 0x100 -#define UV__IN_DELETE 0x200 -#define UV__IN_DELETE_SELF 0x400 -#define UV__IN_MOVE_SELF 0x800 - -#if defined(__x86_64__) -struct uv__epoll_event { - uint32_t events; - uint64_t data; -} __attribute__((packed)); -#else -struct uv__epoll_event { - uint32_t events; - uint64_t data; -}; -#endif - -struct uv__inotify_event { - int32_t wd; - uint32_t mask; - uint32_t cookie; - uint32_t len; - /* char name[0]; */ -}; - -struct uv__mmsghdr { - struct msghdr msg_hdr; - unsigned int msg_len; -}; - -int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags); -int uv__eventfd(unsigned int count); -int uv__epoll_create(int size); -int uv__epoll_create1(int flags); -int uv__epoll_ctl(int epfd, int op, int fd, struct uv__epoll_event *ev); -int uv__epoll_wait(int epfd, - struct uv__epoll_event* events, - int nevents, - int timeout); -int uv__epoll_pwait(int epfd, - struct uv__epoll_event* events, - int nevents, - int timeout, - uint64_t sigmask); -int uv__eventfd2(unsigned int count, int flags); -int uv__inotify_init(void); -int uv__inotify_init1(int flags); -int uv__inotify_add_watch(int fd, const char* path, uint32_t mask); -int uv__inotify_rm_watch(int fd, int32_t wd); -int uv__pipe2(int pipefd[2], int flags); -int uv__recvmmsg(int fd, - struct uv__mmsghdr* mmsg, - unsigned int vlen, - unsigned int flags, - struct timespec* timeout); -int uv__sendmmsg(int fd, - struct uv__mmsghdr* mmsg, - unsigned int vlen, - unsigned int flags); -int uv__utimesat(int dirfd, - const char* path, - const struct timespec times[2], - int flags); -ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset); -ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset); -int uv__dup3(int oldfd, int newfd, int flags); - -#endif /* UV_LINUX_SYSCALL_H_ */ diff --git a/libuv/src/unix/loop-watcher.c b/libuv/src/unix/loop-watcher.c deleted file mode 100644 index dc25760..0000000 --- a/libuv/src/unix/loop-watcher.c +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#define UV_LOOP_WATCHER_DEFINE(name, type) \ - int uv_##name##_init(uv_loop_t* loop, uv_##name##_t* handle) { \ - uv__handle_init(loop, (uv_handle_t*)handle, UV_##type); \ - handle->name##_cb = NULL; \ - return 0; \ - } \ - \ - int uv_##name##_start(uv_##name##_t* handle, uv_##name##_cb cb) { \ - if (uv__is_active(handle)) return 0; \ - if (cb == NULL) return -EINVAL; \ - QUEUE_INSERT_HEAD(&handle->loop->name##_handles, &handle->queue); \ - handle->name##_cb = cb; \ - uv__handle_start(handle); \ - return 0; \ - } \ - \ - int uv_##name##_stop(uv_##name##_t* handle) { \ - if (!uv__is_active(handle)) return 0; \ - QUEUE_REMOVE(&handle->queue); \ - uv__handle_stop(handle); \ - return 0; \ - } \ - \ - void uv__run_##name(uv_loop_t* loop) { \ - uv_##name##_t* h; \ - QUEUE* q; \ - QUEUE_FOREACH(q, &loop->name##_handles) { \ - h = QUEUE_DATA(q, uv_##name##_t, queue); \ - h->name##_cb(h); \ - } \ - } \ - \ - void uv__##name##_close(uv_##name##_t* handle) { \ - uv_##name##_stop(handle); \ - } - -UV_LOOP_WATCHER_DEFINE(prepare, PREPARE) -UV_LOOP_WATCHER_DEFINE(check, CHECK) -UV_LOOP_WATCHER_DEFINE(idle, IDLE) diff --git a/libuv/src/unix/loop.c b/libuv/src/unix/loop.c deleted file mode 100644 index 7e167d0..0000000 --- a/libuv/src/unix/loop.c +++ /dev/null @@ -1,135 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "tree.h" -#include "internal.h" -#include "heap-inl.h" -#include -#include -#include - -int uv_loop_init(uv_loop_t* loop) { - int err; - - uv__signal_global_once_init(); - - memset(loop, 0, sizeof(*loop)); - heap_init((struct heap*) &loop->timer_heap); - QUEUE_INIT(&loop->wq); - QUEUE_INIT(&loop->active_reqs); - QUEUE_INIT(&loop->idle_handles); - QUEUE_INIT(&loop->async_handles); - QUEUE_INIT(&loop->check_handles); - QUEUE_INIT(&loop->prepare_handles); - QUEUE_INIT(&loop->handle_queue); - - loop->nfds = 0; - loop->watchers = NULL; - loop->nwatchers = 0; - QUEUE_INIT(&loop->pending_queue); - QUEUE_INIT(&loop->watcher_queue); - - loop->closing_handles = NULL; - uv__update_time(loop); - uv__async_init(&loop->async_watcher); - loop->signal_pipefd[0] = -1; - loop->signal_pipefd[1] = -1; - loop->backend_fd = -1; - loop->emfile_fd = -1; - - loop->timer_counter = 0; - loop->stop_flag = 0; - - err = uv__platform_loop_init(loop); - if (err) - return err; - - uv_signal_init(loop, &loop->child_watcher); - uv__handle_unref(&loop->child_watcher); - loop->child_watcher.flags |= UV__HANDLE_INTERNAL; - QUEUE_INIT(&loop->process_handles); - - if (uv_rwlock_init(&loop->cloexec_lock)) - abort(); - - if (uv_mutex_init(&loop->wq_mutex)) - abort(); - - if (uv_async_init(loop, &loop->wq_async, uv__work_done)) - abort(); - - uv__handle_unref(&loop->wq_async); - loop->wq_async.flags |= UV__HANDLE_INTERNAL; - - return 0; -} - - -void uv__loop_close(uv_loop_t* loop) { - uv__signal_loop_cleanup(loop); - uv__platform_loop_delete(loop); - uv__async_stop(loop, &loop->async_watcher); - - if (loop->emfile_fd != -1) { - uv__close(loop->emfile_fd); - loop->emfile_fd = -1; - } - - if (loop->backend_fd != -1) { - uv__close(loop->backend_fd); - loop->backend_fd = -1; - } - - uv_mutex_lock(&loop->wq_mutex); - assert(QUEUE_EMPTY(&loop->wq) && "thread pool work queue not empty!"); - assert(!uv__has_active_reqs(loop)); - uv_mutex_unlock(&loop->wq_mutex); - uv_mutex_destroy(&loop->wq_mutex); - - /* - * Note that all thread pool stuff is finished at this point and - * it is safe to just destroy rw lock - */ - uv_rwlock_destroy(&loop->cloexec_lock); - -#if 0 - assert(QUEUE_EMPTY(&loop->pending_queue)); - assert(QUEUE_EMPTY(&loop->watcher_queue)); - assert(loop->nfds == 0); -#endif - - free(loop->watchers); - loop->watchers = NULL; - loop->nwatchers = 0; -} - - -int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap) { - if (option != UV_LOOP_BLOCK_SIGNAL) - return UV_ENOSYS; - - if (va_arg(ap, int) != SIGPROF) - return UV_EINVAL; - - loop->flags |= UV_LOOP_BLOCK_SIGPROF; - return 0; -} diff --git a/libuv/src/unix/netbsd.c b/libuv/src/unix/netbsd.c deleted file mode 100644 index 9eb0679..0000000 --- a/libuv/src/unix/netbsd.c +++ /dev/null @@ -1,368 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#undef NANOSEC -#define NANOSEC ((uint64_t) 1e9) - -static char *process_title; - - -int uv__platform_loop_init(uv_loop_t* loop) { - return uv__kqueue_init(loop); -} - - -void uv__platform_loop_delete(uv_loop_t* loop) { -} - - -uint64_t uv__hrtime(uv_clocktype_t type) { - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec); -} - - -void uv_loadavg(double avg[3]) { - struct loadavg info; - size_t size = sizeof(info); - int which[] = {CTL_VM, VM_LOADAVG}; - - if (sysctl(which, 2, &info, &size, NULL, 0) == -1) return; - - avg[0] = (double) info.ldavg[0] / info.fscale; - avg[1] = (double) info.ldavg[1] / info.fscale; - avg[2] = (double) info.ldavg[2] / info.fscale; -} - - -int uv_exepath(char* buffer, size_t* size) { - int mib[4]; - size_t cb; - pid_t mypid; - - if (buffer == NULL || size == NULL || *size == 0) - return -EINVAL; - - mypid = getpid(); - mib[0] = CTL_KERN; - mib[1] = KERN_PROC_ARGS; - mib[2] = mypid; - mib[3] = KERN_PROC_ARGV; - - cb = *size; - if (sysctl(mib, 4, buffer, &cb, NULL, 0)) - return -errno; - *size = strlen(buffer); - - return 0; -} - - -uint64_t uv_get_free_memory(void) { - struct uvmexp info; - size_t size = sizeof(info); - int which[] = {CTL_VM, VM_UVMEXP}; - - if (sysctl(which, 2, &info, &size, NULL, 0)) - return -errno; - - return (uint64_t) info.free * sysconf(_SC_PAGESIZE); -} - - -uint64_t uv_get_total_memory(void) { -#if defined(HW_PHYSMEM64) - uint64_t info; - int which[] = {CTL_HW, HW_PHYSMEM64}; -#else - unsigned int info; - int which[] = {CTL_HW, HW_PHYSMEM}; -#endif - size_t size = sizeof(info); - - if (sysctl(which, 2, &info, &size, NULL, 0)) - return -errno; - - return (uint64_t) info; -} - - -char** uv_setup_args(int argc, char** argv) { - process_title = argc ? strdup(argv[0]) : NULL; - return argv; -} - - -int uv_set_process_title(const char* title) { - if (process_title) free(process_title); - - process_title = strdup(title); - setproctitle("%s", title); - - return 0; -} - - -int uv_get_process_title(char* buffer, size_t size) { - if (process_title) { - strncpy(buffer, process_title, size); - } else { - if (size > 0) { - buffer[0] = '\0'; - } - } - - return 0; -} - - -int uv_resident_set_memory(size_t* rss) { - kvm_t *kd = NULL; - struct kinfo_proc2 *kinfo = NULL; - pid_t pid; - int nprocs; - int max_size = sizeof(struct kinfo_proc2); - int page_size; - - page_size = getpagesize(); - pid = getpid(); - - kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, "kvm_open"); - - if (kd == NULL) goto error; - - kinfo = kvm_getproc2(kd, KERN_PROC_PID, pid, max_size, &nprocs); - if (kinfo == NULL) goto error; - - *rss = kinfo->p_vm_rssize * page_size; - - kvm_close(kd); - - return 0; - -error: - if (kd) kvm_close(kd); - return -EPERM; -} - - -int uv_uptime(double* uptime) { - time_t now; - struct timeval info; - size_t size = sizeof(info); - static int which[] = {CTL_KERN, KERN_BOOTTIME}; - - if (sysctl(which, 2, &info, &size, NULL, 0)) - return -errno; - - now = time(NULL); - - *uptime = (double)(now - info.tv_sec); - return 0; -} - - -int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { - unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK); - unsigned int multiplier = ((uint64_t)1000L / ticks); - unsigned int cur = 0; - uv_cpu_info_t* cpu_info; - u_int64_t* cp_times; - char model[512]; - u_int64_t cpuspeed; - int numcpus; - size_t size; - int i; - - size = sizeof(model); - if (sysctlbyname("machdep.cpu_brand", &model, &size, NULL, 0) && - sysctlbyname("hw.model", &model, &size, NULL, 0)) { - return -errno; - } - - size = sizeof(numcpus); - if (sysctlbyname("hw.ncpu", &numcpus, &size, NULL, 0)) - return -errno; - *count = numcpus; - - /* Only i386 and amd64 have machdep.tsc_freq */ - size = sizeof(cpuspeed); - if (sysctlbyname("machdep.tsc_freq", &cpuspeed, &size, NULL, 0)) - cpuspeed = 0; - - size = numcpus * CPUSTATES * sizeof(*cp_times); - cp_times = malloc(size); - if (cp_times == NULL) - return -ENOMEM; - - if (sysctlbyname("kern.cp_time", cp_times, &size, NULL, 0)) - return -errno; - - *cpu_infos = malloc(numcpus * sizeof(**cpu_infos)); - if (!(*cpu_infos)) { - free(cp_times); - free(*cpu_infos); - return -ENOMEM; - } - - for (i = 0; i < numcpus; i++) { - cpu_info = &(*cpu_infos)[i]; - cpu_info->cpu_times.user = (uint64_t)(cp_times[CP_USER+cur]) * multiplier; - cpu_info->cpu_times.nice = (uint64_t)(cp_times[CP_NICE+cur]) * multiplier; - cpu_info->cpu_times.sys = (uint64_t)(cp_times[CP_SYS+cur]) * multiplier; - cpu_info->cpu_times.idle = (uint64_t)(cp_times[CP_IDLE+cur]) * multiplier; - cpu_info->cpu_times.irq = (uint64_t)(cp_times[CP_INTR+cur]) * multiplier; - cpu_info->model = strdup(model); - cpu_info->speed = (int)(cpuspeed/(uint64_t) 1e6); - cur += CPUSTATES; - } - free(cp_times); - return 0; -} - - -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - int i; - - for (i = 0; i < count; i++) { - free(cpu_infos[i].model); - } - - free(cpu_infos); -} - - -int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { - struct ifaddrs *addrs, *ent; - uv_interface_address_t* address; - int i; - struct sockaddr_dl *sa_addr; - - if (getifaddrs(&addrs)) - return -errno; - - *count = 0; - - /* Count the number of interfaces */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family != PF_INET)) { - continue; - } - (*count)++; - } - - *addresses = malloc(*count * sizeof(**addresses)); - - if (!(*addresses)) - return -ENOMEM; - - address = *addresses; - - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) - continue; - - if (ent->ifa_addr == NULL) - continue; - - if (ent->ifa_addr->sa_family != PF_INET) - continue; - - address->name = strdup(ent->ifa_name); - - if (ent->ifa_addr->sa_family == AF_INET6) { - address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr); - } else { - address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr); - } - - if (ent->ifa_netmask->sa_family == AF_INET6) { - address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask); - } else { - address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask); - } - - address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK); - - address++; - } - - /* Fill in physical addresses for each interface */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family != AF_LINK)) { - continue; - } - - address = *addresses; - - for (i = 0; i < (*count); i++) { - if (strcmp(address->name, ent->ifa_name) == 0) { - sa_addr = (struct sockaddr_dl*)(ent->ifa_addr); - memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); - } - address++; - } - } - - freeifaddrs(addrs); - - return 0; -} - - -void uv_free_interface_addresses(uv_interface_address_t* addresses, int count) { - int i; - - for (i = 0; i < count; i++) { - free(addresses[i].name); - } - - free(addresses); -} diff --git a/libuv/src/unix/openbsd.c b/libuv/src/unix/openbsd.c deleted file mode 100644 index 859bc0c..0000000 --- a/libuv/src/unix/openbsd.c +++ /dev/null @@ -1,384 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#undef NANOSEC -#define NANOSEC ((uint64_t) 1e9) - - -static char *process_title; - - -int uv__platform_loop_init(uv_loop_t* loop) { - return uv__kqueue_init(loop); -} - - -void uv__platform_loop_delete(uv_loop_t* loop) { -} - - -uint64_t uv__hrtime(uv_clocktype_t type) { - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec); -} - - -void uv_loadavg(double avg[3]) { - struct loadavg info; - size_t size = sizeof(info); - int which[] = {CTL_VM, VM_LOADAVG}; - - if (sysctl(which, 2, &info, &size, NULL, 0) < 0) return; - - avg[0] = (double) info.ldavg[0] / info.fscale; - avg[1] = (double) info.ldavg[1] / info.fscale; - avg[2] = (double) info.ldavg[2] / info.fscale; -} - - -int uv_exepath(char* buffer, size_t* size) { - int mib[4]; - char **argsbuf = NULL; - char **argsbuf_tmp; - size_t argsbuf_size = 100U; - size_t exepath_size; - pid_t mypid; - int err; - - if (buffer == NULL || size == NULL || *size == 0) - return -EINVAL; - - mypid = getpid(); - for (;;) { - err = -ENOMEM; - argsbuf_tmp = realloc(argsbuf, argsbuf_size); - if (argsbuf_tmp == NULL) - goto out; - argsbuf = argsbuf_tmp; - mib[0] = CTL_KERN; - mib[1] = KERN_PROC_ARGS; - mib[2] = mypid; - mib[3] = KERN_PROC_ARGV; - if (sysctl(mib, 4, argsbuf, &argsbuf_size, NULL, 0) == 0) { - break; - } - if (errno != ENOMEM) { - err = -errno; - goto out; - } - argsbuf_size *= 2U; - } - - if (argsbuf[0] == NULL) { - err = -EINVAL; /* FIXME(bnoordhuis) More appropriate error. */ - goto out; - } - - *size -= 1; - exepath_size = strlen(argsbuf[0]); - if (*size > exepath_size) - *size = exepath_size; - - memcpy(buffer, argsbuf[0], *size); - buffer[*size] = '\0'; - err = 0; - -out: - free(argsbuf); - - return err; -} - - -uint64_t uv_get_free_memory(void) { - struct uvmexp info; - size_t size = sizeof(info); - int which[] = {CTL_VM, VM_UVMEXP}; - - if (sysctl(which, 2, &info, &size, NULL, 0)) - return -errno; - - return (uint64_t) info.free * sysconf(_SC_PAGESIZE); -} - - -uint64_t uv_get_total_memory(void) { - uint64_t info; - int which[] = {CTL_HW, HW_PHYSMEM64}; - size_t size = sizeof(info); - - if (sysctl(which, 2, &info, &size, NULL, 0)) - return -errno; - - return (uint64_t) info; -} - - -char** uv_setup_args(int argc, char** argv) { - process_title = argc ? strdup(argv[0]) : NULL; - return argv; -} - - -int uv_set_process_title(const char* title) { - if (process_title) free(process_title); - process_title = strdup(title); - setproctitle(title); - return 0; -} - - -int uv_get_process_title(char* buffer, size_t size) { - if (process_title) { - strncpy(buffer, process_title, size); - } else { - if (size > 0) { - buffer[0] = '\0'; - } - } - - return 0; -} - - -int uv_resident_set_memory(size_t* rss) { - struct kinfo_proc kinfo; - size_t page_size = getpagesize(); - size_t size = sizeof(struct kinfo_proc); - int mib[6]; - - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = getpid(); - mib[4] = sizeof(struct kinfo_proc); - mib[5] = 1; - - if (sysctl(mib, 6, &kinfo, &size, NULL, 0) < 0) - return -errno; - - *rss = kinfo.p_vm_rssize * page_size; - return 0; -} - - -int uv_uptime(double* uptime) { - time_t now; - struct timeval info; - size_t size = sizeof(info); - static int which[] = {CTL_KERN, KERN_BOOTTIME}; - - if (sysctl(which, 2, &info, &size, NULL, 0)) - return -errno; - - now = time(NULL); - - *uptime = (double)(now - info.tv_sec); - return 0; -} - - -int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { - unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK), - multiplier = ((uint64_t)1000L / ticks), cpuspeed; - uint64_t info[CPUSTATES]; - char model[512]; - int numcpus = 1; - int which[] = {CTL_HW,HW_MODEL,0}; - size_t size; - int i; - uv_cpu_info_t* cpu_info; - - size = sizeof(model); - if (sysctl(which, 2, &model, &size, NULL, 0)) - return -errno; - - which[1] = HW_NCPU; - size = sizeof(numcpus); - if (sysctl(which, 2, &numcpus, &size, NULL, 0)) - return -errno; - - *cpu_infos = malloc(numcpus * sizeof(**cpu_infos)); - if (!(*cpu_infos)) - return -ENOMEM; - - *count = numcpus; - - which[1] = HW_CPUSPEED; - size = sizeof(cpuspeed); - if (sysctl(which, 2, &cpuspeed, &size, NULL, 0)) { - SAVE_ERRNO(free(*cpu_infos)); - return -errno; - } - - size = sizeof(info); - which[0] = CTL_KERN; - which[1] = KERN_CPTIME2; - for (i = 0; i < numcpus; i++) { - which[2] = i; - size = sizeof(info); - if (sysctl(which, 3, &info, &size, NULL, 0)) { - SAVE_ERRNO(free(*cpu_infos)); - return -errno; - } - - cpu_info = &(*cpu_infos)[i]; - - cpu_info->cpu_times.user = (uint64_t)(info[CP_USER]) * multiplier; - cpu_info->cpu_times.nice = (uint64_t)(info[CP_NICE]) * multiplier; - cpu_info->cpu_times.sys = (uint64_t)(info[CP_SYS]) * multiplier; - cpu_info->cpu_times.idle = (uint64_t)(info[CP_IDLE]) * multiplier; - cpu_info->cpu_times.irq = (uint64_t)(info[CP_INTR]) * multiplier; - - cpu_info->model = strdup(model); - cpu_info->speed = cpuspeed; - } - - return 0; -} - - -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - int i; - - for (i = 0; i < count; i++) { - free(cpu_infos[i].model); - } - - free(cpu_infos); -} - - -int uv_interface_addresses(uv_interface_address_t** addresses, - int* count) { - struct ifaddrs *addrs, *ent; - uv_interface_address_t* address; - int i; - struct sockaddr_dl *sa_addr; - - if (getifaddrs(&addrs) != 0) - return -errno; - - *count = 0; - - /* Count the number of interfaces */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family != PF_INET)) { - continue; - } - (*count)++; - } - - *addresses = malloc(*count * sizeof(**addresses)); - - if (!(*addresses)) - return -ENOMEM; - - address = *addresses; - - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) - continue; - - if (ent->ifa_addr == NULL) - continue; - - if (ent->ifa_addr->sa_family != PF_INET) - continue; - - address->name = strdup(ent->ifa_name); - - if (ent->ifa_addr->sa_family == AF_INET6) { - address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr); - } else { - address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr); - } - - if (ent->ifa_netmask->sa_family == AF_INET6) { - address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask); - } else { - address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask); - } - - address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK); - - address++; - } - - /* Fill in physical addresses for each interface */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family != AF_LINK)) { - continue; - } - - address = *addresses; - - for (i = 0; i < (*count); i++) { - if (strcmp(address->name, ent->ifa_name) == 0) { - sa_addr = (struct sockaddr_dl*)(ent->ifa_addr); - memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); - } - address++; - } - } - - freeifaddrs(addrs); - - return 0; -} - - -void uv_free_interface_addresses(uv_interface_address_t* addresses, - int count) { - int i; - - for (i = 0; i < count; i++) { - free(addresses[i].name); - } - - free(addresses); -} diff --git a/libuv/src/unix/pipe.c b/libuv/src/unix/pipe.c deleted file mode 100644 index bc8b856..0000000 --- a/libuv/src/unix/pipe.c +++ /dev/null @@ -1,288 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include -#include -#include - - -int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) { - uv__stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE); - handle->shutdown_req = NULL; - handle->connect_req = NULL; - handle->pipe_fname = NULL; - handle->ipc = ipc; - return 0; -} - - -int uv_pipe_bind(uv_pipe_t* handle, const char* name) { - struct sockaddr_un saddr; - const char* pipe_fname; - int sockfd; - int err; - - pipe_fname = NULL; - sockfd = -1; - - /* Already bound? */ - if (uv__stream_fd(handle) >= 0) - return -EINVAL; - - /* Make a copy of the file name, it outlives this function's scope. */ - pipe_fname = strdup(name); - if (pipe_fname == NULL) - return -ENOMEM; - - /* We've got a copy, don't touch the original any more. */ - name = NULL; - - err = uv__socket(AF_UNIX, SOCK_STREAM, 0); - if (err < 0) - goto err_socket; - sockfd = err; - - memset(&saddr, 0, sizeof saddr); - strncpy(saddr.sun_path, pipe_fname, sizeof(saddr.sun_path) - 1); - saddr.sun_path[sizeof(saddr.sun_path) - 1] = '\0'; - saddr.sun_family = AF_UNIX; - - if (bind(sockfd, (struct sockaddr*)&saddr, sizeof saddr)) { - err = -errno; - /* Convert ENOENT to EACCES for compatibility with Windows. */ - if (err == -ENOENT) - err = -EACCES; - goto err_bind; - } - - /* Success. */ - handle->pipe_fname = pipe_fname; /* Is a strdup'ed copy. */ - handle->io_watcher.fd = sockfd; - return 0; - -err_bind: - uv__close(sockfd); - -err_socket: - free((void*)pipe_fname); - return err; -} - - -int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { - if (uv__stream_fd(handle) == -1) - return -EINVAL; - - if (listen(uv__stream_fd(handle), backlog)) - return -errno; - - handle->connection_cb = cb; - handle->io_watcher.cb = uv__server_io; - uv__io_start(handle->loop, &handle->io_watcher, UV__POLLIN); - return 0; -} - - -void uv__pipe_close(uv_pipe_t* handle) { - if (handle->pipe_fname) { - /* - * Unlink the file system entity before closing the file descriptor. - * Doing it the other way around introduces a race where our process - * unlinks a socket with the same name that's just been created by - * another thread or process. - */ - unlink(handle->pipe_fname); - free((void*)handle->pipe_fname); - handle->pipe_fname = NULL; - } - - uv__stream_close((uv_stream_t*)handle); -} - - -int uv_pipe_open(uv_pipe_t* handle, uv_file fd) { - int err; - - err = uv__nonblock(fd, 1); - if (err) - return err; - -#if defined(__APPLE__) - err = uv__stream_try_select((uv_stream_t*) handle, &fd); - if (err) - return err; -#endif /* defined(__APPLE__) */ - - return uv__stream_open((uv_stream_t*)handle, - fd, - UV_STREAM_READABLE | UV_STREAM_WRITABLE); -} - - -void uv_pipe_connect(uv_connect_t* req, - uv_pipe_t* handle, - const char* name, - uv_connect_cb cb) { - struct sockaddr_un saddr; - int new_sock; - int err; - int r; - - new_sock = (uv__stream_fd(handle) == -1); - - if (new_sock) { - err = uv__socket(AF_UNIX, SOCK_STREAM, 0); - if (err < 0) - goto out; - handle->io_watcher.fd = err; - } - - memset(&saddr, 0, sizeof saddr); - strncpy(saddr.sun_path, name, sizeof(saddr.sun_path) - 1); - saddr.sun_path[sizeof(saddr.sun_path) - 1] = '\0'; - saddr.sun_family = AF_UNIX; - - do { - r = connect(uv__stream_fd(handle), - (struct sockaddr*)&saddr, sizeof saddr); - } - while (r == -1 && errno == EINTR); - - if (r == -1 && errno != EINPROGRESS) { - err = -errno; - goto out; - } - - err = 0; - if (new_sock) { - err = uv__stream_open((uv_stream_t*)handle, - uv__stream_fd(handle), - UV_STREAM_READABLE | UV_STREAM_WRITABLE); - } - - if (err == 0) - uv__io_start(handle->loop, &handle->io_watcher, UV__POLLIN | UV__POLLOUT); - -out: - handle->delayed_error = err; - handle->connect_req = req; - - uv__req_init(handle->loop, req, UV_CONNECT); - req->handle = (uv_stream_t*)handle; - req->cb = cb; - QUEUE_INIT(&req->queue); - - /* Force callback to run on next tick in case of error. */ - if (err) - uv__io_feed(handle->loop, &handle->io_watcher); - - /* Mimic the Windows pipe implementation, always - * return 0 and let the callback handle errors. - */ -} - - -typedef int (*uv__peersockfunc)(int, struct sockaddr*, socklen_t*); - - -static int uv__pipe_getsockpeername(const uv_pipe_t* handle, - uv__peersockfunc func, - char* buffer, - size_t* size) { - struct sockaddr_un sa; - socklen_t addrlen; - int err; - - addrlen = sizeof(sa); - memset(&sa, 0, addrlen); - err = func(uv__stream_fd(handle), (struct sockaddr*) &sa, &addrlen); - if (err < 0) { - *size = 0; - return -errno; - } - -#if defined(__linux__) - if (sa.sun_path[0] == 0) - /* Linux abstract namespace */ - addrlen -= offsetof(struct sockaddr_un, sun_path); - else -#endif - addrlen = strlen(sa.sun_path); - - - if (addrlen > *size) { - *size = addrlen; - return UV_ENOBUFS; - } - - memcpy(buffer, sa.sun_path, addrlen); - *size = addrlen; - - return 0; -} - - -int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) { - return uv__pipe_getsockpeername(handle, getsockname, buffer, size); -} - - -int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) { - return uv__pipe_getsockpeername(handle, getpeername, buffer, size); -} - - -void uv_pipe_pending_instances(uv_pipe_t* handle, int count) { -} - - -int uv_pipe_pending_count(uv_pipe_t* handle) { - uv__stream_queued_fds_t* queued_fds; - - if (!handle->ipc) - return 0; - - if (handle->accepted_fd == -1) - return 0; - - if (handle->queued_fds == NULL) - return 1; - - queued_fds = handle->queued_fds; - return queued_fds->offset + 1; -} - - -uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) { - if (!handle->ipc) - return UV_UNKNOWN_HANDLE; - - if (handle->accepted_fd == -1) - return UV_UNKNOWN_HANDLE; - else - return uv__handle_type(handle->accepted_fd); -} diff --git a/libuv/src/unix/poll.c b/libuv/src/unix/poll.c deleted file mode 100644 index 37da3b9..0000000 --- a/libuv/src/unix/poll.c +++ /dev/null @@ -1,113 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include - - -static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { - uv_poll_t* handle; - int pevents; - - handle = container_of(w, uv_poll_t, io_watcher); - - if (events & UV__POLLERR) { - uv__io_stop(loop, w, UV__POLLIN | UV__POLLOUT); - uv__handle_stop(handle); - handle->poll_cb(handle, -EBADF, 0); - return; - } - - pevents = 0; - if (events & UV__POLLIN) - pevents |= UV_READABLE; - if (events & UV__POLLOUT) - pevents |= UV_WRITABLE; - - handle->poll_cb(handle, 0, pevents); -} - - -int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) { - int err; - - err = uv__nonblock(fd, 1); - if (err) - return err; - - uv__handle_init(loop, (uv_handle_t*) handle, UV_POLL); - uv__io_init(&handle->io_watcher, uv__poll_io, fd); - handle->poll_cb = NULL; - return 0; -} - - -int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle, - uv_os_sock_t socket) { - return uv_poll_init(loop, handle, socket); -} - - -static void uv__poll_stop(uv_poll_t* handle) { - uv__io_stop(handle->loop, &handle->io_watcher, UV__POLLIN | UV__POLLOUT); - uv__handle_stop(handle); -} - - -int uv_poll_stop(uv_poll_t* handle) { - assert(!(handle->flags & (UV_CLOSING | UV_CLOSED))); - uv__poll_stop(handle); - return 0; -} - - -int uv_poll_start(uv_poll_t* handle, int pevents, uv_poll_cb poll_cb) { - int events; - - assert((pevents & ~(UV_READABLE | UV_WRITABLE)) == 0); - assert(!(handle->flags & (UV_CLOSING | UV_CLOSED))); - - uv__poll_stop(handle); - - if (pevents == 0) - return 0; - - events = 0; - if (pevents & UV_READABLE) - events |= UV__POLLIN; - if (pevents & UV_WRITABLE) - events |= UV__POLLOUT; - - uv__io_start(handle->loop, &handle->io_watcher, events); - uv__handle_start(handle); - handle->poll_cb = poll_cb; - - return 0; -} - - -void uv__poll_close(uv_poll_t* handle) { - uv__poll_stop(handle); -} diff --git a/libuv/src/unix/process.c b/libuv/src/unix/process.c deleted file mode 100644 index be283b4..0000000 --- a/libuv/src/unix/process.c +++ /dev/null @@ -1,524 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#if defined(__APPLE__) && !TARGET_OS_IPHONE -# include -# define environ (*_NSGetEnviron()) -#else -extern char **environ; -#endif - -#ifdef __linux__ -# include -#endif - - -static void uv__chld(uv_signal_t* handle, int signum) { - uv_process_t* process; - uv_loop_t* loop; - int exit_status; - int term_signal; - int status; - pid_t pid; - QUEUE pending; - QUEUE* q; - QUEUE* h; - - assert(signum == SIGCHLD); - - QUEUE_INIT(&pending); - loop = handle->loop; - - h = &loop->process_handles; - q = QUEUE_HEAD(h); - while (q != h) { - process = QUEUE_DATA(q, uv_process_t, queue); - q = QUEUE_NEXT(q); - - do - pid = waitpid(process->pid, &status, WNOHANG); - while (pid == -1 && errno == EINTR); - - if (pid == 0) - continue; - - if (pid == -1) { - if (errno != ECHILD) - abort(); - continue; - } - - process->status = status; - QUEUE_REMOVE(&process->queue); - QUEUE_INSERT_TAIL(&pending, &process->queue); - } - - h = &pending; - q = QUEUE_HEAD(h); - while (q != h) { - process = QUEUE_DATA(q, uv_process_t, queue); - q = QUEUE_NEXT(q); - - QUEUE_REMOVE(&process->queue); - QUEUE_INIT(&process->queue); - uv__handle_stop(process); - - if (process->exit_cb == NULL) - continue; - - exit_status = 0; - if (WIFEXITED(process->status)) - exit_status = WEXITSTATUS(process->status); - - term_signal = 0; - if (WIFSIGNALED(process->status)) - term_signal = WTERMSIG(process->status); - - process->exit_cb(process, exit_status, term_signal); - } - assert(QUEUE_EMPTY(&pending)); -} - - -int uv__make_socketpair(int fds[2], int flags) { -#if defined(__linux__) - static int no_cloexec; - - if (no_cloexec) - goto skip; - - if (socketpair(AF_UNIX, SOCK_STREAM | UV__SOCK_CLOEXEC | flags, 0, fds) == 0) - return 0; - - /* Retry on EINVAL, it means SOCK_CLOEXEC is not supported. - * Anything else is a genuine error. - */ - if (errno != EINVAL) - return -errno; - - no_cloexec = 1; - -skip: -#endif - - if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds)) - return -errno; - - uv__cloexec(fds[0], 1); - uv__cloexec(fds[1], 1); - - if (flags & UV__F_NONBLOCK) { - uv__nonblock(fds[0], 1); - uv__nonblock(fds[1], 1); - } - - return 0; -} - - -int uv__make_pipe(int fds[2], int flags) { -#if defined(__linux__) - static int no_pipe2; - - if (no_pipe2) - goto skip; - - if (uv__pipe2(fds, flags | UV__O_CLOEXEC) == 0) - return 0; - - if (errno != ENOSYS) - return -errno; - - no_pipe2 = 1; - -skip: -#endif - - if (pipe(fds)) - return -errno; - - uv__cloexec(fds[0], 1); - uv__cloexec(fds[1], 1); - - if (flags & UV__F_NONBLOCK) { - uv__nonblock(fds[0], 1); - uv__nonblock(fds[1], 1); - } - - return 0; -} - - -/* - * Used for initializing stdio streams like options.stdin_stream. Returns - * zero on success. See also the cleanup section in uv_spawn(). - */ -static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) { - int mask; - int fd; - - mask = UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD | UV_INHERIT_STREAM; - - switch (container->flags & mask) { - case UV_IGNORE: - return 0; - - case UV_CREATE_PIPE: - assert(container->data.stream != NULL); - if (container->data.stream->type != UV_NAMED_PIPE) - return -EINVAL; - else - return uv__make_socketpair(fds, 0); - - case UV_INHERIT_FD: - case UV_INHERIT_STREAM: - if (container->flags & UV_INHERIT_FD) - fd = container->data.fd; - else - fd = uv__stream_fd(container->data.stream); - - if (fd == -1) - return -EINVAL; - - fds[1] = fd; - return 0; - - default: - assert(0 && "Unexpected flags"); - return -EINVAL; - } -} - - -static int uv__process_open_stream(uv_stdio_container_t* container, - int pipefds[2], - int writable) { - int flags; - - if (!(container->flags & UV_CREATE_PIPE) || pipefds[0] < 0) - return 0; - - if (uv__close(pipefds[1])) - if (errno != EINTR && errno != EINPROGRESS) - abort(); - - pipefds[1] = -1; - uv__nonblock(pipefds[0], 1); - - if (container->data.stream->type == UV_NAMED_PIPE && - ((uv_pipe_t*)container->data.stream)->ipc) - flags = UV_STREAM_READABLE | UV_STREAM_WRITABLE; - else if (writable) - flags = UV_STREAM_WRITABLE; - else - flags = UV_STREAM_READABLE; - - return uv__stream_open(container->data.stream, pipefds[0], flags); -} - - -static void uv__process_close_stream(uv_stdio_container_t* container) { - if (!(container->flags & UV_CREATE_PIPE)) return; - uv__stream_close((uv_stream_t*)container->data.stream); -} - - -static void uv__write_int(int fd, int val) { - ssize_t n; - - do - n = write(fd, &val, sizeof(val)); - while (n == -1 && errno == EINTR); - - if (n == -1 && errno == EPIPE) - return; /* parent process has quit */ - - assert(n == sizeof(val)); -} - - -static void uv__process_child_init(const uv_process_options_t* options, - int stdio_count, - int (*pipes)[2], - int error_fd) { - int close_fd; - int use_fd; - int fd; - - if (options->flags & UV_PROCESS_DETACHED) - setsid(); - - for (fd = 0; fd < stdio_count; fd++) { - close_fd = pipes[fd][0]; - use_fd = pipes[fd][1]; - - if (use_fd < 0) { - if (fd >= 3) - continue; - else { - /* redirect stdin, stdout and stderr to /dev/null even if UV_IGNORE is - * set - */ - use_fd = open("/dev/null", fd == 0 ? O_RDONLY : O_RDWR); - close_fd = use_fd; - - if (use_fd == -1) { - uv__write_int(error_fd, -errno); - _exit(127); - } - } - } - - if (fd == use_fd) - uv__cloexec(use_fd, 0); - else - dup2(use_fd, fd); - - if (fd <= 2) - uv__nonblock(fd, 0); - - if (close_fd >= stdio_count) - uv__close(close_fd); - } - - for (fd = 0; fd < stdio_count; fd++) { - use_fd = pipes[fd][1]; - - if (use_fd >= 0 && fd != use_fd) - close(use_fd); - } - - if (options->cwd != NULL && chdir(options->cwd)) { - uv__write_int(error_fd, -errno); - _exit(127); - } - - if (options->flags & (UV_PROCESS_SETUID | UV_PROCESS_SETGID)) { - /* When dropping privileges from root, the `setgroups` call will - * remove any extraneous groups. If we don't call this, then - * even though our uid has dropped, we may still have groups - * that enable us to do super-user things. This will fail if we - * aren't root, so don't bother checking the return value, this - * is just done as an optimistic privilege dropping function. - */ - SAVE_ERRNO(setgroups(0, NULL)); - } - - if ((options->flags & UV_PROCESS_SETGID) && setgid(options->gid)) { - uv__write_int(error_fd, -errno); - _exit(127); - } - - if ((options->flags & UV_PROCESS_SETUID) && setuid(options->uid)) { - uv__write_int(error_fd, -errno); - _exit(127); - } - - if (options->env != NULL) { - environ = options->env; - } - - execvp(options->file, options->args); - uv__write_int(error_fd, -errno); - _exit(127); -} - - -int uv_spawn(uv_loop_t* loop, - uv_process_t* process, - const uv_process_options_t* options) { - int signal_pipe[2] = { -1, -1 }; - int (*pipes)[2]; - int stdio_count; - ssize_t r; - pid_t pid; - int err; - int exec_errorno; - int i; - - assert(options->file != NULL); - assert(!(options->flags & ~(UV_PROCESS_DETACHED | - UV_PROCESS_SETGID | - UV_PROCESS_SETUID | - UV_PROCESS_WINDOWS_HIDE | - UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS))); - - uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS); - QUEUE_INIT(&process->queue); - - stdio_count = options->stdio_count; - if (stdio_count < 3) - stdio_count = 3; - - err = -ENOMEM; - pipes = malloc(stdio_count * sizeof(*pipes)); - if (pipes == NULL) - goto error; - - for (i = 0; i < stdio_count; i++) { - pipes[i][0] = -1; - pipes[i][1] = -1; - } - - for (i = 0; i < options->stdio_count; i++) { - err = uv__process_init_stdio(options->stdio + i, pipes[i]); - if (err) - goto error; - } - - /* This pipe is used by the parent to wait until - * the child has called `execve()`. We need this - * to avoid the following race condition: - * - * if ((pid = fork()) > 0) { - * kill(pid, SIGTERM); - * } - * else if (pid == 0) { - * execve("/bin/cat", argp, envp); - * } - * - * The parent sends a signal immediately after forking. - * Since the child may not have called `execve()` yet, - * there is no telling what process receives the signal, - * our fork or /bin/cat. - * - * To avoid ambiguity, we create a pipe with both ends - * marked close-on-exec. Then, after the call to `fork()`, - * the parent polls the read end until it EOFs or errors with EPIPE. - */ - err = uv__make_pipe(signal_pipe, 0); - if (err) - goto error; - - uv_signal_start(&loop->child_watcher, uv__chld, SIGCHLD); - - /* Acquire write lock to prevent opening new fds in worker threads */ - uv_rwlock_wrlock(&loop->cloexec_lock); - pid = fork(); - - if (pid == -1) { - err = -errno; - uv_rwlock_wrunlock(&loop->cloexec_lock); - uv__close(signal_pipe[0]); - uv__close(signal_pipe[1]); - goto error; - } - - if (pid == 0) { - uv__process_child_init(options, stdio_count, pipes, signal_pipe[1]); - abort(); - } - - /* Release lock in parent process */ - uv_rwlock_wrunlock(&loop->cloexec_lock); - uv__close(signal_pipe[1]); - - process->status = 0; - exec_errorno = 0; - do - r = read(signal_pipe[0], &exec_errorno, sizeof(exec_errorno)); - while (r == -1 && errno == EINTR); - - if (r == 0) - ; /* okay, EOF */ - else if (r == sizeof(exec_errorno)) - ; /* okay, read errorno */ - else if (r == -1 && errno == EPIPE) - ; /* okay, got EPIPE */ - else - abort(); - - uv__close(signal_pipe[0]); - - for (i = 0; i < options->stdio_count; i++) { - err = uv__process_open_stream(options->stdio + i, pipes[i], i == 0); - if (err == 0) - continue; - - while (i--) - uv__process_close_stream(options->stdio + i); - - goto error; - } - - /* Only activate this handle if exec() happened successfully */ - if (exec_errorno == 0) { - QUEUE_INSERT_TAIL(&loop->process_handles, &process->queue); - uv__handle_start(process); - } - - process->pid = pid; - process->exit_cb = options->exit_cb; - - free(pipes); - return exec_errorno; - -error: - if (pipes != NULL) { - for (i = 0; i < stdio_count; i++) { - if (i < options->stdio_count) - if (options->stdio[i].flags & (UV_INHERIT_FD | UV_INHERIT_STREAM)) - continue; - if (pipes[i][0] != -1) - close(pipes[i][0]); - if (pipes[i][1] != -1) - close(pipes[i][1]); - } - free(pipes); - } - - return err; -} - - -int uv_process_kill(uv_process_t* process, int signum) { - return uv_kill(process->pid, signum); -} - - -int uv_kill(int pid, int signum) { - if (kill(pid, signum)) - return -errno; - else - return 0; -} - - -void uv__process_close(uv_process_t* handle) { - QUEUE_REMOVE(&handle->queue); - uv__handle_stop(handle); - if (QUEUE_EMPTY(&handle->loop->process_handles)) - uv_signal_stop(&handle->loop->child_watcher); -} diff --git a/libuv/src/unix/proctitle.c b/libuv/src/unix/proctitle.c deleted file mode 100644 index 16b0523..0000000 --- a/libuv/src/unix/proctitle.c +++ /dev/null @@ -1,102 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include - -extern void uv__set_process_title(const char* title); - -static void* args_mem; - -static struct { - char* str; - size_t len; -} process_title; - - -char** uv_setup_args(int argc, char** argv) { - char** new_argv; - size_t size; - char* s; - int i; - - if (argc <= 0) - return argv; - - /* Calculate how much memory we need for the argv strings. */ - size = 0; - for (i = 0; i < argc; i++) - size += strlen(argv[i]) + 1; - - process_title.str = argv[0]; - process_title.len = argv[argc - 1] + strlen(argv[argc - 1]) - argv[0]; - assert(process_title.len + 1 == size); /* argv memory should be adjacent. */ - - /* Add space for the argv pointers. */ - size += (argc + 1) * sizeof(char*); - - new_argv = malloc(size); - if (new_argv == NULL) - return argv; - args_mem = new_argv; - - /* Copy over the strings and set up the pointer table. */ - s = (char*) &new_argv[argc + 1]; - for (i = 0; i < argc; i++) { - size = strlen(argv[i]) + 1; - memcpy(s, argv[i], size); - new_argv[i] = s; - s += size; - } - new_argv[i] = NULL; - - return new_argv; -} - - -int uv_set_process_title(const char* title) { - if (process_title.len == 0) - return 0; - - /* No need to terminate, byte after is always '\0'. */ - strncpy(process_title.str, title, process_title.len); - uv__set_process_title(title); - - return 0; -} - - -int uv_get_process_title(char* buffer, size_t size) { - if (process_title.len > 0) - strncpy(buffer, process_title.str, size); - else if (size > 0) - buffer[0] = '\0'; - - return 0; -} - - -UV_DESTRUCTOR(static void free_args_mem(void)) { - free(args_mem); /* Keep valgrind happy. */ - args_mem = NULL; -} diff --git a/libuv/src/unix/pthread-fixes.c b/libuv/src/unix/pthread-fixes.c deleted file mode 100644 index dc54f35..0000000 --- a/libuv/src/unix/pthread-fixes.c +++ /dev/null @@ -1,103 +0,0 @@ -/* Copyright (c) 2013, Sony Mobile Communications AB - * Copyright (c) 2012, Google Inc. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/* Android versions < 4.1 have a broken pthread_sigmask. - * Note that this block of code must come before any inclusion of - * pthread-fixes.h so that the real pthread_sigmask can be referenced. - * */ -#include -#include - -int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset) { - static int workaround; - - if (workaround) { - return sigprocmask(how, set, oset); - } else if (pthread_sigmask(how, set, oset)) { - if (errno == EINVAL && sigprocmask(how, set, oset) == 0) { - workaround = 1; - return 0; - } else { - return -1; - } - } else { - return 0; - } -} - -/*Android doesn't provide pthread_barrier_t for now.*/ -#ifndef PTHREAD_BARRIER_SERIAL_THREAD - -#include "pthread-fixes.h" - -int pthread_barrier_init(pthread_barrier_t* barrier, - const void* barrier_attr, - unsigned count) { - barrier->count = count; - pthread_mutex_init(&barrier->mutex, NULL); - pthread_cond_init(&barrier->cond, NULL); - return 0; -} - -int pthread_barrier_wait(pthread_barrier_t* barrier) { - /* Lock the mutex*/ - pthread_mutex_lock(&barrier->mutex); - /* Decrement the count. If this is the first thread to reach 0, wake up - waiters, unlock the mutex, then return PTHREAD_BARRIER_SERIAL_THREAD.*/ - if (--barrier->count == 0) { - /* First thread to reach the barrier */ - pthread_cond_broadcast(&barrier->cond); - pthread_mutex_unlock(&barrier->mutex); - return PTHREAD_BARRIER_SERIAL_THREAD; - } - /* Otherwise, wait for other threads until the count reaches 0, then - return 0 to indicate this is not the first thread.*/ - do { - pthread_cond_wait(&barrier->cond, &barrier->mutex); - } while (barrier->count > 0); - - pthread_mutex_unlock(&barrier->mutex); - return 0; -} - -int pthread_barrier_destroy(pthread_barrier_t *barrier) { - barrier->count = 0; - pthread_cond_destroy(&barrier->cond); - pthread_mutex_destroy(&barrier->mutex); - return 0; -} - -#endif /* defined(PTHREAD_BARRIER_SERIAL_THREAD) */ - -int pthread_yield(void) { - sched_yield(); - return 0; -} diff --git a/libuv/src/unix/signal.c b/libuv/src/unix/signal.c deleted file mode 100644 index 0b7a405..0000000 --- a/libuv/src/unix/signal.c +++ /dev/null @@ -1,465 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include -#include -#include - - -typedef struct { - uv_signal_t* handle; - int signum; -} uv__signal_msg_t; - -RB_HEAD(uv__signal_tree_s, uv_signal_s); - - -static int uv__signal_unlock(void); -static void uv__signal_event(uv_loop_t* loop, uv__io_t* w, unsigned int events); -static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2); -static void uv__signal_stop(uv_signal_t* handle); - - -static pthread_once_t uv__signal_global_init_guard = PTHREAD_ONCE_INIT; -static struct uv__signal_tree_s uv__signal_tree = - RB_INITIALIZER(uv__signal_tree); -static int uv__signal_lock_pipefd[2]; - - -RB_GENERATE_STATIC(uv__signal_tree_s, - uv_signal_s, tree_entry, - uv__signal_compare) - - -static void uv__signal_global_init(void) { - if (uv__make_pipe(uv__signal_lock_pipefd, 0)) - abort(); - - if (uv__signal_unlock()) - abort(); -} - - -void uv__signal_global_once_init(void) { - pthread_once(&uv__signal_global_init_guard, uv__signal_global_init); -} - - - -static int uv__signal_lock(void) { - int r; - char data; - - do { - r = read(uv__signal_lock_pipefd[0], &data, sizeof data); - } while (r < 0 && errno == EINTR); - - return (r < 0) ? -1 : 0; -} - - -static int uv__signal_unlock(void) { - int r; - char data = 42; - - do { - r = write(uv__signal_lock_pipefd[1], &data, sizeof data); - } while (r < 0 && errno == EINTR); - - return (r < 0) ? -1 : 0; -} - - -static void uv__signal_block_and_lock(sigset_t* saved_sigmask) { - sigset_t new_mask; - - if (sigfillset(&new_mask)) - abort(); - - if (pthread_sigmask(SIG_SETMASK, &new_mask, saved_sigmask)) - abort(); - - if (uv__signal_lock()) - abort(); -} - - -static void uv__signal_unlock_and_unblock(sigset_t* saved_sigmask) { - if (uv__signal_unlock()) - abort(); - - if (pthread_sigmask(SIG_SETMASK, saved_sigmask, NULL)) - abort(); -} - - -static uv_signal_t* uv__signal_first_handle(int signum) { - /* This function must be called with the signal lock held. */ - uv_signal_t lookup; - uv_signal_t* handle; - - lookup.signum = signum; - lookup.loop = NULL; - - handle = RB_NFIND(uv__signal_tree_s, &uv__signal_tree, &lookup); - - if (handle != NULL && handle->signum == signum) - return handle; - - return NULL; -} - - -static void uv__signal_handler(int signum) { - uv__signal_msg_t msg; - uv_signal_t* handle; - int saved_errno; - - saved_errno = errno; - memset(&msg, 0, sizeof msg); - - if (uv__signal_lock()) { - errno = saved_errno; - return; - } - - for (handle = uv__signal_first_handle(signum); - handle != NULL && handle->signum == signum; - handle = RB_NEXT(uv__signal_tree_s, &uv__signal_tree, handle)) { - int r; - - msg.signum = signum; - msg.handle = handle; - - /* write() should be atomic for small data chunks, so the entire message - * should be written at once. In theory the pipe could become full, in - * which case the user is out of luck. - */ - do { - r = write(handle->loop->signal_pipefd[1], &msg, sizeof msg); - } while (r == -1 && errno == EINTR); - - assert(r == sizeof msg || - (r == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))); - - if (r != -1) - handle->caught_signals++; - } - - uv__signal_unlock(); - errno = saved_errno; -} - - -static int uv__signal_register_handler(int signum) { - /* When this function is called, the signal lock must be held. */ - struct sigaction sa; - - /* XXX use a separate signal stack? */ - memset(&sa, 0, sizeof(sa)); - if (sigfillset(&sa.sa_mask)) - abort(); - sa.sa_handler = uv__signal_handler; - - /* XXX save old action so we can restore it later on? */ - if (sigaction(signum, &sa, NULL)) - return -errno; - - return 0; -} - - -static void uv__signal_unregister_handler(int signum) { - /* When this function is called, the signal lock must be held. */ - struct sigaction sa; - - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = SIG_DFL; - - /* sigaction can only fail with EINVAL or EFAULT; an attempt to deregister a - * signal implies that it was successfully registered earlier, so EINVAL - * should never happen. - */ - if (sigaction(signum, &sa, NULL)) - abort(); -} - - -static int uv__signal_loop_once_init(uv_loop_t* loop) { - int err; - - /* Return if already initialized. */ - if (loop->signal_pipefd[0] != -1) - return 0; - - err = uv__make_pipe(loop->signal_pipefd, UV__F_NONBLOCK); - if (err) - return err; - - uv__io_init(&loop->signal_io_watcher, - uv__signal_event, - loop->signal_pipefd[0]); - uv__io_start(loop, &loop->signal_io_watcher, UV__POLLIN); - - return 0; -} - - -void uv__signal_loop_cleanup(uv_loop_t* loop) { - QUEUE* q; - - /* Stop all the signal watchers that are still attached to this loop. This - * ensures that the (shared) signal tree doesn't contain any invalid entries - * entries, and that signal handlers are removed when appropriate. - */ - QUEUE_FOREACH(q, &loop->handle_queue) { - uv_handle_t* handle = QUEUE_DATA(q, uv_handle_t, handle_queue); - - if (handle->type == UV_SIGNAL) - uv__signal_stop((uv_signal_t*) handle); - } - - if (loop->signal_pipefd[0] != -1) { - uv__close(loop->signal_pipefd[0]); - loop->signal_pipefd[0] = -1; - } - - if (loop->signal_pipefd[1] != -1) { - uv__close(loop->signal_pipefd[1]); - loop->signal_pipefd[1] = -1; - } -} - - -int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle) { - int err; - - err = uv__signal_loop_once_init(loop); - if (err) - return err; - - uv__handle_init(loop, (uv_handle_t*) handle, UV_SIGNAL); - handle->signum = 0; - handle->caught_signals = 0; - handle->dispatched_signals = 0; - - return 0; -} - - -void uv__signal_close(uv_signal_t* handle) { - - uv__signal_stop(handle); - - /* If there are any caught signals "trapped" in the signal pipe, we can't - * call the close callback yet. Otherwise, add the handle to the finish_close - * queue. - */ - if (handle->caught_signals == handle->dispatched_signals) { - uv__make_close_pending((uv_handle_t*) handle); - } -} - - -int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) { - sigset_t saved_sigmask; - int err; - - assert(!(handle->flags & (UV_CLOSING | UV_CLOSED))); - - /* If the user supplies signum == 0, then return an error already. If the - * signum is otherwise invalid then uv__signal_register will find out - * eventually. - */ - if (signum == 0) - return -EINVAL; - - /* Short circuit: if the signal watcher is already watching {signum} don't - * go through the process of deregistering and registering the handler. - * Additionally, this avoids pending signals getting lost in the small time - * time frame that handle->signum == 0. - */ - if (signum == handle->signum) { - handle->signal_cb = signal_cb; - return 0; - } - - /* If the signal handler was already active, stop it first. */ - if (handle->signum != 0) { - uv__signal_stop(handle); - } - - uv__signal_block_and_lock(&saved_sigmask); - - /* If at this point there are no active signal watchers for this signum (in - * any of the loops), it's time to try and register a handler for it here. - */ - if (uv__signal_first_handle(signum) == NULL) { - err = uv__signal_register_handler(signum); - if (err) { - /* Registering the signal handler failed. Must be an invalid signal. */ - uv__signal_unlock_and_unblock(&saved_sigmask); - return err; - } - } - - handle->signum = signum; - RB_INSERT(uv__signal_tree_s, &uv__signal_tree, handle); - - uv__signal_unlock_and_unblock(&saved_sigmask); - - handle->signal_cb = signal_cb; - uv__handle_start(handle); - - return 0; -} - - -static void uv__signal_event(uv_loop_t* loop, - uv__io_t* w, - unsigned int events) { - uv__signal_msg_t* msg; - uv_signal_t* handle; - char buf[sizeof(uv__signal_msg_t) * 32]; - size_t bytes, end, i; - int r; - - bytes = 0; - end = 0; - - do { - r = read(loop->signal_pipefd[0], buf + bytes, sizeof(buf) - bytes); - - if (r == -1 && errno == EINTR) - continue; - - if (r == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) { - /* If there are bytes in the buffer already (which really is extremely - * unlikely if possible at all) we can't exit the function here. We'll - * spin until more bytes are read instead. - */ - if (bytes > 0) - continue; - - /* Otherwise, there was nothing there. */ - return; - } - - /* Other errors really should never happen. */ - if (r == -1) - abort(); - - bytes += r; - - /* `end` is rounded down to a multiple of sizeof(uv__signal_msg_t). */ - end = (bytes / sizeof(uv__signal_msg_t)) * sizeof(uv__signal_msg_t); - - for (i = 0; i < end; i += sizeof(uv__signal_msg_t)) { - msg = (uv__signal_msg_t*) (buf + i); - handle = msg->handle; - - if (msg->signum == handle->signum) { - assert(!(handle->flags & UV_CLOSING)); - handle->signal_cb(handle, handle->signum); - } - - handle->dispatched_signals++; - - /* If uv_close was called while there were caught signals that were not - * yet dispatched, the uv__finish_close was deferred. Make close pending - * now if this has happened. - */ - if ((handle->flags & UV_CLOSING) && - (handle->caught_signals == handle->dispatched_signals)) { - uv__make_close_pending((uv_handle_t*) handle); - } - } - - bytes -= end; - - /* If there are any "partial" messages left, move them to the start of the - * the buffer, and spin. This should not happen. - */ - if (bytes) { - memmove(buf, buf + end, bytes); - continue; - } - } while (end == sizeof buf); -} - - -static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) { - /* Compare signums first so all watchers with the same signnum end up - * adjacent. - */ - if (w1->signum < w2->signum) return -1; - if (w1->signum > w2->signum) return 1; - - /* Sort by loop pointer, so we can easily look up the first item after - * { .signum = x, .loop = NULL }. - */ - if (w1->loop < w2->loop) return -1; - if (w1->loop > w2->loop) return 1; - - if (w1 < w2) return -1; - if (w1 > w2) return 1; - - return 0; -} - - -int uv_signal_stop(uv_signal_t* handle) { - assert(!(handle->flags & (UV_CLOSING | UV_CLOSED))); - uv__signal_stop(handle); - return 0; -} - - -static void uv__signal_stop(uv_signal_t* handle) { - uv_signal_t* removed_handle; - sigset_t saved_sigmask; - - /* If the watcher wasn't started, this is a no-op. */ - if (handle->signum == 0) - return; - - uv__signal_block_and_lock(&saved_sigmask); - - removed_handle = RB_REMOVE(uv__signal_tree_s, &uv__signal_tree, handle); - assert(removed_handle == handle); - (void) removed_handle; - - /* Check if there are other active signal watchers observing this signal. If - * not, unregister the signal handler. - */ - if (uv__signal_first_handle(handle->signum) == NULL) - uv__signal_unregister_handler(handle->signum); - - uv__signal_unlock_and_unblock(&saved_sigmask); - - handle->signum = 0; - uv__handle_stop(handle); -} diff --git a/libuv/src/unix/spinlock.h b/libuv/src/unix/spinlock.h deleted file mode 100644 index a20c83c..0000000 --- a/libuv/src/unix/spinlock.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright (c) 2013, Ben Noordhuis - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef UV_SPINLOCK_H_ -#define UV_SPINLOCK_H_ - -#include "internal.h" /* ACCESS_ONCE, UV_UNUSED */ -#include "atomic-ops.h" - -#define UV_SPINLOCK_INITIALIZER { 0 } - -typedef struct { - int lock; -} uv_spinlock_t; - -UV_UNUSED(static void uv_spinlock_init(uv_spinlock_t* spinlock)); -UV_UNUSED(static void uv_spinlock_lock(uv_spinlock_t* spinlock)); -UV_UNUSED(static void uv_spinlock_unlock(uv_spinlock_t* spinlock)); -UV_UNUSED(static int uv_spinlock_trylock(uv_spinlock_t* spinlock)); - -UV_UNUSED(static void uv_spinlock_init(uv_spinlock_t* spinlock)) { - ACCESS_ONCE(int, spinlock->lock) = 0; -} - -UV_UNUSED(static void uv_spinlock_lock(uv_spinlock_t* spinlock)) { - while (!uv_spinlock_trylock(spinlock)) cpu_relax(); -} - -UV_UNUSED(static void uv_spinlock_unlock(uv_spinlock_t* spinlock)) { - ACCESS_ONCE(int, spinlock->lock) = 0; -} - -UV_UNUSED(static int uv_spinlock_trylock(uv_spinlock_t* spinlock)) { - /* TODO(bnoordhuis) Maybe change to a ticket lock to guarantee fair queueing. - * Not really critical until we have locks that are (frequently) contended - * for by several threads. - */ - return 0 == cmpxchgi(&spinlock->lock, 0, 1); -} - -#endif /* UV_SPINLOCK_H_ */ diff --git a/libuv/src/unix/stream.c b/libuv/src/unix/stream.c deleted file mode 100644 index d41a342..0000000 --- a/libuv/src/unix/stream.c +++ /dev/null @@ -1,1577 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include /* IOV_MAX */ - -#if defined(__APPLE__) -# include -# include -# include - -/* Forward declaration */ -typedef struct uv__stream_select_s uv__stream_select_t; - -struct uv__stream_select_s { - uv_stream_t* stream; - uv_thread_t thread; - uv_sem_t close_sem; - uv_sem_t async_sem; - uv_async_t async; - int events; - int fake_fd; - int int_fd; - int fd; - fd_set* sread; - size_t sread_sz; - fd_set* swrite; - size_t swrite_sz; -}; -#endif /* defined(__APPLE__) */ - -static void uv__stream_connect(uv_stream_t*); -static void uv__write(uv_stream_t* stream); -static void uv__read(uv_stream_t* stream); -static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events); -static void uv__write_callbacks(uv_stream_t* stream); -static size_t uv__write_req_size(uv_write_t* req); - - -void uv__stream_init(uv_loop_t* loop, - uv_stream_t* stream, - uv_handle_type type) { - int err; - - uv__handle_init(loop, (uv_handle_t*)stream, type); - stream->read_cb = NULL; - stream->alloc_cb = NULL; - stream->close_cb = NULL; - stream->connection_cb = NULL; - stream->connect_req = NULL; - stream->shutdown_req = NULL; - stream->accepted_fd = -1; - stream->queued_fds = NULL; - stream->delayed_error = 0; - QUEUE_INIT(&stream->write_queue); - QUEUE_INIT(&stream->write_completed_queue); - stream->write_queue_size = 0; - - if (loop->emfile_fd == -1) { - err = uv__open_cloexec("/", O_RDONLY); - if (err >= 0) - loop->emfile_fd = err; - } - -#if defined(__APPLE__) - stream->select = NULL; -#endif /* defined(__APPLE_) */ - - uv__io_init(&stream->io_watcher, uv__stream_io, -1); -} - - -static void uv__stream_osx_interrupt_select(uv_stream_t* stream) { -#if defined(__APPLE__) - /* Notify select() thread about state change */ - uv__stream_select_t* s; - int r; - - s = stream->select; - if (s == NULL) - return; - - /* Interrupt select() loop - * NOTE: fake_fd and int_fd are socketpair(), thus writing to one will - * emit read event on other side - */ - do - r = write(s->fake_fd, "x", 1); - while (r == -1 && errno == EINTR); - - assert(r == 1); -#else /* !defined(__APPLE__) */ - /* No-op on any other platform */ -#endif /* !defined(__APPLE__) */ -} - - -#if defined(__APPLE__) -static void uv__stream_osx_select(void* arg) { - uv_stream_t* stream; - uv__stream_select_t* s; - char buf[1024]; - int events; - int fd; - int r; - int max_fd; - - stream = arg; - s = stream->select; - fd = s->fd; - - if (fd > s->int_fd) - max_fd = fd; - else - max_fd = s->int_fd; - - while (1) { - /* Terminate on semaphore */ - if (uv_sem_trywait(&s->close_sem) == 0) - break; - - /* Watch fd using select(2) */ - memset(s->sread, 0, s->sread_sz); - memset(s->swrite, 0, s->swrite_sz); - - if (uv__io_active(&stream->io_watcher, UV__POLLIN)) - FD_SET(fd, s->sread); - if (uv__io_active(&stream->io_watcher, UV__POLLOUT)) - FD_SET(fd, s->swrite); - FD_SET(s->int_fd, s->sread); - - /* Wait indefinitely for fd events */ - r = select(max_fd + 1, s->sread, s->swrite, NULL, NULL); - if (r == -1) { - if (errno == EINTR) - continue; - - /* XXX: Possible?! */ - abort(); - } - - /* Ignore timeouts */ - if (r == 0) - continue; - - /* Empty socketpair's buffer in case of interruption */ - if (FD_ISSET(s->int_fd, s->sread)) - while (1) { - r = read(s->int_fd, buf, sizeof(buf)); - - if (r == sizeof(buf)) - continue; - - if (r != -1) - break; - - if (errno == EAGAIN || errno == EWOULDBLOCK) - break; - - if (errno == EINTR) - continue; - - abort(); - } - - /* Handle events */ - events = 0; - if (FD_ISSET(fd, s->sread)) - events |= UV__POLLIN; - if (FD_ISSET(fd, s->swrite)) - events |= UV__POLLOUT; - - assert(events != 0 || FD_ISSET(s->int_fd, s->sread)); - if (events != 0) { - ACCESS_ONCE(int, s->events) = events; - - uv_async_send(&s->async); - uv_sem_wait(&s->async_sem); - - /* Should be processed at this stage */ - assert((s->events == 0) || (stream->flags & UV_CLOSING)); - } - } -} - - -static void uv__stream_osx_select_cb(uv_async_t* handle) { - uv__stream_select_t* s; - uv_stream_t* stream; - int events; - - s = container_of(handle, uv__stream_select_t, async); - stream = s->stream; - - /* Get and reset stream's events */ - events = s->events; - ACCESS_ONCE(int, s->events) = 0; - uv_sem_post(&s->async_sem); - - assert(events != 0); - assert(events == (events & (UV__POLLIN | UV__POLLOUT))); - - /* Invoke callback on event-loop */ - if ((events & UV__POLLIN) && uv__io_active(&stream->io_watcher, UV__POLLIN)) - uv__stream_io(stream->loop, &stream->io_watcher, UV__POLLIN); - - if ((events & UV__POLLOUT) && uv__io_active(&stream->io_watcher, UV__POLLOUT)) - uv__stream_io(stream->loop, &stream->io_watcher, UV__POLLOUT); -} - - -static void uv__stream_osx_cb_close(uv_handle_t* async) { - uv__stream_select_t* s; - - s = container_of(async, uv__stream_select_t, async); - free(s); -} - - -int uv__stream_try_select(uv_stream_t* stream, int* fd) { - /* - * kqueue doesn't work with some files from /dev mount on osx. - * select(2) in separate thread for those fds - */ - - struct kevent filter[1]; - struct kevent events[1]; - struct timespec timeout; - uv__stream_select_t* s; - int fds[2]; - int err; - int ret; - int kq; - int old_fd; - int max_fd; - size_t sread_sz; - size_t swrite_sz; - - kq = kqueue(); - if (kq == -1) { - perror("(libuv) kqueue()"); - return -errno; - } - - EV_SET(&filter[0], *fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0); - - /* Use small timeout, because we only want to capture EINVALs */ - timeout.tv_sec = 0; - timeout.tv_nsec = 1; - - ret = kevent(kq, filter, 1, events, 1, &timeout); - uv__close(kq); - - if (ret == -1) - return -errno; - - if (ret == 0 || (events[0].flags & EV_ERROR) == 0 || events[0].data != EINVAL) - return 0; - - /* At this point we definitely know that this fd won't work with kqueue */ - - /* - * Create fds for io watcher and to interrupt the select() loop. - * NOTE: do it ahead of malloc below to allocate enough space for fd_sets - */ - if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds)) - return -errno; - - max_fd = *fd; - if (fds[1] > max_fd) - max_fd = fds[1]; - - sread_sz = (max_fd + NBBY) / NBBY; - swrite_sz = sread_sz; - - s = malloc(sizeof(*s) + sread_sz + swrite_sz); - if (s == NULL) { - err = -ENOMEM; - goto failed_malloc; - } - - s->events = 0; - s->fd = *fd; - s->sread = (fd_set*) ((char*) s + sizeof(*s)); - s->sread_sz = sread_sz; - s->swrite = (fd_set*) ((char*) s->sread + sread_sz); - s->swrite_sz = swrite_sz; - - err = uv_async_init(stream->loop, &s->async, uv__stream_osx_select_cb); - if (err) - goto failed_async_init; - - s->async.flags |= UV__HANDLE_INTERNAL; - uv__handle_unref(&s->async); - - err = uv_sem_init(&s->close_sem, 0); - if (err != 0) - goto failed_close_sem_init; - - err = uv_sem_init(&s->async_sem, 0); - if (err != 0) - goto failed_async_sem_init; - - s->fake_fd = fds[0]; - s->int_fd = fds[1]; - - old_fd = *fd; - s->stream = stream; - stream->select = s; - *fd = s->fake_fd; - - err = uv_thread_create(&s->thread, uv__stream_osx_select, stream); - if (err != 0) - goto failed_thread_create; - - return 0; - -failed_thread_create: - s->stream = NULL; - stream->select = NULL; - *fd = old_fd; - - uv_sem_destroy(&s->async_sem); - -failed_async_sem_init: - uv_sem_destroy(&s->close_sem); - -failed_close_sem_init: - uv__close(fds[0]); - uv__close(fds[1]); - uv_close((uv_handle_t*) &s->async, uv__stream_osx_cb_close); - return err; - -failed_async_init: - free(s); - -failed_malloc: - uv__close(fds[0]); - uv__close(fds[1]); - - return err; -} -#endif /* defined(__APPLE__) */ - - -int uv__stream_open(uv_stream_t* stream, int fd, int flags) { - assert(fd >= 0); - stream->flags |= flags; - - if (stream->type == UV_TCP) { - if ((stream->flags & UV_TCP_NODELAY) && uv__tcp_nodelay(fd, 1)) - return -errno; - - /* TODO Use delay the user passed in. */ - if ((stream->flags & UV_TCP_KEEPALIVE) && uv__tcp_keepalive(fd, 1, 60)) - return -errno; - } - - stream->io_watcher.fd = fd; - - return 0; -} - - -void uv__stream_flush_write_queue(uv_stream_t* stream, int error) { - uv_write_t* req; - QUEUE* q; - while (!QUEUE_EMPTY(&stream->write_queue)) { - q = QUEUE_HEAD(&stream->write_queue); - QUEUE_REMOVE(q); - - req = QUEUE_DATA(q, uv_write_t, queue); - req->error = error; - - QUEUE_INSERT_TAIL(&stream->write_completed_queue, &req->queue); - } -} - - -void uv__stream_destroy(uv_stream_t* stream) { - assert(!uv__io_active(&stream->io_watcher, UV__POLLIN | UV__POLLOUT)); - assert(stream->flags & UV_CLOSED); - - if (stream->connect_req) { - uv__req_unregister(stream->loop, stream->connect_req); - stream->connect_req->cb(stream->connect_req, -ECANCELED); - stream->connect_req = NULL; - } - - uv__stream_flush_write_queue(stream, -ECANCELED); - uv__write_callbacks(stream); - - if (stream->shutdown_req) { - /* The ECANCELED error code is a lie, the shutdown(2) syscall is a - * fait accompli at this point. Maybe we should revisit this in v0.11. - * A possible reason for leaving it unchanged is that it informs the - * callee that the handle has been destroyed. - */ - uv__req_unregister(stream->loop, stream->shutdown_req); - stream->shutdown_req->cb(stream->shutdown_req, -ECANCELED); - stream->shutdown_req = NULL; - } - - assert(stream->write_queue_size == 0); -} - - -/* Implements a best effort approach to mitigating accept() EMFILE errors. - * We have a spare file descriptor stashed away that we close to get below - * the EMFILE limit. Next, we accept all pending connections and close them - * immediately to signal the clients that we're overloaded - and we are, but - * we still keep on trucking. - * - * There is one caveat: it's not reliable in a multi-threaded environment. - * The file descriptor limit is per process. Our party trick fails if another - * thread opens a file or creates a socket in the time window between us - * calling close() and accept(). - */ -static int uv__emfile_trick(uv_loop_t* loop, int accept_fd) { - int err; - int emfile_fd; - - if (loop->emfile_fd == -1) - return -EMFILE; - - uv__close(loop->emfile_fd); - loop->emfile_fd = -1; - - do { - err = uv__accept(accept_fd); - if (err >= 0) - uv__close(err); - } while (err >= 0 || err == -EINTR); - - emfile_fd = uv__open_cloexec("/", O_RDONLY); - if (emfile_fd >= 0) - loop->emfile_fd = emfile_fd; - - return err; -} - - -#if defined(UV_HAVE_KQUEUE) -# define UV_DEC_BACKLOG(w) w->rcount--; -#else -# define UV_DEC_BACKLOG(w) /* no-op */ -#endif /* defined(UV_HAVE_KQUEUE) */ - - -void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { - uv_stream_t* stream; - int err; - - stream = container_of(w, uv_stream_t, io_watcher); - assert(events == UV__POLLIN); - assert(stream->accepted_fd == -1); - assert(!(stream->flags & UV_CLOSING)); - - uv__io_start(stream->loop, &stream->io_watcher, UV__POLLIN); - - /* connection_cb can close the server socket while we're - * in the loop so check it on each iteration. - */ - while (uv__stream_fd(stream) != -1) { - assert(stream->accepted_fd == -1); - -#if defined(UV_HAVE_KQUEUE) - if (w->rcount <= 0) - return; -#endif /* defined(UV_HAVE_KQUEUE) */ - - err = uv__accept(uv__stream_fd(stream)); - if (err < 0) { - if (err == -EAGAIN || err == -EWOULDBLOCK) - return; /* Not an error. */ - - if (err == -ECONNABORTED) - continue; /* Ignore. Nothing we can do about that. */ - - if (err == -EMFILE || err == -ENFILE) { - err = uv__emfile_trick(loop, uv__stream_fd(stream)); - if (err == -EAGAIN || err == -EWOULDBLOCK) - break; - } - - stream->connection_cb(stream, err); - continue; - } - - UV_DEC_BACKLOG(w) - stream->accepted_fd = err; - stream->connection_cb(stream, 0); - - if (stream->accepted_fd != -1) { - /* The user hasn't yet accepted called uv_accept() */ - uv__io_stop(loop, &stream->io_watcher, UV__POLLIN); - return; - } - - if (stream->type == UV_TCP && (stream->flags & UV_TCP_SINGLE_ACCEPT)) { - /* Give other processes a chance to accept connections. */ - struct timespec timeout = { 0, 1 }; - nanosleep(&timeout, NULL); - } - } -} - - -#undef UV_DEC_BACKLOG - - -int uv_accept(uv_stream_t* server, uv_stream_t* client) { - int err; - - /* TODO document this */ - assert(server->loop == client->loop); - - if (server->accepted_fd == -1) - return -EAGAIN; - - switch (client->type) { - case UV_NAMED_PIPE: - case UV_TCP: - err = uv__stream_open(client, - server->accepted_fd, - UV_STREAM_READABLE | UV_STREAM_WRITABLE); - if (err) { - /* TODO handle error */ - uv__close(server->accepted_fd); - goto done; - } - break; - - case UV_UDP: - err = uv_udp_open((uv_udp_t*) client, server->accepted_fd); - if (err) { - uv__close(server->accepted_fd); - goto done; - } - break; - - default: - return -EINVAL; - } - -done: - /* Process queued fds */ - if (server->queued_fds != NULL) { - uv__stream_queued_fds_t* queued_fds; - - queued_fds = server->queued_fds; - - /* Read first */ - server->accepted_fd = queued_fds->fds[0]; - - /* All read, free */ - assert(queued_fds->offset > 0); - if (--queued_fds->offset == 0) { - free(queued_fds); - server->queued_fds = NULL; - } else { - /* Shift rest */ - memmove(queued_fds->fds, - queued_fds->fds + 1, - queued_fds->offset * sizeof(*queued_fds->fds)); - } - } else { - server->accepted_fd = -1; - if (err == 0) - uv__io_start(server->loop, &server->io_watcher, UV__POLLIN); - } - return err; -} - - -int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) { - int err; - - switch (stream->type) { - case UV_TCP: - err = uv_tcp_listen((uv_tcp_t*)stream, backlog, cb); - break; - - case UV_NAMED_PIPE: - err = uv_pipe_listen((uv_pipe_t*)stream, backlog, cb); - break; - - default: - err = -EINVAL; - } - - if (err == 0) - uv__handle_start(stream); - - return err; -} - - -static void uv__drain(uv_stream_t* stream) { - uv_shutdown_t* req; - int err; - - assert(QUEUE_EMPTY(&stream->write_queue)); - uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLOUT); - uv__stream_osx_interrupt_select(stream); - - /* Shutdown? */ - if ((stream->flags & UV_STREAM_SHUTTING) && - !(stream->flags & UV_CLOSING) && - !(stream->flags & UV_STREAM_SHUT)) { - assert(stream->shutdown_req); - - req = stream->shutdown_req; - stream->shutdown_req = NULL; - stream->flags &= ~UV_STREAM_SHUTTING; - uv__req_unregister(stream->loop, req); - - err = 0; - if (shutdown(uv__stream_fd(stream), SHUT_WR)) - err = -errno; - - if (err == 0) - stream->flags |= UV_STREAM_SHUT; - - if (req->cb != NULL) - req->cb(req, err); - } -} - - -static size_t uv__write_req_size(uv_write_t* req) { - size_t size; - - assert(req->bufs != NULL); - size = uv__count_bufs(req->bufs + req->write_index, - req->nbufs - req->write_index); - assert(req->handle->write_queue_size >= size); - - return size; -} - - -static void uv__write_req_finish(uv_write_t* req) { - uv_stream_t* stream = req->handle; - - /* Pop the req off tcp->write_queue. */ - QUEUE_REMOVE(&req->queue); - - /* Only free when there was no error. On error, we touch up write_queue_size - * right before making the callback. The reason we don't do that right away - * is that a write_queue_size > 0 is our only way to signal to the user that - * they should stop writing - which they should if we got an error. Something - * to revisit in future revisions of the libuv API. - */ - if (req->error == 0) { - if (req->bufs != req->bufsml) - free(req->bufs); - req->bufs = NULL; - } - - /* Add it to the write_completed_queue where it will have its - * callback called in the near future. - */ - QUEUE_INSERT_TAIL(&stream->write_completed_queue, &req->queue); - uv__io_feed(stream->loop, &stream->io_watcher); -} - - -static int uv__handle_fd(uv_handle_t* handle) { - switch (handle->type) { - case UV_NAMED_PIPE: - case UV_TCP: - return ((uv_stream_t*) handle)->io_watcher.fd; - - case UV_UDP: - return ((uv_udp_t*) handle)->io_watcher.fd; - - default: - return -1; - } -} - -static int uv__getiovmax() { -#if defined(IOV_MAX) - return IOV_MAX; -#elif defined(_SC_IOV_MAX) - static int iovmax = -1; - if (iovmax == -1) - iovmax = sysconf(_SC_IOV_MAX); - return iovmax; -#else - return 1024; -#endif -} - -static void uv__write(uv_stream_t* stream) { - struct iovec* iov; - QUEUE* q; - uv_write_t* req; - int iovmax; - int iovcnt; - ssize_t n; - -start: - - assert(uv__stream_fd(stream) >= 0); - - if (QUEUE_EMPTY(&stream->write_queue)) - return; - - q = QUEUE_HEAD(&stream->write_queue); - req = QUEUE_DATA(q, uv_write_t, queue); - assert(req->handle == stream); - - /* - * Cast to iovec. We had to have our own uv_buf_t instead of iovec - * because Windows's WSABUF is not an iovec. - */ - assert(sizeof(uv_buf_t) == sizeof(struct iovec)); - iov = (struct iovec*) &(req->bufs[req->write_index]); - iovcnt = req->nbufs - req->write_index; - - iovmax = uv__getiovmax(); - - /* Limit iov count to avoid EINVALs from writev() */ - if (iovcnt > iovmax) - iovcnt = iovmax; - - /* - * Now do the actual writev. Note that we've been updating the pointers - * inside the iov each time we write. So there is no need to offset it. - */ - - if (req->send_handle) { - struct msghdr msg; - char scratch[64]; - struct cmsghdr *cmsg; - int fd_to_send = uv__handle_fd((uv_handle_t*) req->send_handle); - - assert(fd_to_send >= 0); - - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = iov; - msg.msg_iovlen = iovcnt; - msg.msg_flags = 0; - - msg.msg_control = (void*) scratch; - msg.msg_controllen = CMSG_SPACE(sizeof(fd_to_send)); - - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(sizeof(fd_to_send)); - - /* silence aliasing warning */ - { - void* pv = CMSG_DATA(cmsg); - int* pi = pv; - *pi = fd_to_send; - } - - do { - n = sendmsg(uv__stream_fd(stream), &msg, 0); - } - while (n == -1 && errno == EINTR); - } else { - do { - if (iovcnt == 1) { - n = write(uv__stream_fd(stream), iov[0].iov_base, iov[0].iov_len); - } else { - n = writev(uv__stream_fd(stream), iov, iovcnt); - } - } - while (n == -1 && errno == EINTR); - } - - if (n < 0) { - if (errno != EAGAIN && errno != EWOULDBLOCK) { - /* Error */ - req->error = -errno; - uv__write_req_finish(req); - uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLOUT); - if (!uv__io_active(&stream->io_watcher, UV__POLLIN)) - uv__handle_stop(stream); - uv__stream_osx_interrupt_select(stream); - return; - } else if (stream->flags & UV_STREAM_BLOCKING) { - /* If this is a blocking stream, try again. */ - goto start; - } - } else { - /* Successful write */ - - while (n >= 0) { - uv_buf_t* buf = &(req->bufs[req->write_index]); - size_t len = buf->len; - - assert(req->write_index < req->nbufs); - - if ((size_t)n < len) { - buf->base += n; - buf->len -= n; - stream->write_queue_size -= n; - n = 0; - - /* There is more to write. */ - if (stream->flags & UV_STREAM_BLOCKING) { - /* - * If we're blocking then we should not be enabling the write - * watcher - instead we need to try again. - */ - goto start; - } else { - /* Break loop and ensure the watcher is pending. */ - break; - } - - } else { - /* Finished writing the buf at index req->write_index. */ - req->write_index++; - - assert((size_t)n >= len); - n -= len; - - assert(stream->write_queue_size >= len); - stream->write_queue_size -= len; - - if (req->write_index == req->nbufs) { - /* Then we're done! */ - assert(n == 0); - uv__write_req_finish(req); - /* TODO: start trying to write the next request. */ - return; - } - } - } - } - - /* Either we've counted n down to zero or we've got EAGAIN. */ - assert(n == 0 || n == -1); - - /* Only non-blocking streams should use the write_watcher. */ - assert(!(stream->flags & UV_STREAM_BLOCKING)); - - /* We're not done. */ - uv__io_start(stream->loop, &stream->io_watcher, UV__POLLOUT); - - /* Notify select() thread about state change */ - uv__stream_osx_interrupt_select(stream); -} - - -static void uv__write_callbacks(uv_stream_t* stream) { - uv_write_t* req; - QUEUE* q; - - while (!QUEUE_EMPTY(&stream->write_completed_queue)) { - /* Pop a req off write_completed_queue. */ - q = QUEUE_HEAD(&stream->write_completed_queue); - req = QUEUE_DATA(q, uv_write_t, queue); - QUEUE_REMOVE(q); - uv__req_unregister(stream->loop, req); - - if (req->bufs != NULL) { - stream->write_queue_size -= uv__write_req_size(req); - if (req->bufs != req->bufsml) - free(req->bufs); - req->bufs = NULL; - } - - /* NOTE: call callback AFTER freeing the request data. */ - if (req->cb) - req->cb(req, req->error); - } - - assert(QUEUE_EMPTY(&stream->write_completed_queue)); -} - - -uv_handle_type uv__handle_type(int fd) { - struct sockaddr_storage ss; - socklen_t len; - int type; - - memset(&ss, 0, sizeof(ss)); - len = sizeof(ss); - - if (getsockname(fd, (struct sockaddr*)&ss, &len)) - return UV_UNKNOWN_HANDLE; - - len = sizeof type; - - if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len)) - return UV_UNKNOWN_HANDLE; - - if (type == SOCK_STREAM) { - switch (ss.ss_family) { - case AF_UNIX: - return UV_NAMED_PIPE; - case AF_INET: - case AF_INET6: - return UV_TCP; - } - } - - if (type == SOCK_DGRAM && - (ss.ss_family == AF_INET || ss.ss_family == AF_INET6)) - return UV_UDP; - - return UV_UNKNOWN_HANDLE; -} - - -static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) { - stream->flags |= UV_STREAM_READ_EOF; - uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLIN); - if (!uv__io_active(&stream->io_watcher, UV__POLLOUT)) - uv__handle_stop(stream); - uv__stream_osx_interrupt_select(stream); - stream->read_cb(stream, UV_EOF, buf); - stream->flags &= ~UV_STREAM_READING; -} - - -static int uv__stream_queue_fd(uv_stream_t* stream, int fd) { - uv__stream_queued_fds_t* queued_fds; - unsigned int queue_size; - - queued_fds = stream->queued_fds; - if (queued_fds == NULL) { - queue_size = 8; - queued_fds = malloc((queue_size - 1) * sizeof(*queued_fds->fds) + - sizeof(*queued_fds)); - if (queued_fds == NULL) - return -ENOMEM; - queued_fds->size = queue_size; - queued_fds->offset = 0; - stream->queued_fds = queued_fds; - - /* Grow */ - } else if (queued_fds->size == queued_fds->offset) { - queue_size = queued_fds->size + 8; - queued_fds = realloc(queued_fds, - (queue_size - 1) * sizeof(*queued_fds->fds) + - sizeof(*queued_fds)); - - /* - * Allocation failure, report back. - * NOTE: if it is fatal - sockets will be closed in uv__stream_close - */ - if (queued_fds == NULL) - return -ENOMEM; - queued_fds->size = queue_size; - stream->queued_fds = queued_fds; - } - - /* Put fd in a queue */ - queued_fds->fds[queued_fds->offset++] = fd; - - return 0; -} - - -#define UV__CMSG_FD_COUNT 64 -#define UV__CMSG_FD_SIZE (UV__CMSG_FD_COUNT * sizeof(int)) - - -static int uv__stream_recv_cmsg(uv_stream_t* stream, struct msghdr* msg) { - struct cmsghdr* cmsg; - - for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg)) { - char* start; - char* end; - int err; - void* pv; - int* pi; - unsigned int i; - unsigned int count; - - if (cmsg->cmsg_type != SCM_RIGHTS) { - fprintf(stderr, "ignoring non-SCM_RIGHTS ancillary data: %d\n", - cmsg->cmsg_type); - continue; - } - - /* silence aliasing warning */ - pv = CMSG_DATA(cmsg); - pi = pv; - - /* Count available fds */ - start = (char*) cmsg; - end = (char*) cmsg + cmsg->cmsg_len; - count = 0; - while (start + CMSG_LEN(count * sizeof(*pi)) < end) - count++; - assert(start + CMSG_LEN(count * sizeof(*pi)) == end); - - for (i = 0; i < count; i++) { - /* Already has accepted fd, queue now */ - if (stream->accepted_fd != -1) { - err = uv__stream_queue_fd(stream, pi[i]); - if (err != 0) { - /* Close rest */ - for (; i < count; i++) - uv__close(pi[i]); - return err; - } - } else { - stream->accepted_fd = pi[i]; - } - } - } - - return 0; -} - - -static void uv__read(uv_stream_t* stream) { - uv_buf_t buf; - ssize_t nread; - struct msghdr msg; - char cmsg_space[CMSG_SPACE(UV__CMSG_FD_SIZE)]; - int count; - int err; - int is_ipc; - - stream->flags &= ~UV_STREAM_READ_PARTIAL; - - /* Prevent loop starvation when the data comes in as fast as (or faster than) - * we can read it. XXX Need to rearm fd if we switch to edge-triggered I/O. - */ - count = 32; - - is_ipc = stream->type == UV_NAMED_PIPE && ((uv_pipe_t*) stream)->ipc; - - /* XXX: Maybe instead of having UV_STREAM_READING we just test if - * tcp->read_cb is NULL or not? - */ - while (stream->read_cb - && (stream->flags & UV_STREAM_READING) - && (count-- > 0)) { - assert(stream->alloc_cb != NULL); - - stream->alloc_cb((uv_handle_t*)stream, 64 * 1024, &buf); - if (buf.len == 0) { - /* User indicates it can't or won't handle the read. */ - stream->read_cb(stream, UV_ENOBUFS, &buf); - return; - } - - assert(buf.base != NULL); - assert(uv__stream_fd(stream) >= 0); - - if (!is_ipc) { - do { - nread = read(uv__stream_fd(stream), buf.base, buf.len); - } - while (nread < 0 && errno == EINTR); - } else { - /* ipc uses recvmsg */ - msg.msg_flags = 0; - msg.msg_iov = (struct iovec*) &buf; - msg.msg_iovlen = 1; - msg.msg_name = NULL; - msg.msg_namelen = 0; - /* Set up to receive a descriptor even if one isn't in the message */ - msg.msg_controllen = sizeof(cmsg_space); - msg.msg_control = cmsg_space; - - do { - nread = uv__recvmsg(uv__stream_fd(stream), &msg, 0); - } - while (nread < 0 && errno == EINTR); - } - - if (nread < 0) { - /* Error */ - if (errno == EAGAIN || errno == EWOULDBLOCK) { - /* Wait for the next one. */ - if (stream->flags & UV_STREAM_READING) { - uv__io_start(stream->loop, &stream->io_watcher, UV__POLLIN); - uv__stream_osx_interrupt_select(stream); - } - stream->read_cb(stream, 0, &buf); - } else { - /* Error. User should call uv_close(). */ - stream->read_cb(stream, -errno, &buf); - if (stream->flags & UV_STREAM_READING) { - stream->flags &= ~UV_STREAM_READING; - uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLIN); - if (!uv__io_active(&stream->io_watcher, UV__POLLOUT)) - uv__handle_stop(stream); - uv__stream_osx_interrupt_select(stream); - } - } - return; - } else if (nread == 0) { - uv__stream_eof(stream, &buf); - return; - } else { - /* Successful read */ - ssize_t buflen = buf.len; - - if (is_ipc) { - err = uv__stream_recv_cmsg(stream, &msg); - if (err != 0) { - stream->read_cb(stream, err, &buf); - return; - } - } - stream->read_cb(stream, nread, &buf); - - /* Return if we didn't fill the buffer, there is no more data to read. */ - if (nread < buflen) { - stream->flags |= UV_STREAM_READ_PARTIAL; - return; - } - } - } -} - - -#undef UV__CMSG_FD_COUNT -#undef UV__CMSG_FD_SIZE - - -int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) { - assert((stream->type == UV_TCP || stream->type == UV_NAMED_PIPE) && - "uv_shutdown (unix) only supports uv_handle_t right now"); - - if (!(stream->flags & UV_STREAM_WRITABLE) || - stream->flags & UV_STREAM_SHUT || - stream->flags & UV_STREAM_SHUTTING || - stream->flags & UV_CLOSED || - stream->flags & UV_CLOSING) { - return -ENOTCONN; - } - - assert(uv__stream_fd(stream) >= 0); - - /* Initialize request */ - uv__req_init(stream->loop, req, UV_SHUTDOWN); - req->handle = stream; - req->cb = cb; - stream->shutdown_req = req; - stream->flags |= UV_STREAM_SHUTTING; - - uv__io_start(stream->loop, &stream->io_watcher, UV__POLLOUT); - uv__stream_osx_interrupt_select(stream); - - return 0; -} - - -static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { - uv_stream_t* stream; - - stream = container_of(w, uv_stream_t, io_watcher); - - assert(stream->type == UV_TCP || - stream->type == UV_NAMED_PIPE || - stream->type == UV_TTY); - assert(!(stream->flags & UV_CLOSING)); - - if (stream->connect_req) { - uv__stream_connect(stream); - return; - } - - assert(uv__stream_fd(stream) >= 0); - - /* Ignore POLLHUP here. Even it it's set, there may still be data to read. */ - if (events & (UV__POLLIN | UV__POLLERR | UV__POLLHUP)) - uv__read(stream); - - if (uv__stream_fd(stream) == -1) - return; /* read_cb closed stream. */ - - /* Short-circuit iff POLLHUP is set, the user is still interested in read - * events and uv__read() reported a partial read but not EOF. If the EOF - * flag is set, uv__read() called read_cb with err=UV_EOF and we don't - * have to do anything. If the partial read flag is not set, we can't - * report the EOF yet because there is still data to read. - */ - if ((events & UV__POLLHUP) && - (stream->flags & UV_STREAM_READING) && - (stream->flags & UV_STREAM_READ_PARTIAL) && - !(stream->flags & UV_STREAM_READ_EOF)) { - uv_buf_t buf = { NULL, 0 }; - uv__stream_eof(stream, &buf); - } - - if (uv__stream_fd(stream) == -1) - return; /* read_cb closed stream. */ - - if (events & (UV__POLLOUT | UV__POLLERR | UV__POLLHUP)) { - uv__write(stream); - uv__write_callbacks(stream); - - /* Write queue drained. */ - if (QUEUE_EMPTY(&stream->write_queue)) - uv__drain(stream); - } -} - - -/** - * We get called here from directly following a call to connect(2). - * In order to determine if we've errored out or succeeded must call - * getsockopt. - */ -static void uv__stream_connect(uv_stream_t* stream) { - int error; - uv_connect_t* req = stream->connect_req; - socklen_t errorsize = sizeof(int); - - assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE); - assert(req); - - if (stream->delayed_error) { - /* To smooth over the differences between unixes errors that - * were reported synchronously on the first connect can be delayed - * until the next tick--which is now. - */ - error = stream->delayed_error; - stream->delayed_error = 0; - } else { - /* Normal situation: we need to get the socket error from the kernel. */ - assert(uv__stream_fd(stream) >= 0); - getsockopt(uv__stream_fd(stream), - SOL_SOCKET, - SO_ERROR, - &error, - &errorsize); - error = -error; - } - - if (error == -EINPROGRESS) - return; - - stream->connect_req = NULL; - uv__req_unregister(stream->loop, req); - - if (error < 0 || QUEUE_EMPTY(&stream->write_queue)) { - uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLOUT); - } - - if (req->cb) - req->cb(req, error); - - if (uv__stream_fd(stream) == -1) - return; - - if (error < 0) { - uv__stream_flush_write_queue(stream, -ECANCELED); - uv__write_callbacks(stream); - } -} - - -int uv_write2(uv_write_t* req, - uv_stream_t* stream, - const uv_buf_t bufs[], - unsigned int nbufs, - uv_stream_t* send_handle, - uv_write_cb cb) { - int empty_queue; - - assert(nbufs > 0); - assert((stream->type == UV_TCP || - stream->type == UV_NAMED_PIPE || - stream->type == UV_TTY) && - "uv_write (unix) does not yet support other types of streams"); - - if (uv__stream_fd(stream) < 0) - return -EBADF; - - if (send_handle) { - if (stream->type != UV_NAMED_PIPE || !((uv_pipe_t*)stream)->ipc) - return -EINVAL; - - /* XXX We abuse uv_write2() to send over UDP handles to child processes. - * Don't call uv__stream_fd() on those handles, it's a macro that on OS X - * evaluates to a function that operates on a uv_stream_t with a couple of - * OS X specific fields. On other Unices it does (handle)->io_watcher.fd, - * which works but only by accident. - */ - if (uv__handle_fd((uv_handle_t*) send_handle) < 0) - return -EBADF; - } - - /* It's legal for write_queue_size > 0 even when the write_queue is empty; - * it means there are error-state requests in the write_completed_queue that - * will touch up write_queue_size later, see also uv__write_req_finish(). - * We could check that write_queue is empty instead but that implies making - * a write() syscall when we know that the handle is in error mode. - */ - empty_queue = (stream->write_queue_size == 0); - - /* Initialize the req */ - uv__req_init(stream->loop, req, UV_WRITE); - req->cb = cb; - req->handle = stream; - req->error = 0; - req->send_handle = send_handle; - QUEUE_INIT(&req->queue); - - req->bufs = req->bufsml; - if (nbufs > ARRAY_SIZE(req->bufsml)) - req->bufs = malloc(nbufs * sizeof(bufs[0])); - - if (req->bufs == NULL) - return -ENOMEM; - - memcpy(req->bufs, bufs, nbufs * sizeof(bufs[0])); - req->nbufs = nbufs; - req->write_index = 0; - stream->write_queue_size += uv__count_bufs(bufs, nbufs); - - /* Append the request to write_queue. */ - QUEUE_INSERT_TAIL(&stream->write_queue, &req->queue); - - /* If the queue was empty when this function began, we should attempt to - * do the write immediately. Otherwise start the write_watcher and wait - * for the fd to become writable. - */ - if (stream->connect_req) { - /* Still connecting, do nothing. */ - } - else if (empty_queue) { - uv__write(stream); - } - else { - /* - * blocking streams should never have anything in the queue. - * if this assert fires then somehow the blocking stream isn't being - * sufficiently flushed in uv__write. - */ - assert(!(stream->flags & UV_STREAM_BLOCKING)); - uv__io_start(stream->loop, &stream->io_watcher, UV__POLLOUT); - uv__stream_osx_interrupt_select(stream); - } - - return 0; -} - - -/* The buffers to be written must remain valid until the callback is called. - * This is not required for the uv_buf_t array. - */ -int uv_write(uv_write_t* req, - uv_stream_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - uv_write_cb cb) { - return uv_write2(req, handle, bufs, nbufs, NULL, cb); -} - - -void uv_try_write_cb(uv_write_t* req, int status) { - /* Should not be called */ - abort(); -} - - -int uv_try_write(uv_stream_t* stream, - const uv_buf_t bufs[], - unsigned int nbufs) { - int r; - int has_pollout; - size_t written; - size_t req_size; - uv_write_t req; - - /* Connecting or already writing some data */ - if (stream->connect_req != NULL || stream->write_queue_size != 0) - return -EAGAIN; - - has_pollout = uv__io_active(&stream->io_watcher, UV__POLLOUT); - - r = uv_write(&req, stream, bufs, nbufs, uv_try_write_cb); - if (r != 0) - return r; - - /* Remove not written bytes from write queue size */ - written = uv__count_bufs(bufs, nbufs); - if (req.bufs != NULL) - req_size = uv__write_req_size(&req); - else - req_size = 0; - written -= req_size; - stream->write_queue_size -= req_size; - - /* Unqueue request, regardless of immediateness */ - QUEUE_REMOVE(&req.queue); - uv__req_unregister(stream->loop, &req); - if (req.bufs != req.bufsml) - free(req.bufs); - req.bufs = NULL; - - /* Do not poll for writable, if we wasn't before calling this */ - if (!has_pollout) { - uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLOUT); - uv__stream_osx_interrupt_select(stream); - } - - if (written == 0) - return -EAGAIN; - else - return written; -} - - -int uv_read_start(uv_stream_t* stream, - uv_alloc_cb alloc_cb, - uv_read_cb read_cb) { - assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE || - stream->type == UV_TTY); - - if (stream->flags & UV_CLOSING) - return -EINVAL; - - /* The UV_STREAM_READING flag is irrelevant of the state of the tcp - it just - * expresses the desired state of the user. - */ - stream->flags |= UV_STREAM_READING; - - /* TODO: try to do the read inline? */ - /* TODO: keep track of tcp state. If we've gotten a EOF then we should - * not start the IO watcher. - */ - assert(uv__stream_fd(stream) >= 0); - assert(alloc_cb); - - stream->read_cb = read_cb; - stream->alloc_cb = alloc_cb; - - uv__io_start(stream->loop, &stream->io_watcher, UV__POLLIN); - uv__handle_start(stream); - uv__stream_osx_interrupt_select(stream); - - return 0; -} - - -int uv_read_stop(uv_stream_t* stream) { - if (!(stream->flags & UV_STREAM_READING)) - return 0; - - stream->flags &= ~UV_STREAM_READING; - uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLIN); - if (!uv__io_active(&stream->io_watcher, UV__POLLOUT)) - uv__handle_stop(stream); - uv__stream_osx_interrupt_select(stream); - - stream->read_cb = NULL; - stream->alloc_cb = NULL; - return 0; -} - - -int uv_is_readable(const uv_stream_t* stream) { - return !!(stream->flags & UV_STREAM_READABLE); -} - - -int uv_is_writable(const uv_stream_t* stream) { - return !!(stream->flags & UV_STREAM_WRITABLE); -} - - -#if defined(__APPLE__) -int uv___stream_fd(const uv_stream_t* handle) { - const uv__stream_select_t* s; - - assert(handle->type == UV_TCP || - handle->type == UV_TTY || - handle->type == UV_NAMED_PIPE); - - s = handle->select; - if (s != NULL) - return s->fd; - - return handle->io_watcher.fd; -} -#endif /* defined(__APPLE__) */ - - -void uv__stream_close(uv_stream_t* handle) { - unsigned int i; - uv__stream_queued_fds_t* queued_fds; - -#if defined(__APPLE__) - /* Terminate select loop first */ - if (handle->select != NULL) { - uv__stream_select_t* s; - - s = handle->select; - - uv_sem_post(&s->close_sem); - uv_sem_post(&s->async_sem); - uv__stream_osx_interrupt_select(handle); - uv_thread_join(&s->thread); - uv_sem_destroy(&s->close_sem); - uv_sem_destroy(&s->async_sem); - uv__close(s->fake_fd); - uv__close(s->int_fd); - uv_close((uv_handle_t*) &s->async, uv__stream_osx_cb_close); - - handle->select = NULL; - } -#endif /* defined(__APPLE__) */ - - uv__io_close(handle->loop, &handle->io_watcher); - uv_read_stop(handle); - uv__handle_stop(handle); - - if (handle->io_watcher.fd != -1) { - /* Don't close stdio file descriptors. Nothing good comes from it. */ - if (handle->io_watcher.fd > STDERR_FILENO) - uv__close(handle->io_watcher.fd); - handle->io_watcher.fd = -1; - } - - if (handle->accepted_fd != -1) { - uv__close(handle->accepted_fd); - handle->accepted_fd = -1; - } - - /* Close all queued fds */ - if (handle->queued_fds != NULL) { - queued_fds = handle->queued_fds; - for (i = 0; i < queued_fds->offset; i++) - uv__close(queued_fds->fds[i]); - free(handle->queued_fds); - handle->queued_fds = NULL; - } - - assert(!uv__io_active(&handle->io_watcher, UV__POLLIN | UV__POLLOUT)); -} - - -int uv_stream_set_blocking(uv_stream_t* handle, int blocking) { - return UV_ENOSYS; -} diff --git a/libuv/src/unix/sunos.c b/libuv/src/unix/sunos.c deleted file mode 100644 index c41d0f0..0000000 --- a/libuv/src/unix/sunos.c +++ /dev/null @@ -1,763 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include -#include -#include - -#ifndef SUNOS_NO_IFADDRS -# include -#endif -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#define PORT_FIRED 0x69 -#define PORT_UNUSED 0x0 -#define PORT_LOADED 0x99 -#define PORT_DELETED -1 - -#if (!defined(_LP64)) && (_FILE_OFFSET_BITS - 0 == 64) -#define PROCFS_FILE_OFFSET_BITS_HACK 1 -#undef _FILE_OFFSET_BITS -#else -#define PROCFS_FILE_OFFSET_BITS_HACK 0 -#endif - -#include - -#if (PROCFS_FILE_OFFSET_BITS_HACK - 0 == 1) -#define _FILE_OFFSET_BITS 64 -#endif - - -int uv__platform_loop_init(uv_loop_t* loop) { - int err; - int fd; - - loop->fs_fd = -1; - loop->backend_fd = -1; - - fd = port_create(); - if (fd == -1) - return -errno; - - err = uv__cloexec(fd, 1); - if (err) { - uv__close(fd); - return err; - } - loop->backend_fd = fd; - - return 0; -} - - -void uv__platform_loop_delete(uv_loop_t* loop) { - if (loop->fs_fd != -1) { - uv__close(loop->fs_fd); - loop->fs_fd = -1; - } - - if (loop->backend_fd != -1) { - uv__close(loop->backend_fd); - loop->backend_fd = -1; - } -} - - -void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { - struct port_event* events; - uintptr_t i; - uintptr_t nfds; - - assert(loop->watchers != NULL); - - events = (struct port_event*) loop->watchers[loop->nwatchers]; - nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; - if (events == NULL) - return; - - /* Invalidate events with same file descriptor */ - for (i = 0; i < nfds; i++) - if ((int) events[i].portev_object == fd) - events[i].portev_object = -1; -} - - -void uv__io_poll(uv_loop_t* loop, int timeout) { - struct port_event events[1024]; - struct port_event* pe; - struct timespec spec; - QUEUE* q; - uv__io_t* w; - sigset_t* pset; - sigset_t set; - uint64_t base; - uint64_t diff; - unsigned int nfds; - unsigned int i; - int saved_errno; - int nevents; - int count; - int err; - int fd; - - if (loop->nfds == 0) { - assert(QUEUE_EMPTY(&loop->watcher_queue)); - return; - } - - while (!QUEUE_EMPTY(&loop->watcher_queue)) { - q = QUEUE_HEAD(&loop->watcher_queue); - QUEUE_REMOVE(q); - QUEUE_INIT(q); - - w = QUEUE_DATA(q, uv__io_t, watcher_queue); - assert(w->pevents != 0); - - if (port_associate(loop->backend_fd, PORT_SOURCE_FD, w->fd, w->pevents, 0)) - abort(); - - w->events = w->pevents; - } - - pset = NULL; - if (loop->flags & UV_LOOP_BLOCK_SIGPROF) { - pset = &set; - sigemptyset(pset); - sigaddset(pset, SIGPROF); - } - - assert(timeout >= -1); - base = loop->time; - count = 48; /* Benchmarks suggest this gives the best throughput. */ - - for (;;) { - if (timeout != -1) { - spec.tv_sec = timeout / 1000; - spec.tv_nsec = (timeout % 1000) * 1000000; - } - - /* Work around a kernel bug where nfds is not updated. */ - events[0].portev_source = 0; - - nfds = 1; - saved_errno = 0; - - if (pset != NULL) - pthread_sigmask(SIG_BLOCK, pset, NULL); - - err = port_getn(loop->backend_fd, - events, - ARRAY_SIZE(events), - &nfds, - timeout == -1 ? NULL : &spec); - - if (pset != NULL) - pthread_sigmask(SIG_UNBLOCK, pset, NULL); - - if (err) { - /* Work around another kernel bug: port_getn() may return events even - * on error. - */ - if (errno == EINTR || errno == ETIME) - saved_errno = errno; - else - abort(); - } - - /* Update loop->time unconditionally. It's tempting to skip the update when - * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the - * operating system didn't reschedule our process while in the syscall. - */ - SAVE_ERRNO(uv__update_time(loop)); - - if (events[0].portev_source == 0) { - if (timeout == 0) - return; - - if (timeout == -1) - continue; - - goto update_timeout; - } - - if (nfds == 0) { - assert(timeout != -1); - return; - } - - nevents = 0; - - assert(loop->watchers != NULL); - loop->watchers[loop->nwatchers] = (void*) events; - loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds; - for (i = 0; i < nfds; i++) { - pe = events + i; - fd = pe->portev_object; - - /* Skip invalidated events, see uv__platform_invalidate_fd */ - if (fd == -1) - continue; - - assert(fd >= 0); - assert((unsigned) fd < loop->nwatchers); - - w = loop->watchers[fd]; - - /* File descriptor that we've stopped watching, ignore. */ - if (w == NULL) - continue; - - w->cb(loop, w, pe->portev_events); - nevents++; - - if (w != loop->watchers[fd]) - continue; /* Disabled by callback. */ - - /* Events Ports operates in oneshot mode, rearm timer on next run. */ - if (w->pevents != 0 && QUEUE_EMPTY(&w->watcher_queue)) - QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue); - } - loop->watchers[loop->nwatchers] = NULL; - loop->watchers[loop->nwatchers + 1] = NULL; - - if (nevents != 0) { - if (nfds == ARRAY_SIZE(events) && --count != 0) { - /* Poll for more events but don't block this time. */ - timeout = 0; - continue; - } - return; - } - - if (saved_errno == ETIME) { - assert(timeout != -1); - return; - } - - if (timeout == 0) - return; - - if (timeout == -1) - continue; - -update_timeout: - assert(timeout > 0); - - diff = loop->time - base; - if (diff >= (uint64_t) timeout) - return; - - timeout -= diff; - } -} - - -uint64_t uv__hrtime(uv_clocktype_t type) { - return gethrtime(); -} - - -/* - * We could use a static buffer for the path manipulations that we need outside - * of the function, but this function could be called by multiple consumers and - * we don't want to potentially create a race condition in the use of snprintf. - */ -int uv_exepath(char* buffer, size_t* size) { - ssize_t res; - char buf[128]; - - if (buffer == NULL || size == NULL || *size == 0) - return -EINVAL; - - snprintf(buf, sizeof(buf), "/proc/%lu/path/a.out", (unsigned long) getpid()); - - res = *size - 1; - if (res > 0) - res = readlink(buf, buffer, res); - - if (res == -1) - return -errno; - - buffer[res] = '\0'; - *size = res; - return 0; -} - - -uint64_t uv_get_free_memory(void) { - return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_AVPHYS_PAGES); -} - - -uint64_t uv_get_total_memory(void) { - return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_PHYS_PAGES); -} - - -void uv_loadavg(double avg[3]) { - (void) getloadavg(avg, 3); -} - - -#if defined(PORT_SOURCE_FILE) - -static int uv__fs_event_rearm(uv_fs_event_t *handle) { - if (handle->fd == -1) - return -EBADF; - - if (port_associate(handle->loop->fs_fd, - PORT_SOURCE_FILE, - (uintptr_t) &handle->fo, - FILE_ATTRIB | FILE_MODIFIED, - handle) == -1) { - return -errno; - } - handle->fd = PORT_LOADED; - - return 0; -} - - -static void uv__fs_event_read(uv_loop_t* loop, - uv__io_t* w, - unsigned int revents) { - uv_fs_event_t *handle = NULL; - timespec_t timeout; - port_event_t pe; - int events; - int r; - - (void) w; - (void) revents; - - do { - uint_t n = 1; - - /* - * Note that our use of port_getn() here (and not port_get()) is deliberate: - * there is a bug in event ports (Sun bug 6456558) whereby a zeroed timeout - * causes port_get() to return success instead of ETIME when there aren't - * actually any events (!); by using port_getn() in lieu of port_get(), - * we can at least workaround the bug by checking for zero returned events - * and treating it as we would ETIME. - */ - do { - memset(&timeout, 0, sizeof timeout); - r = port_getn(loop->fs_fd, &pe, 1, &n, &timeout); - } - while (r == -1 && errno == EINTR); - - if ((r == -1 && errno == ETIME) || n == 0) - break; - - handle = (uv_fs_event_t*) pe.portev_user; - assert((r == 0) && "unexpected port_get() error"); - - events = 0; - if (pe.portev_events & (FILE_ATTRIB | FILE_MODIFIED)) - events |= UV_CHANGE; - if (pe.portev_events & ~(FILE_ATTRIB | FILE_MODIFIED)) - events |= UV_RENAME; - assert(events != 0); - handle->fd = PORT_FIRED; - handle->cb(handle, NULL, events, 0); - - if (handle->fd != PORT_DELETED) { - r = uv__fs_event_rearm(handle); - if (r != 0) - handle->cb(handle, NULL, 0, r); - } - } - while (handle->fd != PORT_DELETED); -} - - -int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { - uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); - return 0; -} - - -int uv_fs_event_start(uv_fs_event_t* handle, - uv_fs_event_cb cb, - const char* path, - unsigned int flags) { - int portfd; - int first_run; - int err; - - if (uv__is_active(handle)) - return -EINVAL; - - first_run = 0; - if (handle->loop->fs_fd == -1) { - portfd = port_create(); - if (portfd == -1) - return -errno; - handle->loop->fs_fd = portfd; - first_run = 1; - } - - uv__handle_start(handle); - handle->path = strdup(path); - handle->fd = PORT_UNUSED; - handle->cb = cb; - - memset(&handle->fo, 0, sizeof handle->fo); - handle->fo.fo_name = handle->path; - err = uv__fs_event_rearm(handle); - if (err != 0) - return err; - - if (first_run) { - uv__io_init(&handle->loop->fs_event_watcher, uv__fs_event_read, portfd); - uv__io_start(handle->loop, &handle->loop->fs_event_watcher, UV__POLLIN); - } - - return 0; -} - - -int uv_fs_event_stop(uv_fs_event_t* handle) { - if (!uv__is_active(handle)) - return 0; - - if (handle->fd == PORT_FIRED || handle->fd == PORT_LOADED) { - port_dissociate(handle->loop->fs_fd, - PORT_SOURCE_FILE, - (uintptr_t) &handle->fo); - } - - handle->fd = PORT_DELETED; - free(handle->path); - handle->path = NULL; - handle->fo.fo_name = NULL; - uv__handle_stop(handle); - - return 0; -} - -void uv__fs_event_close(uv_fs_event_t* handle) { - uv_fs_event_stop(handle); -} - -#else /* !defined(PORT_SOURCE_FILE) */ - -int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { - return -ENOSYS; -} - - -int uv_fs_event_start(uv_fs_event_t* handle, - uv_fs_event_cb cb, - const char* filename, - unsigned int flags) { - return -ENOSYS; -} - - -int uv_fs_event_stop(uv_fs_event_t* handle) { - return -ENOSYS; -} - - -void uv__fs_event_close(uv_fs_event_t* handle) { - UNREACHABLE(); -} - -#endif /* defined(PORT_SOURCE_FILE) */ - - -char** uv_setup_args(int argc, char** argv) { - return argv; -} - - -int uv_set_process_title(const char* title) { - return 0; -} - - -int uv_get_process_title(char* buffer, size_t size) { - if (size > 0) { - buffer[0] = '\0'; - } - return 0; -} - - -int uv_resident_set_memory(size_t* rss) { - psinfo_t psinfo; - int err; - int fd; - - fd = open("/proc/self/psinfo", O_RDONLY); - if (fd == -1) - return -errno; - - /* FIXME(bnoordhuis) Handle EINTR. */ - err = -EINVAL; - if (read(fd, &psinfo, sizeof(psinfo)) == sizeof(psinfo)) { - *rss = (size_t)psinfo.pr_rssize * 1024; - err = 0; - } - uv__close(fd); - - return err; -} - - -int uv_uptime(double* uptime) { - kstat_ctl_t *kc; - kstat_t *ksp; - kstat_named_t *knp; - - long hz = sysconf(_SC_CLK_TCK); - - kc = kstat_open(); - if (kc == NULL) - return -EPERM; - - ksp = kstat_lookup(kc, (char*) "unix", 0, (char*) "system_misc"); - if (kstat_read(kc, ksp, NULL) == -1) { - *uptime = -1; - } else { - knp = (kstat_named_t*) kstat_data_lookup(ksp, (char*) "clk_intr"); - *uptime = knp->value.ul / hz; - } - kstat_close(kc); - - return 0; -} - - -int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { - int lookup_instance; - kstat_ctl_t *kc; - kstat_t *ksp; - kstat_named_t *knp; - uv_cpu_info_t* cpu_info; - - kc = kstat_open(); - if (kc == NULL) - return -EPERM; - - /* Get count of cpus */ - lookup_instance = 0; - while ((ksp = kstat_lookup(kc, (char*) "cpu_info", lookup_instance, NULL))) { - lookup_instance++; - } - - *cpu_infos = malloc(lookup_instance * sizeof(**cpu_infos)); - if (!(*cpu_infos)) { - kstat_close(kc); - return -ENOMEM; - } - - *count = lookup_instance; - - cpu_info = *cpu_infos; - lookup_instance = 0; - while ((ksp = kstat_lookup(kc, (char*) "cpu_info", lookup_instance, NULL))) { - if (kstat_read(kc, ksp, NULL) == -1) { - cpu_info->speed = 0; - cpu_info->model = NULL; - } else { - knp = kstat_data_lookup(ksp, (char*) "clock_MHz"); - assert(knp->data_type == KSTAT_DATA_INT32 || - knp->data_type == KSTAT_DATA_INT64); - cpu_info->speed = (knp->data_type == KSTAT_DATA_INT32) ? knp->value.i32 - : knp->value.i64; - - knp = kstat_data_lookup(ksp, (char*) "brand"); - assert(knp->data_type == KSTAT_DATA_STRING); - cpu_info->model = strdup(KSTAT_NAMED_STR_PTR(knp)); - } - - lookup_instance++; - cpu_info++; - } - - cpu_info = *cpu_infos; - lookup_instance = 0; - for (;;) { - ksp = kstat_lookup(kc, (char*) "cpu", lookup_instance, (char*) "sys"); - - if (ksp == NULL) - break; - - if (kstat_read(kc, ksp, NULL) == -1) { - cpu_info->cpu_times.user = 0; - cpu_info->cpu_times.nice = 0; - cpu_info->cpu_times.sys = 0; - cpu_info->cpu_times.idle = 0; - cpu_info->cpu_times.irq = 0; - } else { - knp = kstat_data_lookup(ksp, (char*) "cpu_ticks_user"); - assert(knp->data_type == KSTAT_DATA_UINT64); - cpu_info->cpu_times.user = knp->value.ui64; - - knp = kstat_data_lookup(ksp, (char*) "cpu_ticks_kernel"); - assert(knp->data_type == KSTAT_DATA_UINT64); - cpu_info->cpu_times.sys = knp->value.ui64; - - knp = kstat_data_lookup(ksp, (char*) "cpu_ticks_idle"); - assert(knp->data_type == KSTAT_DATA_UINT64); - cpu_info->cpu_times.idle = knp->value.ui64; - - knp = kstat_data_lookup(ksp, (char*) "intr"); - assert(knp->data_type == KSTAT_DATA_UINT64); - cpu_info->cpu_times.irq = knp->value.ui64; - cpu_info->cpu_times.nice = 0; - } - - lookup_instance++; - cpu_info++; - } - - kstat_close(kc); - - return 0; -} - - -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - int i; - - for (i = 0; i < count; i++) { - free(cpu_infos[i].model); - } - - free(cpu_infos); -} - - -int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { -#ifdef SUNOS_NO_IFADDRS - return -ENOSYS; -#else - uv_interface_address_t* address; - struct sockaddr_dl* sa_addr; - struct ifaddrs* addrs; - struct ifaddrs* ent; - int i; - - if (getifaddrs(&addrs)) - return -errno; - - *count = 0; - - /* Count the number of interfaces */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family == PF_PACKET)) { - continue; - } - - (*count)++; - } - - *addresses = malloc(*count * sizeof(**addresses)); - if (!(*addresses)) - return -ENOMEM; - - address = *addresses; - - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) - continue; - - if (ent->ifa_addr == NULL) - continue; - - address->name = strdup(ent->ifa_name); - - if (ent->ifa_addr->sa_family == AF_INET6) { - address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr); - } else { - address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr); - } - - if (ent->ifa_netmask->sa_family == AF_INET6) { - address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask); - } else { - address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask); - } - - address->is_internal = !!((ent->ifa_flags & IFF_PRIVATE) || - (ent->ifa_flags & IFF_LOOPBACK)); - - address++; - } - - /* Fill in physical addresses for each interface */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family != AF_LINK)) { - continue; - } - - address = *addresses; - - for (i = 0; i < (*count); i++) { - if (strcmp(address->name, ent->ifa_name) == 0) { - sa_addr = (struct sockaddr_dl*)(ent->ifa_addr); - memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); - } - address++; - } - } - - freeifaddrs(addrs); - - return 0; -#endif /* SUNOS_NO_IFADDRS */ -} - - -void uv_free_interface_addresses(uv_interface_address_t* addresses, - int count) { - int i; - - for (i = 0; i < count; i++) { - free(addresses[i].name); - } - - free(addresses); -} diff --git a/libuv/src/unix/tcp.c b/libuv/src/unix/tcp.c deleted file mode 100644 index 4060e7b..0000000 --- a/libuv/src/unix/tcp.c +++ /dev/null @@ -1,327 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include - - -int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* tcp) { - uv__stream_init(loop, (uv_stream_t*)tcp, UV_TCP); - return 0; -} - - -static int maybe_new_socket(uv_tcp_t* handle, int domain, int flags) { - int sockfd; - int err; - - if (uv__stream_fd(handle) != -1) - return 0; - - err = uv__socket(domain, SOCK_STREAM, 0); - if (err < 0) - return err; - sockfd = err; - - err = uv__stream_open((uv_stream_t*) handle, sockfd, flags); - if (err) { - uv__close(sockfd); - return err; - } - - return 0; -} - - -int uv__tcp_bind(uv_tcp_t* tcp, - const struct sockaddr* addr, - unsigned int addrlen, - unsigned int flags) { - int err; - int on; - - /* Cannot set IPv6-only mode on non-IPv6 socket. */ - if ((flags & UV_TCP_IPV6ONLY) && addr->sa_family != AF_INET6) - return -EINVAL; - - err = maybe_new_socket(tcp, - addr->sa_family, - UV_STREAM_READABLE | UV_STREAM_WRITABLE); - if (err) - return err; - - on = 1; - if (setsockopt(tcp->io_watcher.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) - return -errno; - -#ifdef IPV6_V6ONLY - if (addr->sa_family == AF_INET6) { - on = (flags & UV_TCP_IPV6ONLY) != 0; - if (setsockopt(tcp->io_watcher.fd, - IPPROTO_IPV6, - IPV6_V6ONLY, - &on, - sizeof on) == -1) { - return -errno; - } - } -#endif - - errno = 0; - if (bind(tcp->io_watcher.fd, addr, addrlen) && errno != EADDRINUSE) - return -errno; - tcp->delayed_error = -errno; - - if (addr->sa_family == AF_INET6) - tcp->flags |= UV_HANDLE_IPV6; - - return 0; -} - - -int uv__tcp_connect(uv_connect_t* req, - uv_tcp_t* handle, - const struct sockaddr* addr, - unsigned int addrlen, - uv_connect_cb cb) { - int err; - int r; - - assert(handle->type == UV_TCP); - - if (handle->connect_req != NULL) - return -EALREADY; /* FIXME(bnoordhuis) -EINVAL or maybe -EBUSY. */ - - err = maybe_new_socket(handle, - addr->sa_family, - UV_STREAM_READABLE | UV_STREAM_WRITABLE); - if (err) - return err; - - handle->delayed_error = 0; - - do - r = connect(uv__stream_fd(handle), addr, addrlen); - while (r == -1 && errno == EINTR); - - if (r == -1) { - if (errno == EINPROGRESS) - ; /* not an error */ - else if (errno == ECONNREFUSED) - /* If we get a ECONNREFUSED wait until the next tick to report the - * error. Solaris wants to report immediately--other unixes want to - * wait. - */ - handle->delayed_error = -errno; - else - return -errno; - } - - uv__req_init(handle->loop, req, UV_CONNECT); - req->cb = cb; - req->handle = (uv_stream_t*) handle; - QUEUE_INIT(&req->queue); - handle->connect_req = req; - - uv__io_start(handle->loop, &handle->io_watcher, UV__POLLOUT); - - if (handle->delayed_error) - uv__io_feed(handle->loop, &handle->io_watcher); - - return 0; -} - - -int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) { - int err; - - err = uv__nonblock(sock, 1); - if (err) - return err; - - return uv__stream_open((uv_stream_t*)handle, - sock, - UV_STREAM_READABLE | UV_STREAM_WRITABLE); -} - - -int uv_tcp_getsockname(const uv_tcp_t* handle, - struct sockaddr* name, - int* namelen) { - socklen_t socklen; - - if (handle->delayed_error) - return handle->delayed_error; - - if (uv__stream_fd(handle) < 0) - return -EINVAL; /* FIXME(bnoordhuis) -EBADF */ - - /* sizeof(socklen_t) != sizeof(int) on some systems. */ - socklen = (socklen_t) *namelen; - - if (getsockname(uv__stream_fd(handle), name, &socklen)) - return -errno; - - *namelen = (int) socklen; - return 0; -} - - -int uv_tcp_getpeername(const uv_tcp_t* handle, - struct sockaddr* name, - int* namelen) { - socklen_t socklen; - - if (handle->delayed_error) - return handle->delayed_error; - - if (uv__stream_fd(handle) < 0) - return -EINVAL; /* FIXME(bnoordhuis) -EBADF */ - - /* sizeof(socklen_t) != sizeof(int) on some systems. */ - socklen = (socklen_t) *namelen; - - if (getpeername(uv__stream_fd(handle), name, &socklen)) - return -errno; - - *namelen = (int) socklen; - return 0; -} - - -int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) { - static int single_accept = -1; - int err; - - if (tcp->delayed_error) - return tcp->delayed_error; - - if (single_accept == -1) { - const char* val = getenv("UV_TCP_SINGLE_ACCEPT"); - single_accept = (val != NULL && atoi(val) != 0); /* Off by default. */ - } - - if (single_accept) - tcp->flags |= UV_TCP_SINGLE_ACCEPT; - - err = maybe_new_socket(tcp, AF_INET, UV_STREAM_READABLE); - if (err) - return err; - - if (listen(tcp->io_watcher.fd, backlog)) - return -errno; - - tcp->connection_cb = cb; - - /* Start listening for connections. */ - tcp->io_watcher.cb = uv__server_io; - uv__io_start(tcp->loop, &tcp->io_watcher, UV__POLLIN); - - return 0; -} - - -int uv__tcp_nodelay(int fd, int on) { - if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on))) - return -errno; - return 0; -} - - -int uv__tcp_keepalive(int fd, int on, unsigned int delay) { - if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on))) - return -errno; - -#ifdef TCP_KEEPIDLE - if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay))) - return -errno; -#endif - - /* Solaris/SmartOS, if you don't support keep-alive, - * then don't advertise it in your system headers... - */ - /* FIXME(bnoordhuis) That's possibly because sizeof(delay) should be 1. */ -#if defined(TCP_KEEPALIVE) && !defined(__sun) - if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay))) - return -errno; -#endif - - return 0; -} - - -int uv_tcp_nodelay(uv_tcp_t* handle, int on) { - int err; - - if (uv__stream_fd(handle) != -1) { - err = uv__tcp_nodelay(uv__stream_fd(handle), on); - if (err) - return err; - } - - if (on) - handle->flags |= UV_TCP_NODELAY; - else - handle->flags &= ~UV_TCP_NODELAY; - - return 0; -} - - -int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) { - int err; - - if (uv__stream_fd(handle) != -1) { - err =uv__tcp_keepalive(uv__stream_fd(handle), on, delay); - if (err) - return err; - } - - if (on) - handle->flags |= UV_TCP_KEEPALIVE; - else - handle->flags &= ~UV_TCP_KEEPALIVE; - - /* TODO Store delay if uv__stream_fd(handle) == -1 but don't want to enlarge - * uv_tcp_t with an int that's almost never used... - */ - - return 0; -} - - -int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) { - if (enable) - handle->flags &= ~UV_TCP_SINGLE_ACCEPT; - else - handle->flags |= UV_TCP_SINGLE_ACCEPT; - return 0; -} - - -void uv__tcp_close(uv_tcp_t* handle) { - uv__stream_close((uv_stream_t*)handle); -} diff --git a/libuv/src/unix/thread.c b/libuv/src/unix/thread.c deleted file mode 100644 index 7a55bd6..0000000 --- a/libuv/src/unix/thread.c +++ /dev/null @@ -1,519 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include - -#include - -#undef NANOSEC -#define NANOSEC ((uint64_t) 1e9) - - -struct thread_ctx { - void (*entry)(void* arg); - void* arg; -}; - - -static void* uv__thread_start(void *arg) -{ - struct thread_ctx *ctx_p; - struct thread_ctx ctx; - - ctx_p = arg; - ctx = *ctx_p; - free(ctx_p); - ctx.entry(ctx.arg); - - return 0; -} - - -int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { - struct thread_ctx* ctx; - int err; - - ctx = malloc(sizeof(*ctx)); - if (ctx == NULL) - return UV_ENOMEM; - - ctx->entry = entry; - ctx->arg = arg; - - err = pthread_create(tid, NULL, uv__thread_start, ctx); - - if (err) - free(ctx); - - return err ? -1 : 0; -} - - -uv_thread_t uv_thread_self(void) { - return pthread_self(); -} - -int uv_thread_join(uv_thread_t *tid) { - return -pthread_join(*tid, NULL); -} - - -int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) { - return pthread_equal(*t1, *t2); -} - - -int uv_mutex_init(uv_mutex_t* mutex) { -#if defined(NDEBUG) || !defined(PTHREAD_MUTEX_ERRORCHECK) - return -pthread_mutex_init(mutex, NULL); -#else - pthread_mutexattr_t attr; - int err; - - if (pthread_mutexattr_init(&attr)) - abort(); - - if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK)) - abort(); - - err = pthread_mutex_init(mutex, &attr); - - if (pthread_mutexattr_destroy(&attr)) - abort(); - - return -err; -#endif -} - - -void uv_mutex_destroy(uv_mutex_t* mutex) { - if (pthread_mutex_destroy(mutex)) - abort(); -} - - -void uv_mutex_lock(uv_mutex_t* mutex) { - if (pthread_mutex_lock(mutex)) - abort(); -} - - -int uv_mutex_trylock(uv_mutex_t* mutex) { - int err; - - /* FIXME(bnoordhuis) EAGAIN means recursive lock limit reached. Arguably - * a bug, should probably abort rather than return -EAGAIN. - */ - err = pthread_mutex_trylock(mutex); - if (err && err != EBUSY && err != EAGAIN) - abort(); - - return -err; -} - - -void uv_mutex_unlock(uv_mutex_t* mutex) { - if (pthread_mutex_unlock(mutex)) - abort(); -} - - -int uv_rwlock_init(uv_rwlock_t* rwlock) { - return -pthread_rwlock_init(rwlock, NULL); -} - - -void uv_rwlock_destroy(uv_rwlock_t* rwlock) { - if (pthread_rwlock_destroy(rwlock)) - abort(); -} - - -void uv_rwlock_rdlock(uv_rwlock_t* rwlock) { - if (pthread_rwlock_rdlock(rwlock)) - abort(); -} - - -int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock) { - int err; - - err = pthread_rwlock_tryrdlock(rwlock); - if (err && err != EBUSY && err != EAGAIN) - abort(); - - return -err; -} - - -void uv_rwlock_rdunlock(uv_rwlock_t* rwlock) { - if (pthread_rwlock_unlock(rwlock)) - abort(); -} - - -void uv_rwlock_wrlock(uv_rwlock_t* rwlock) { - if (pthread_rwlock_wrlock(rwlock)) - abort(); -} - - -int uv_rwlock_trywrlock(uv_rwlock_t* rwlock) { - int err; - - err = pthread_rwlock_trywrlock(rwlock); - if (err && err != EBUSY && err != EAGAIN) - abort(); - - return -err; -} - - -void uv_rwlock_wrunlock(uv_rwlock_t* rwlock) { - if (pthread_rwlock_unlock(rwlock)) - abort(); -} - - -void uv_once(uv_once_t* guard, void (*callback)(void)) { - if (pthread_once(guard, callback)) - abort(); -} - -#if defined(__APPLE__) && defined(__MACH__) - -int uv_sem_init(uv_sem_t* sem, unsigned int value) { - kern_return_t err; - - err = semaphore_create(mach_task_self(), sem, SYNC_POLICY_FIFO, value); - if (err == KERN_SUCCESS) - return 0; - if (err == KERN_INVALID_ARGUMENT) - return -EINVAL; - if (err == KERN_RESOURCE_SHORTAGE) - return -ENOMEM; - - abort(); - return -EINVAL; /* Satisfy the compiler. */ -} - - -void uv_sem_destroy(uv_sem_t* sem) { - if (semaphore_destroy(mach_task_self(), *sem)) - abort(); -} - - -void uv_sem_post(uv_sem_t* sem) { - if (semaphore_signal(*sem)) - abort(); -} - - -void uv_sem_wait(uv_sem_t* sem) { - int r; - - do - r = semaphore_wait(*sem); - while (r == KERN_ABORTED); - - if (r != KERN_SUCCESS) - abort(); -} - - -int uv_sem_trywait(uv_sem_t* sem) { - mach_timespec_t interval; - kern_return_t err; - - interval.tv_sec = 0; - interval.tv_nsec = 0; - - err = semaphore_timedwait(*sem, interval); - if (err == KERN_SUCCESS) - return 0; - if (err == KERN_OPERATION_TIMED_OUT) - return -EAGAIN; - - abort(); - return -EINVAL; /* Satisfy the compiler. */ -} - -#else /* !(defined(__APPLE__) && defined(__MACH__)) */ - -int uv_sem_init(uv_sem_t* sem, unsigned int value) { - if (sem_init(sem, 0, value)) - return -errno; - return 0; -} - - -void uv_sem_destroy(uv_sem_t* sem) { - if (sem_destroy(sem)) - abort(); -} - - -void uv_sem_post(uv_sem_t* sem) { - if (sem_post(sem)) - abort(); -} - - -void uv_sem_wait(uv_sem_t* sem) { - int r; - - do - r = sem_wait(sem); - while (r == -1 && errno == EINTR); - - if (r) - abort(); -} - - -int uv_sem_trywait(uv_sem_t* sem) { - int r; - - do - r = sem_trywait(sem); - while (r == -1 && errno == EINTR); - - if (r) { - if (errno == EAGAIN) - return -EAGAIN; - abort(); - } - - return 0; -} - -#endif /* defined(__APPLE__) && defined(__MACH__) */ - - -#if defined(__APPLE__) && defined(__MACH__) - -int uv_cond_init(uv_cond_t* cond) { - return -pthread_cond_init(cond, NULL); -} - -#else /* !(defined(__APPLE__) && defined(__MACH__)) */ - -int uv_cond_init(uv_cond_t* cond) { - pthread_condattr_t attr; - int err; - - err = pthread_condattr_init(&attr); - if (err) - return -err; - -#if !defined(__ANDROID__) - err = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); - if (err) - goto error2; -#endif - - err = pthread_cond_init(cond, &attr); - if (err) - goto error2; - - err = pthread_condattr_destroy(&attr); - if (err) - goto error; - - return 0; - -error: - pthread_cond_destroy(cond); -error2: - pthread_condattr_destroy(&attr); - return -err; -} - -#endif /* defined(__APPLE__) && defined(__MACH__) */ - -void uv_cond_destroy(uv_cond_t* cond) { - if (pthread_cond_destroy(cond)) - abort(); -} - -void uv_cond_signal(uv_cond_t* cond) { - if (pthread_cond_signal(cond)) - abort(); -} - -void uv_cond_broadcast(uv_cond_t* cond) { - if (pthread_cond_broadcast(cond)) - abort(); -} - -void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) { - if (pthread_cond_wait(cond, mutex)) - abort(); -} - - -int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) { - int r; - struct timespec ts; - -#if defined(__APPLE__) && defined(__MACH__) - ts.tv_sec = timeout / NANOSEC; - ts.tv_nsec = timeout % NANOSEC; - r = pthread_cond_timedwait_relative_np(cond, mutex, &ts); -#else - timeout += uv__hrtime(UV_CLOCK_PRECISE); - ts.tv_sec = timeout / NANOSEC; - ts.tv_nsec = timeout % NANOSEC; -#if defined(__ANDROID__) - /* - * The bionic pthread implementation doesn't support CLOCK_MONOTONIC, - * but has this alternative function instead. - */ - r = pthread_cond_timedwait_monotonic_np(cond, mutex, &ts); -#else - r = pthread_cond_timedwait(cond, mutex, &ts); -#endif /* __ANDROID__ */ -#endif - - - if (r == 0) - return 0; - - if (r == ETIMEDOUT) - return -ETIMEDOUT; - - abort(); - return -EINVAL; /* Satisfy the compiler. */ -} - - -#if defined(__APPLE__) && defined(__MACH__) - -int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) { - int err; - - barrier->n = count; - barrier->count = 0; - - err = uv_mutex_init(&barrier->mutex); - if (err) - return -err; - - err = uv_sem_init(&barrier->turnstile1, 0); - if (err) - goto error2; - - err = uv_sem_init(&barrier->turnstile2, 1); - if (err) - goto error; - - return 0; - -error: - uv_sem_destroy(&barrier->turnstile1); -error2: - uv_mutex_destroy(&barrier->mutex); - return -err; - -} - - -void uv_barrier_destroy(uv_barrier_t* barrier) { - uv_sem_destroy(&barrier->turnstile2); - uv_sem_destroy(&barrier->turnstile1); - uv_mutex_destroy(&barrier->mutex); -} - - -int uv_barrier_wait(uv_barrier_t* barrier) { - int serial_thread; - - uv_mutex_lock(&barrier->mutex); - if (++barrier->count == barrier->n) { - uv_sem_wait(&barrier->turnstile2); - uv_sem_post(&barrier->turnstile1); - } - uv_mutex_unlock(&barrier->mutex); - - uv_sem_wait(&barrier->turnstile1); - uv_sem_post(&barrier->turnstile1); - - uv_mutex_lock(&barrier->mutex); - serial_thread = (--barrier->count == 0); - if (serial_thread) { - uv_sem_wait(&barrier->turnstile1); - uv_sem_post(&barrier->turnstile2); - } - uv_mutex_unlock(&barrier->mutex); - - uv_sem_wait(&barrier->turnstile2); - uv_sem_post(&barrier->turnstile2); - return serial_thread; -} - -#else /* !(defined(__APPLE__) && defined(__MACH__)) */ - -int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) { - return -pthread_barrier_init(barrier, NULL, count); -} - - -void uv_barrier_destroy(uv_barrier_t* barrier) { - if (pthread_barrier_destroy(barrier)) - abort(); -} - - -int uv_barrier_wait(uv_barrier_t* barrier) { - int r = pthread_barrier_wait(barrier); - if (r && r != PTHREAD_BARRIER_SERIAL_THREAD) - abort(); - return r == PTHREAD_BARRIER_SERIAL_THREAD; -} - -#endif /* defined(__APPLE__) && defined(__MACH__) */ - -int uv_key_create(uv_key_t* key) { - return -pthread_key_create(key, NULL); -} - - -void uv_key_delete(uv_key_t* key) { - if (pthread_key_delete(*key)) - abort(); -} - - -void* uv_key_get(uv_key_t* key) { - return pthread_getspecific(*key); -} - - -void uv_key_set(uv_key_t* key, void* value) { - if (pthread_setspecific(*key, value)) - abort(); -} diff --git a/libuv/src/unix/timer.c b/libuv/src/unix/timer.c deleted file mode 100644 index ca3ec3d..0000000 --- a/libuv/src/unix/timer.c +++ /dev/null @@ -1,172 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" -#include "heap-inl.h" - -#include -#include - - -static int timer_less_than(const struct heap_node* ha, - const struct heap_node* hb) { - const uv_timer_t* a; - const uv_timer_t* b; - - a = container_of(ha, const uv_timer_t, heap_node); - b = container_of(hb, const uv_timer_t, heap_node); - - if (a->timeout < b->timeout) - return 1; - if (b->timeout < a->timeout) - return 0; - - /* Compare start_id when both have the same timeout. start_id is - * allocated with loop->timer_counter in uv_timer_start(). - */ - if (a->start_id < b->start_id) - return 1; - if (b->start_id < a->start_id) - return 0; - - return 0; -} - - -int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) { - uv__handle_init(loop, (uv_handle_t*)handle, UV_TIMER); - handle->timer_cb = NULL; - handle->repeat = 0; - return 0; -} - - -int uv_timer_start(uv_timer_t* handle, - uv_timer_cb cb, - uint64_t timeout, - uint64_t repeat) { - uint64_t clamped_timeout; - - if (cb == NULL) - return -EINVAL; - - if (uv__is_active(handle)) - uv_timer_stop(handle); - - clamped_timeout = handle->loop->time + timeout; - if (clamped_timeout < timeout) - clamped_timeout = (uint64_t) -1; - - handle->timer_cb = cb; - handle->timeout = clamped_timeout; - handle->repeat = repeat; - /* start_id is the second index to be compared in uv__timer_cmp() */ - handle->start_id = handle->loop->timer_counter++; - - heap_insert((struct heap*) &handle->loop->timer_heap, - (struct heap_node*) &handle->heap_node, - timer_less_than); - uv__handle_start(handle); - - return 0; -} - - -int uv_timer_stop(uv_timer_t* handle) { - if (!uv__is_active(handle)) - return 0; - - heap_remove((struct heap*) &handle->loop->timer_heap, - (struct heap_node*) &handle->heap_node, - timer_less_than); - uv__handle_stop(handle); - - return 0; -} - - -int uv_timer_again(uv_timer_t* handle) { - if (handle->timer_cb == NULL) - return -EINVAL; - - if (handle->repeat) { - uv_timer_stop(handle); - uv_timer_start(handle, handle->timer_cb, handle->repeat, handle->repeat); - } - - return 0; -} - - -void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat) { - handle->repeat = repeat; -} - - -uint64_t uv_timer_get_repeat(const uv_timer_t* handle) { - return handle->repeat; -} - - -int uv__next_timeout(const uv_loop_t* loop) { - const struct heap_node* heap_node; - const uv_timer_t* handle; - uint64_t diff; - - heap_node = heap_min((const struct heap*) &loop->timer_heap); - if (heap_node == NULL) - return -1; /* block indefinitely */ - - handle = container_of(heap_node, const uv_timer_t, heap_node); - if (handle->timeout <= loop->time) - return 0; - - diff = handle->timeout - loop->time; - if (diff > INT_MAX) - diff = INT_MAX; - - return diff; -} - - -void uv__run_timers(uv_loop_t* loop) { - struct heap_node* heap_node; - uv_timer_t* handle; - - for (;;) { - heap_node = heap_min((struct heap*) &loop->timer_heap); - if (heap_node == NULL) - break; - - handle = container_of(heap_node, uv_timer_t, heap_node); - if (handle->timeout > loop->time) - break; - - uv_timer_stop(handle); - uv_timer_again(handle); - handle->timer_cb(handle); - } -} - - -void uv__timer_close(uv_timer_t* handle) { - uv_timer_stop(handle); -} diff --git a/libuv/src/unix/tty.c b/libuv/src/unix/tty.c deleted file mode 100644 index a1ea433..0000000 --- a/libuv/src/unix/tty.c +++ /dev/null @@ -1,234 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" -#include "spinlock.h" - -#include -#include -#include -#include -#include - -static int orig_termios_fd = -1; -static struct termios orig_termios; -static uv_spinlock_t termios_spinlock = UV_SPINLOCK_INITIALIZER; - - -int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { - int flags; - int newfd; - int r; - - flags = 0; - newfd = -1; - - uv__stream_init(loop, (uv_stream_t*) tty, UV_TTY); - - /* Reopen the file descriptor when it refers to a tty. This lets us put the - * tty in non-blocking mode without affecting other processes that share it - * with us. - * - * Example: `node | cat` - if we put our fd 0 in non-blocking mode, it also - * affects fd 1 of `cat` because both file descriptors refer to the same - * struct file in the kernel. When we reopen our fd 0, it points to a - * different struct file, hence changing its properties doesn't affect - * other processes. - */ - if (isatty(fd)) { - r = uv__open_cloexec("/dev/tty", O_RDWR); - - if (r < 0) { - /* fallback to using blocking writes */ - if (!readable) - flags |= UV_STREAM_BLOCKING; - goto skip; - } - - newfd = r; - - r = uv__dup2_cloexec(newfd, fd); - if (r < 0 && r != -EINVAL) { - /* EINVAL means newfd == fd which could conceivably happen if another - * thread called close(fd) between our calls to isatty() and open(). - * That's a rather unlikely event but let's handle it anyway. - */ - uv__close(newfd); - return r; - } - - fd = newfd; - } - -skip: -#if defined(__APPLE__) - r = uv__stream_try_select((uv_stream_t*) tty, &fd); - if (r) { - if (newfd != -1) - uv__close(newfd); - return r; - } -#endif - - if (readable) - flags |= UV_STREAM_READABLE; - else - flags |= UV_STREAM_WRITABLE; - - if (!(flags & UV_STREAM_BLOCKING)) - uv__nonblock(fd, 1); - - uv__stream_open((uv_stream_t*) tty, fd, flags); - tty->mode = UV_TTY_MODE_NORMAL; - - return 0; -} - - -int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) { - struct termios tmp; - int fd; - - if (tty->mode == (int) mode) - return 0; - - fd = uv__stream_fd(tty); - if (tty->mode == UV_TTY_MODE_NORMAL && mode != UV_TTY_MODE_NORMAL) { - if (tcgetattr(fd, &tty->orig_termios)) - return -errno; - - /* This is used for uv_tty_reset_mode() */ - uv_spinlock_lock(&termios_spinlock); - if (orig_termios_fd == -1) { - orig_termios = tty->orig_termios; - orig_termios_fd = fd; - } - uv_spinlock_unlock(&termios_spinlock); - } - - tmp = tty->orig_termios; - switch (mode) { - case UV_TTY_MODE_NORMAL: - break; - case UV_TTY_MODE_RAW: - tmp.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); - tmp.c_oflag |= (ONLCR); - tmp.c_cflag |= (CS8); - tmp.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); - tmp.c_cc[VMIN] = 1; - tmp.c_cc[VTIME] = 0; - break; - case UV_TTY_MODE_IO: - cfmakeraw(&tmp); - break; - } - - /* Apply changes after draining */ - if (tcsetattr(fd, TCSADRAIN, &tmp)) - return -errno; - - tty->mode = mode; - return 0; -} - - -int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) { - struct winsize ws; - - if (ioctl(uv__stream_fd(tty), TIOCGWINSZ, &ws)) - return -errno; - - *width = ws.ws_col; - *height = ws.ws_row; - - return 0; -} - - -uv_handle_type uv_guess_handle(uv_file file) { - struct sockaddr sa; - struct stat s; - socklen_t len; - int type; - - if (file < 0) - return UV_UNKNOWN_HANDLE; - - if (isatty(file)) - return UV_TTY; - - if (fstat(file, &s)) - return UV_UNKNOWN_HANDLE; - - if (S_ISREG(s.st_mode)) - return UV_FILE; - - if (S_ISCHR(s.st_mode)) - return UV_FILE; /* XXX UV_NAMED_PIPE? */ - - if (S_ISFIFO(s.st_mode)) - return UV_NAMED_PIPE; - - if (!S_ISSOCK(s.st_mode)) - return UV_UNKNOWN_HANDLE; - - len = sizeof(type); - if (getsockopt(file, SOL_SOCKET, SO_TYPE, &type, &len)) - return UV_UNKNOWN_HANDLE; - - len = sizeof(sa); - if (getsockname(file, &sa, &len)) - return UV_UNKNOWN_HANDLE; - - if (type == SOCK_DGRAM) - if (sa.sa_family == AF_INET || sa.sa_family == AF_INET6) - return UV_UDP; - - if (type == SOCK_STREAM) { - if (sa.sa_family == AF_INET || sa.sa_family == AF_INET6) - return UV_TCP; - if (sa.sa_family == AF_UNIX) - return UV_NAMED_PIPE; - } - - return UV_UNKNOWN_HANDLE; -} - - -/* This function is async signal-safe, meaning that it's safe to call from - * inside a signal handler _unless_ execution was inside uv_tty_set_mode()'s - * critical section when the signal was raised. - */ -int uv_tty_reset_mode(void) { - int err; - - if (!uv_spinlock_trylock(&termios_spinlock)) - return -EBUSY; /* In uv_tty_set_mode(). */ - - err = 0; - if (orig_termios_fd != -1) - if (tcsetattr(orig_termios_fd, TCSANOW, &orig_termios)) - err = -errno; - - uv_spinlock_unlock(&termios_spinlock); - return err; -} diff --git a/libuv/src/unix/udp.c b/libuv/src/unix/udp.c deleted file mode 100644 index 941c0ae..0000000 --- a/libuv/src/unix/udp.c +++ /dev/null @@ -1,782 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include -#include - -#if defined(IPV6_JOIN_GROUP) && !defined(IPV6_ADD_MEMBERSHIP) -# define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP -#endif - -#if defined(IPV6_LEAVE_GROUP) && !defined(IPV6_DROP_MEMBERSHIP) -# define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP -#endif - - -static void uv__udp_run_completed(uv_udp_t* handle); -static void uv__udp_io(uv_loop_t* loop, uv__io_t* w, unsigned int revents); -static void uv__udp_recvmsg(uv_udp_t* handle); -static void uv__udp_sendmsg(uv_udp_t* handle); -static int uv__udp_maybe_deferred_bind(uv_udp_t* handle, - int domain, - unsigned int flags); - - -void uv__udp_close(uv_udp_t* handle) { - uv__io_close(handle->loop, &handle->io_watcher); - uv__handle_stop(handle); - - if (handle->io_watcher.fd != -1) { - uv__close(handle->io_watcher.fd); - handle->io_watcher.fd = -1; - } -} - - -void uv__udp_finish_close(uv_udp_t* handle) { - uv_udp_send_t* req; - QUEUE* q; - - assert(!uv__io_active(&handle->io_watcher, UV__POLLIN | UV__POLLOUT)); - assert(handle->io_watcher.fd == -1); - - while (!QUEUE_EMPTY(&handle->write_queue)) { - q = QUEUE_HEAD(&handle->write_queue); - QUEUE_REMOVE(q); - - req = QUEUE_DATA(q, uv_udp_send_t, queue); - req->status = -ECANCELED; - QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue); - } - - uv__udp_run_completed(handle); - - assert(handle->send_queue_size == 0); - assert(handle->send_queue_count == 0); - - /* Now tear down the handle. */ - handle->recv_cb = NULL; - handle->alloc_cb = NULL; - /* but _do not_ touch close_cb */ -} - - -static void uv__udp_run_completed(uv_udp_t* handle) { - uv_udp_send_t* req; - QUEUE* q; - - while (!QUEUE_EMPTY(&handle->write_completed_queue)) { - q = QUEUE_HEAD(&handle->write_completed_queue); - QUEUE_REMOVE(q); - - req = QUEUE_DATA(q, uv_udp_send_t, queue); - uv__req_unregister(handle->loop, req); - - handle->send_queue_size -= uv__count_bufs(req->bufs, req->nbufs); - handle->send_queue_count--; - - if (req->bufs != req->bufsml) - free(req->bufs); - req->bufs = NULL; - - if (req->send_cb == NULL) - continue; - - /* req->status >= 0 == bytes written - * req->status < 0 == errno - */ - if (req->status >= 0) - req->send_cb(req, 0); - else - req->send_cb(req, req->status); - } - - if (QUEUE_EMPTY(&handle->write_queue)) { - /* Pending queue and completion queue empty, stop watcher. */ - uv__io_stop(handle->loop, &handle->io_watcher, UV__POLLOUT); - if (!uv__io_active(&handle->io_watcher, UV__POLLIN)) - uv__handle_stop(handle); - } -} - - -static void uv__udp_io(uv_loop_t* loop, uv__io_t* w, unsigned int revents) { - uv_udp_t* handle; - - handle = container_of(w, uv_udp_t, io_watcher); - assert(handle->type == UV_UDP); - - if (revents & UV__POLLIN) - uv__udp_recvmsg(handle); - - if (revents & UV__POLLOUT) { - uv__udp_sendmsg(handle); - uv__udp_run_completed(handle); - } -} - - -static void uv__udp_recvmsg(uv_udp_t* handle) { - struct sockaddr_storage peer; - struct msghdr h; - ssize_t nread; - uv_buf_t buf; - int flags; - int count; - - assert(handle->recv_cb != NULL); - assert(handle->alloc_cb != NULL); - - /* Prevent loop starvation when the data comes in as fast as (or faster than) - * we can read it. XXX Need to rearm fd if we switch to edge-triggered I/O. - */ - count = 32; - - memset(&h, 0, sizeof(h)); - h.msg_name = &peer; - - do { - handle->alloc_cb((uv_handle_t*) handle, 64 * 1024, &buf); - if (buf.len == 0) { - handle->recv_cb(handle, UV_ENOBUFS, &buf, NULL, 0); - return; - } - assert(buf.base != NULL); - - h.msg_namelen = sizeof(peer); - h.msg_iov = (void*) &buf; - h.msg_iovlen = 1; - - do { - nread = recvmsg(handle->io_watcher.fd, &h, 0); - } - while (nread == -1 && errno == EINTR); - - if (nread == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) - handle->recv_cb(handle, 0, &buf, NULL, 0); - else - handle->recv_cb(handle, -errno, &buf, NULL, 0); - } - else { - const struct sockaddr *addr; - if (h.msg_namelen == 0) - addr = NULL; - else - addr = (const struct sockaddr*) &peer; - - flags = 0; - if (h.msg_flags & MSG_TRUNC) - flags |= UV_UDP_PARTIAL; - - handle->recv_cb(handle, nread, &buf, addr, flags); - } - } - /* recv_cb callback may decide to pause or close the handle */ - while (nread != -1 - && count-- > 0 - && handle->io_watcher.fd != -1 - && handle->recv_cb != NULL); -} - - -static void uv__udp_sendmsg(uv_udp_t* handle) { - uv_udp_send_t* req; - QUEUE* q; - struct msghdr h; - ssize_t size; - - while (!QUEUE_EMPTY(&handle->write_queue)) { - q = QUEUE_HEAD(&handle->write_queue); - assert(q != NULL); - - req = QUEUE_DATA(q, uv_udp_send_t, queue); - assert(req != NULL); - - memset(&h, 0, sizeof h); - h.msg_name = &req->addr; - h.msg_namelen = (req->addr.ss_family == AF_INET6 ? - sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)); - h.msg_iov = (struct iovec*) req->bufs; - h.msg_iovlen = req->nbufs; - - do { - size = sendmsg(handle->io_watcher.fd, &h, 0); - } while (size == -1 && errno == EINTR); - - if (size == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) - break; - - req->status = (size == -1 ? -errno : size); - - /* Sending a datagram is an atomic operation: either all data - * is written or nothing is (and EMSGSIZE is raised). That is - * why we don't handle partial writes. Just pop the request - * off the write queue and onto the completed queue, done. - */ - QUEUE_REMOVE(&req->queue); - QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue); - uv__io_feed(handle->loop, &handle->io_watcher); - } -} - - -/* On the BSDs, SO_REUSEPORT implies SO_REUSEADDR but with some additional - * refinements for programs that use multicast. - * - * Linux as of 3.9 has a SO_REUSEPORT socket option but with semantics that - * are different from the BSDs: it _shares_ the port rather than steal it - * from the current listener. While useful, it's not something we can emulate - * on other platforms so we don't enable it. - */ -static int uv__set_reuse(int fd) { - int yes; - -#if defined(SO_REUSEPORT) && !defined(__linux__) - yes = 1; - if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes))) - return -errno; -#else - yes = 1; - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes))) - return -errno; -#endif - - return 0; -} - - -int uv__udp_bind(uv_udp_t* handle, - const struct sockaddr* addr, - unsigned int addrlen, - unsigned int flags) { - int err; - int yes; - int fd; - - /* Check for bad flags. */ - if (flags & ~(UV_UDP_IPV6ONLY | UV_UDP_REUSEADDR)) - return -EINVAL; - - /* Cannot set IPv6-only mode on non-IPv6 socket. */ - if ((flags & UV_UDP_IPV6ONLY) && addr->sa_family != AF_INET6) - return -EINVAL; - - fd = handle->io_watcher.fd; - if (fd == -1) { - err = uv__socket(addr->sa_family, SOCK_DGRAM, 0); - if (err < 0) - return err; - fd = err; - handle->io_watcher.fd = fd; - } - - if (flags & UV_UDP_REUSEADDR) { - err = uv__set_reuse(fd); - if (err) - goto out; - } - - if (flags & UV_UDP_IPV6ONLY) { -#ifdef IPV6_V6ONLY - yes = 1; - if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof yes) == -1) { - err = -errno; - goto out; - } -#else - err = -ENOTSUP; - goto out; -#endif - } - - if (bind(fd, addr, addrlen)) { - err = -errno; - goto out; - } - - if (addr->sa_family == AF_INET6) - handle->flags |= UV_HANDLE_IPV6; - - return 0; - -out: - uv__close(handle->io_watcher.fd); - handle->io_watcher.fd = -1; - return err; -} - - -static int uv__udp_maybe_deferred_bind(uv_udp_t* handle, - int domain, - unsigned int flags) { - unsigned char taddr[sizeof(struct sockaddr_in6)]; - socklen_t addrlen; - - if (handle->io_watcher.fd != -1) - return 0; - - switch (domain) { - case AF_INET: - { - struct sockaddr_in* addr = (void*)&taddr; - memset(addr, 0, sizeof *addr); - addr->sin_family = AF_INET; - addr->sin_addr.s_addr = INADDR_ANY; - addrlen = sizeof *addr; - break; - } - case AF_INET6: - { - struct sockaddr_in6* addr = (void*)&taddr; - memset(addr, 0, sizeof *addr); - addr->sin6_family = AF_INET6; - addr->sin6_addr = in6addr_any; - addrlen = sizeof *addr; - break; - } - default: - assert(0 && "unsupported address family"); - abort(); - } - - return uv__udp_bind(handle, (const struct sockaddr*) &taddr, addrlen, flags); -} - - -int uv__udp_send(uv_udp_send_t* req, - uv_udp_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - const struct sockaddr* addr, - unsigned int addrlen, - uv_udp_send_cb send_cb) { - int err; - int empty_queue; - - assert(nbufs > 0); - - err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0); - if (err) - return err; - - /* It's legal for send_queue_count > 0 even when the write_queue is empty; - * it means there are error-state requests in the write_completed_queue that - * will touch up send_queue_size/count later. - */ - empty_queue = (handle->send_queue_count == 0); - - uv__req_init(handle->loop, req, UV_UDP_SEND); - assert(addrlen <= sizeof(req->addr)); - memcpy(&req->addr, addr, addrlen); - req->send_cb = send_cb; - req->handle = handle; - req->nbufs = nbufs; - - req->bufs = req->bufsml; - if (nbufs > ARRAY_SIZE(req->bufsml)) - req->bufs = malloc(nbufs * sizeof(bufs[0])); - - if (req->bufs == NULL) - return -ENOMEM; - - memcpy(req->bufs, bufs, nbufs * sizeof(bufs[0])); - handle->send_queue_size += uv__count_bufs(req->bufs, req->nbufs); - handle->send_queue_count++; - QUEUE_INSERT_TAIL(&handle->write_queue, &req->queue); - uv__handle_start(handle); - - if (empty_queue) - uv__udp_sendmsg(handle); - else - uv__io_start(handle->loop, &handle->io_watcher, UV__POLLOUT); - - return 0; -} - - -int uv__udp_try_send(uv_udp_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - const struct sockaddr* addr, - unsigned int addrlen) { - int err; - struct msghdr h; - ssize_t size; - - assert(nbufs > 0); - - /* already sending a message */ - if (handle->send_queue_count != 0) - return -EAGAIN; - - err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0); - if (err) - return err; - - memset(&h, 0, sizeof h); - h.msg_name = (struct sockaddr*) addr; - h.msg_namelen = addrlen; - h.msg_iov = (struct iovec*) bufs; - h.msg_iovlen = nbufs; - - do { - size = sendmsg(handle->io_watcher.fd, &h, 0); - } while (size == -1 && errno == EINTR); - - if (size == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) - return -EAGAIN; - else - return -errno; - } - - return size; -} - - -static int uv__udp_set_membership4(uv_udp_t* handle, - const struct sockaddr_in* multicast_addr, - const char* interface_addr, - uv_membership membership) { - struct ip_mreq mreq; - int optname; - int err; - - memset(&mreq, 0, sizeof mreq); - - if (interface_addr) { - err = uv_inet_pton(AF_INET, interface_addr, &mreq.imr_interface.s_addr); - if (err) - return err; - } else { - mreq.imr_interface.s_addr = htonl(INADDR_ANY); - } - - mreq.imr_multiaddr.s_addr = multicast_addr->sin_addr.s_addr; - - switch (membership) { - case UV_JOIN_GROUP: - optname = IP_ADD_MEMBERSHIP; - break; - case UV_LEAVE_GROUP: - optname = IP_DROP_MEMBERSHIP; - break; - default: - return -EINVAL; - } - - if (setsockopt(handle->io_watcher.fd, - IPPROTO_IP, - optname, - &mreq, - sizeof(mreq))) { - return -errno; - } - - return 0; -} - - -static int uv__udp_set_membership6(uv_udp_t* handle, - const struct sockaddr_in6* multicast_addr, - const char* interface_addr, - uv_membership membership) { - int optname; - struct ipv6_mreq mreq; - struct sockaddr_in6 addr6; - - memset(&mreq, 0, sizeof mreq); - - if (interface_addr) { - if (uv_ip6_addr(interface_addr, 0, &addr6)) - return -EINVAL; - mreq.ipv6mr_interface = addr6.sin6_scope_id; - } else { - mreq.ipv6mr_interface = 0; - } - - mreq.ipv6mr_multiaddr = multicast_addr->sin6_addr; - - switch (membership) { - case UV_JOIN_GROUP: - optname = IPV6_ADD_MEMBERSHIP; - break; - case UV_LEAVE_GROUP: - optname = IPV6_DROP_MEMBERSHIP; - break; - default: - return -EINVAL; - } - - if (setsockopt(handle->io_watcher.fd, - IPPROTO_IPV6, - optname, - &mreq, - sizeof(mreq))) { - return -errno; - } - - return 0; -} - - -int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) { - uv__handle_init(loop, (uv_handle_t*)handle, UV_UDP); - handle->alloc_cb = NULL; - handle->recv_cb = NULL; - handle->send_queue_size = 0; - handle->send_queue_count = 0; - uv__io_init(&handle->io_watcher, uv__udp_io, -1); - QUEUE_INIT(&handle->write_queue); - QUEUE_INIT(&handle->write_completed_queue); - return 0; -} - - -int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) { - int err; - - /* Check for already active socket. */ - if (handle->io_watcher.fd != -1) - return -EALREADY; /* FIXME(bnoordhuis) Should be -EBUSY. */ - - err = uv__nonblock(sock, 1); - if (err) - return err; - - err = uv__set_reuse(sock); - if (err) - return err; - - handle->io_watcher.fd = sock; - return 0; -} - - -int uv_udp_set_membership(uv_udp_t* handle, - const char* multicast_addr, - const char* interface_addr, - uv_membership membership) { - int err; - struct sockaddr_in addr4; - struct sockaddr_in6 addr6; - - if (uv_ip4_addr(multicast_addr, 0, &addr4) == 0) { - err = uv__udp_maybe_deferred_bind(handle, AF_INET, UV_UDP_REUSEADDR); - if (err) - return err; - return uv__udp_set_membership4(handle, &addr4, interface_addr, membership); - } else if (uv_ip6_addr(multicast_addr, 0, &addr6) == 0) { - err = uv__udp_maybe_deferred_bind(handle, AF_INET6, UV_UDP_REUSEADDR); - if (err) - return err; - return uv__udp_set_membership6(handle, &addr6, interface_addr, membership); - } else { - return -EINVAL; - } -} - - -static int uv__setsockopt_maybe_char(uv_udp_t* handle, - int option4, - int option6, - int val) { - int r; -#if defined(__sun) || defined(_AIX) - char arg = val; -#else - int arg = val; -#endif - - if (val < 0 || val > 255) - return -EINVAL; - - if (handle->flags & UV_HANDLE_IPV6) - r = setsockopt(handle->io_watcher.fd, - IPPROTO_IPV6, - option6, - &arg, - sizeof(arg)); - else - r = setsockopt(handle->io_watcher.fd, - IPPROTO_IP, - option4, - &arg, - sizeof(arg)); - - if (r) - return -errno; - - return 0; -} - - -int uv_udp_set_broadcast(uv_udp_t* handle, int on) { - if (setsockopt(handle->io_watcher.fd, - SOL_SOCKET, - SO_BROADCAST, - &on, - sizeof(on))) { - return -errno; - } - - return 0; -} - - -int uv_udp_set_ttl(uv_udp_t* handle, int ttl) { - if (ttl < 1 || ttl > 255) - return -EINVAL; - - return uv__setsockopt_maybe_char(handle, - IP_TTL, - IPV6_UNICAST_HOPS, - ttl); -} - - -int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl) { - return uv__setsockopt_maybe_char(handle, - IP_MULTICAST_TTL, - IPV6_MULTICAST_HOPS, - ttl); -} - - -int uv_udp_set_multicast_loop(uv_udp_t* handle, int on) { - return uv__setsockopt_maybe_char(handle, - IP_MULTICAST_LOOP, - IPV6_MULTICAST_LOOP, - on); -} - -int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) { - struct sockaddr_storage addr_st; - struct sockaddr_in* addr4; - struct sockaddr_in6* addr6; - - addr4 = (struct sockaddr_in*) &addr_st; - addr6 = (struct sockaddr_in6*) &addr_st; - - if (!interface_addr) { - memset(&addr_st, 0, sizeof addr_st); - if (handle->flags & UV_HANDLE_IPV6) { - addr_st.ss_family = AF_INET6; - addr6->sin6_scope_id = 0; - } else { - addr_st.ss_family = AF_INET; - addr4->sin_addr.s_addr = htonl(INADDR_ANY); - } - } else if (uv_ip4_addr(interface_addr, 0, addr4) == 0) { - /* nothing, address was parsed */ - } else if (uv_ip6_addr(interface_addr, 0, addr6) == 0) { - /* nothing, address was parsed */ - } else { - return -EINVAL; - } - - if (addr_st.ss_family == AF_INET) { - if (setsockopt(handle->io_watcher.fd, - IPPROTO_IP, - IP_MULTICAST_IF, - (void*) &addr4->sin_addr, - sizeof(addr4->sin_addr)) == -1) { - return -errno; - } - } else if (addr_st.ss_family == AF_INET6) { - if (setsockopt(handle->io_watcher.fd, - IPPROTO_IPV6, - IPV6_MULTICAST_IF, - &addr6->sin6_scope_id, - sizeof(addr6->sin6_scope_id)) == -1) { - return -errno; - } - } else { - assert(0 && "unexpected address family"); - abort(); - } - - return 0; -} - - -int uv_udp_getsockname(const uv_udp_t* handle, - struct sockaddr* name, - int* namelen) { - socklen_t socklen; - - if (handle->io_watcher.fd == -1) - return -EINVAL; /* FIXME(bnoordhuis) -EBADF */ - - /* sizeof(socklen_t) != sizeof(int) on some systems. */ - socklen = (socklen_t) *namelen; - - if (getsockname(handle->io_watcher.fd, name, &socklen)) - return -errno; - - *namelen = (int) socklen; - return 0; -} - - -int uv__udp_recv_start(uv_udp_t* handle, - uv_alloc_cb alloc_cb, - uv_udp_recv_cb recv_cb) { - int err; - - if (alloc_cb == NULL || recv_cb == NULL) - return -EINVAL; - - if (uv__io_active(&handle->io_watcher, UV__POLLIN)) - return -EALREADY; /* FIXME(bnoordhuis) Should be -EBUSY. */ - - err = uv__udp_maybe_deferred_bind(handle, AF_INET, 0); - if (err) - return err; - - handle->alloc_cb = alloc_cb; - handle->recv_cb = recv_cb; - - uv__io_start(handle->loop, &handle->io_watcher, UV__POLLIN); - uv__handle_start(handle); - - return 0; -} - - -int uv__udp_recv_stop(uv_udp_t* handle) { - uv__io_stop(handle->loop, &handle->io_watcher, UV__POLLIN); - - if (!uv__io_active(&handle->io_watcher, UV__POLLOUT)) - uv__handle_stop(handle); - - handle->alloc_cb = NULL; - handle->recv_cb = NULL; - - return 0; -} diff --git a/libuv/src/uv-common.c b/libuv/src/uv-common.c deleted file mode 100644 index 791c09b..0000000 --- a/libuv/src/uv-common.c +++ /dev/null @@ -1,528 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "uv-common.h" - -#include -#include -#include -#include /* NULL */ -#include /* malloc */ -#include /* memset */ - -#if !defined(_WIN32) -# include /* if_nametoindex */ -#endif - -#define XX(uc, lc) case UV_##uc: return sizeof(uv_##lc##_t); - -size_t uv_handle_size(uv_handle_type type) { - switch (type) { - UV_HANDLE_TYPE_MAP(XX) - default: - return -1; - } -} - -size_t uv_req_size(uv_req_type type) { - switch(type) { - UV_REQ_TYPE_MAP(XX) - default: - return -1; - } -} - -#undef XX - - -size_t uv_loop_size(void) { - return sizeof(uv_loop_t); -} - - -uv_buf_t uv_buf_init(char* base, unsigned int len) { - uv_buf_t buf; - buf.base = base; - buf.len = len; - return buf; -} - - -#define UV_ERR_NAME_GEN(name, _) case UV_ ## name: return #name; -const char* uv_err_name(int err) { - switch (err) { - UV_ERRNO_MAP(UV_ERR_NAME_GEN) - default: - assert(0); - return NULL; - } -} -#undef UV_ERR_NAME_GEN - - -#define UV_STRERROR_GEN(name, msg) case UV_ ## name: return msg; -const char* uv_strerror(int err) { - switch (err) { - UV_ERRNO_MAP(UV_STRERROR_GEN) - default: - return "Unknown system error"; - } -} -#undef UV_STRERROR_GEN - - -int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr) { - memset(addr, 0, sizeof(*addr)); - addr->sin_family = AF_INET; - addr->sin_port = htons(port); - return uv_inet_pton(AF_INET, ip, &(addr->sin_addr.s_addr)); -} - - -int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr) { - char address_part[40]; - size_t address_part_size; - const char* zone_index; - - memset(addr, 0, sizeof(*addr)); - addr->sin6_family = AF_INET6; - addr->sin6_port = htons(port); - - zone_index = strchr(ip, '%'); - if (zone_index != NULL) { - address_part_size = zone_index - ip; - if (address_part_size >= sizeof(address_part)) - address_part_size = sizeof(address_part) - 1; - - memcpy(address_part, ip, address_part_size); - address_part[address_part_size] = '\0'; - ip = address_part; - - zone_index++; /* skip '%' */ - /* NOTE: unknown interface (id=0) is silently ignored */ -#ifdef _WIN32 - addr->sin6_scope_id = atoi(zone_index); -#else - addr->sin6_scope_id = if_nametoindex(zone_index); -#endif - } - - return uv_inet_pton(AF_INET6, ip, &addr->sin6_addr); -} - - -int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size) { - return uv_inet_ntop(AF_INET, &src->sin_addr, dst, size); -} - - -int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size) { - return uv_inet_ntop(AF_INET6, &src->sin6_addr, dst, size); -} - - -int uv_tcp_bind(uv_tcp_t* handle, - const struct sockaddr* addr, - unsigned int flags) { - unsigned int addrlen; - - if (handle->type != UV_TCP) - return UV_EINVAL; - - if (addr->sa_family == AF_INET) - addrlen = sizeof(struct sockaddr_in); - else if (addr->sa_family == AF_INET6) - addrlen = sizeof(struct sockaddr_in6); - else - return UV_EINVAL; - - return uv__tcp_bind(handle, addr, addrlen, flags); -} - - -int uv_udp_bind(uv_udp_t* handle, - const struct sockaddr* addr, - unsigned int flags) { - unsigned int addrlen; - - if (handle->type != UV_UDP) - return UV_EINVAL; - - if (addr->sa_family == AF_INET) - addrlen = sizeof(struct sockaddr_in); - else if (addr->sa_family == AF_INET6) - addrlen = sizeof(struct sockaddr_in6); - else - return UV_EINVAL; - - return uv__udp_bind(handle, addr, addrlen, flags); -} - - -int uv_tcp_connect(uv_connect_t* req, - uv_tcp_t* handle, - const struct sockaddr* addr, - uv_connect_cb cb) { - unsigned int addrlen; - - if (handle->type != UV_TCP) - return UV_EINVAL; - - if (addr->sa_family == AF_INET) - addrlen = sizeof(struct sockaddr_in); - else if (addr->sa_family == AF_INET6) - addrlen = sizeof(struct sockaddr_in6); - else - return UV_EINVAL; - - return uv__tcp_connect(req, handle, addr, addrlen, cb); -} - - -int uv_udp_send(uv_udp_send_t* req, - uv_udp_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - const struct sockaddr* addr, - uv_udp_send_cb send_cb) { - unsigned int addrlen; - - if (handle->type != UV_UDP) - return UV_EINVAL; - - if (addr->sa_family == AF_INET) - addrlen = sizeof(struct sockaddr_in); - else if (addr->sa_family == AF_INET6) - addrlen = sizeof(struct sockaddr_in6); - else - return UV_EINVAL; - - return uv__udp_send(req, handle, bufs, nbufs, addr, addrlen, send_cb); -} - - -int uv_udp_try_send(uv_udp_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - const struct sockaddr* addr) { - unsigned int addrlen; - - if (handle->type != UV_UDP) - return UV_EINVAL; - - if (addr->sa_family == AF_INET) - addrlen = sizeof(struct sockaddr_in); - else if (addr->sa_family == AF_INET6) - addrlen = sizeof(struct sockaddr_in6); - else - return UV_EINVAL; - - return uv__udp_try_send(handle, bufs, nbufs, addr, addrlen); -} - - -int uv_udp_recv_start(uv_udp_t* handle, - uv_alloc_cb alloc_cb, - uv_udp_recv_cb recv_cb) { - if (handle->type != UV_UDP || alloc_cb == NULL || recv_cb == NULL) - return UV_EINVAL; - else - return uv__udp_recv_start(handle, alloc_cb, recv_cb); -} - - -int uv_udp_recv_stop(uv_udp_t* handle) { - if (handle->type != UV_UDP) - return UV_EINVAL; - else - return uv__udp_recv_stop(handle); -} - - -void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) { - QUEUE* q; - uv_handle_t* h; - - QUEUE_FOREACH(q, &loop->handle_queue) { - h = QUEUE_DATA(q, uv_handle_t, handle_queue); - if (h->flags & UV__HANDLE_INTERNAL) continue; - walk_cb(h, arg); - } -} - - -#ifndef NDEBUG -static void uv__print_handles(uv_loop_t* loop, int only_active) { - const char* type; - QUEUE* q; - uv_handle_t* h; - - if (loop == NULL) - loop = uv_default_loop(); - - QUEUE_FOREACH(q, &loop->handle_queue) { - h = QUEUE_DATA(q, uv_handle_t, handle_queue); - - if (only_active && !uv__is_active(h)) - continue; - - switch (h->type) { -#define X(uc, lc) case UV_##uc: type = #lc; break; - UV_HANDLE_TYPE_MAP(X) -#undef X - default: type = ""; - } - - fprintf(stderr, - "[%c%c%c] %-8s %p\n", - "R-"[!(h->flags & UV__HANDLE_REF)], - "A-"[!(h->flags & UV__HANDLE_ACTIVE)], - "I-"[!(h->flags & UV__HANDLE_INTERNAL)], - type, - (void*)h); - } -} - - -void uv_print_all_handles(uv_loop_t* loop) { - uv__print_handles(loop, 0); -} - - -void uv_print_active_handles(uv_loop_t* loop) { - uv__print_handles(loop, 1); -} -#endif - - -void uv_ref(uv_handle_t* handle) { - uv__handle_ref(handle); -} - - -void uv_unref(uv_handle_t* handle) { - uv__handle_unref(handle); -} - - -int uv_has_ref(const uv_handle_t* handle) { - return uv__has_ref(handle); -} - - -void uv_stop(uv_loop_t* loop) { - loop->stop_flag = 1; -} - - -uint64_t uv_now(const uv_loop_t* loop) { - return loop->time; -} - - - -size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs) { - unsigned int i; - size_t bytes; - - bytes = 0; - for (i = 0; i < nbufs; i++) - bytes += (size_t) bufs[i].len; - - return bytes; -} - -int uv_recv_buffer_size(uv_handle_t* handle, int* value) { - return uv__socket_sockopt(handle, SO_RCVBUF, value); -} - -int uv_send_buffer_size(uv_handle_t* handle, int *value) { - return uv__socket_sockopt(handle, SO_SNDBUF, value); -} - -int uv_fs_event_getpath(uv_fs_event_t* handle, char* buffer, size_t* size) { - size_t required_len; - - if (!uv__is_active(handle)) { - *size = 0; - return UV_EINVAL; - } - - required_len = strlen(handle->path); - if (required_len > *size) { - *size = required_len; - return UV_ENOBUFS; - } - - memcpy(buffer, handle->path, required_len); - *size = required_len; - - return 0; -} - - -void uv__fs_scandir_cleanup(uv_fs_t* req) { - uv__dirent_t** dents; - - dents = req->ptr; - if (req->nbufs > 0 && req->nbufs != (unsigned int) req->result) - req->nbufs--; - for (; req->nbufs < (unsigned int) req->result; req->nbufs++) - free(dents[req->nbufs]); -} - - -int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) { - uv__dirent_t** dents; - uv__dirent_t* dent; - - dents = req->ptr; - - /* Free previous entity */ - if (req->nbufs > 0) - free(dents[req->nbufs - 1]); - - /* End was already reached */ - if (req->nbufs == (unsigned int) req->result) { - free(dents); - req->ptr = NULL; - return UV_EOF; - } - - dent = dents[req->nbufs++]; - - ent->name = dent->d_name; -#ifdef HAVE_DIRENT_TYPES - switch (dent->d_type) { - case UV__DT_DIR: - ent->type = UV_DIRENT_DIR; - break; - case UV__DT_FILE: - ent->type = UV_DIRENT_FILE; - break; - case UV__DT_LINK: - ent->type = UV_DIRENT_LINK; - break; - case UV__DT_FIFO: - ent->type = UV_DIRENT_FIFO; - break; - case UV__DT_SOCKET: - ent->type = UV_DIRENT_SOCKET; - break; - case UV__DT_CHAR: - ent->type = UV_DIRENT_CHAR; - break; - case UV__DT_BLOCK: - ent->type = UV_DIRENT_BLOCK; - break; - default: - ent->type = UV_DIRENT_UNKNOWN; - } -#else - ent->type = UV_DIRENT_UNKNOWN; -#endif - - return 0; -} - - -int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...) { - va_list ap; - int err; - - va_start(ap, option); - /* Any platform-agnostic options should be handled here. */ - err = uv__loop_configure(loop, option, ap); - va_end(ap); - - return err; -} - - -static uv_loop_t default_loop_struct; -static uv_loop_t* default_loop_ptr; - - -uv_loop_t* uv_default_loop(void) { - if (default_loop_ptr != NULL) - return default_loop_ptr; - - if (uv_loop_init(&default_loop_struct)) - return NULL; - - default_loop_ptr = &default_loop_struct; - return default_loop_ptr; -} - - -uv_loop_t* uv_loop_new(void) { - uv_loop_t* loop; - - loop = malloc(sizeof(*loop)); - if (loop == NULL) - return NULL; - - if (uv_loop_init(loop)) { - free(loop); - return NULL; - } - - return loop; -} - - -int uv_loop_close(uv_loop_t* loop) { - QUEUE* q; - uv_handle_t* h; - - if (!QUEUE_EMPTY(&(loop)->active_reqs)) - return UV_EBUSY; - - QUEUE_FOREACH(q, &loop->handle_queue) { - h = QUEUE_DATA(q, uv_handle_t, handle_queue); - if (!(h->flags & UV__HANDLE_INTERNAL)) - return UV_EBUSY; - } - - uv__loop_close(loop); - -#ifndef NDEBUG - memset(loop, -1, sizeof(*loop)); -#endif - if (loop == default_loop_ptr) - default_loop_ptr = NULL; - - return 0; -} - - -void uv_loop_delete(uv_loop_t* loop) { - uv_loop_t* default_loop; - int err; - - default_loop = default_loop_ptr; - - err = uv_loop_close(loop); - assert(err == 0); - if (loop != default_loop) - free(loop); -} diff --git a/libuv/src/uv-common.h b/libuv/src/uv-common.h deleted file mode 100644 index 463caba..0000000 --- a/libuv/src/uv-common.h +++ /dev/null @@ -1,214 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* - * This file is private to libuv. It provides common functionality to both - * Windows and Unix backends. - */ - -#ifndef UV_COMMON_H_ -#define UV_COMMON_H_ - -#include -#include -#include - -#if defined(_MSC_VER) && _MSC_VER < 1600 -# include "stdint-msvc2008.h" -#else -# include -#endif - -#include "uv.h" -#include "tree.h" -#include "queue.h" - -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) - -#define container_of(ptr, type, member) \ - ((type *) ((char *) (ptr) - offsetof(type, member))) - -#define STATIC_ASSERT(expr) \ - void uv__static_assert(int static_assert_failed[1 - 2 * !(expr)]) - -#ifndef _WIN32 -enum { - UV__HANDLE_INTERNAL = 0x8000, - UV__HANDLE_ACTIVE = 0x4000, - UV__HANDLE_REF = 0x2000, - UV__HANDLE_CLOSING = 0 /* no-op on unix */ -}; -#else -# define UV__HANDLE_INTERNAL 0x80 -# define UV__HANDLE_ACTIVE 0x40 -# define UV__HANDLE_REF 0x20 -# define UV__HANDLE_CLOSING 0x01 -#endif - -int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap); - -void uv__loop_close(uv_loop_t* loop); - -int uv__tcp_bind(uv_tcp_t* tcp, - const struct sockaddr* addr, - unsigned int addrlen, - unsigned int flags); - -int uv__tcp_connect(uv_connect_t* req, - uv_tcp_t* handle, - const struct sockaddr* addr, - unsigned int addrlen, - uv_connect_cb cb); - -int uv__udp_bind(uv_udp_t* handle, - const struct sockaddr* addr, - unsigned int addrlen, - unsigned int flags); - -int uv__udp_send(uv_udp_send_t* req, - uv_udp_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - const struct sockaddr* addr, - unsigned int addrlen, - uv_udp_send_cb send_cb); - -int uv__udp_try_send(uv_udp_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - const struct sockaddr* addr, - unsigned int addrlen); - -int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloccb, - uv_udp_recv_cb recv_cb); - -int uv__udp_recv_stop(uv_udp_t* handle); - -void uv__fs_poll_close(uv_fs_poll_t* handle); - -int uv__getaddrinfo_translate_error(int sys_err); /* EAI_* error. */ - -void uv__work_submit(uv_loop_t* loop, - struct uv__work *w, - void (*work)(struct uv__work *w), - void (*done)(struct uv__work *w, int status)); - -void uv__work_done(uv_async_t* handle); - -size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs); - -int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value); - -void uv__fs_scandir_cleanup(uv_fs_t* req); - -#define uv__has_active_reqs(loop) \ - (QUEUE_EMPTY(&(loop)->active_reqs) == 0) - -#define uv__req_register(loop, req) \ - do { \ - QUEUE_INSERT_TAIL(&(loop)->active_reqs, &(req)->active_queue); \ - } \ - while (0) - -#define uv__req_unregister(loop, req) \ - do { \ - assert(uv__has_active_reqs(loop)); \ - QUEUE_REMOVE(&(req)->active_queue); \ - } \ - while (0) - -#define uv__has_active_handles(loop) \ - ((loop)->active_handles > 0) - -#define uv__active_handle_add(h) \ - do { \ - (h)->loop->active_handles++; \ - } \ - while (0) - -#define uv__active_handle_rm(h) \ - do { \ - (h)->loop->active_handles--; \ - } \ - while (0) - -#define uv__is_active(h) \ - (((h)->flags & UV__HANDLE_ACTIVE) != 0) - -#define uv__is_closing(h) \ - (((h)->flags & (UV_CLOSING | UV_CLOSED)) != 0) - -#define uv__handle_start(h) \ - do { \ - assert(((h)->flags & UV__HANDLE_CLOSING) == 0); \ - if (((h)->flags & UV__HANDLE_ACTIVE) != 0) break; \ - (h)->flags |= UV__HANDLE_ACTIVE; \ - if (((h)->flags & UV__HANDLE_REF) != 0) uv__active_handle_add(h); \ - } \ - while (0) - -#define uv__handle_stop(h) \ - do { \ - assert(((h)->flags & UV__HANDLE_CLOSING) == 0); \ - if (((h)->flags & UV__HANDLE_ACTIVE) == 0) break; \ - (h)->flags &= ~UV__HANDLE_ACTIVE; \ - if (((h)->flags & UV__HANDLE_REF) != 0) uv__active_handle_rm(h); \ - } \ - while (0) - -#define uv__handle_ref(h) \ - do { \ - if (((h)->flags & UV__HANDLE_REF) != 0) break; \ - (h)->flags |= UV__HANDLE_REF; \ - if (((h)->flags & UV__HANDLE_CLOSING) != 0) break; \ - if (((h)->flags & UV__HANDLE_ACTIVE) != 0) uv__active_handle_add(h); \ - } \ - while (0) - -#define uv__handle_unref(h) \ - do { \ - if (((h)->flags & UV__HANDLE_REF) == 0) break; \ - (h)->flags &= ~UV__HANDLE_REF; \ - if (((h)->flags & UV__HANDLE_CLOSING) != 0) break; \ - if (((h)->flags & UV__HANDLE_ACTIVE) != 0) uv__active_handle_rm(h); \ - } \ - while (0) - -#define uv__has_ref(h) \ - (((h)->flags & UV__HANDLE_REF) != 0) - -#if defined(_WIN32) -# define uv__handle_platform_init(h) -#else -# define uv__handle_platform_init(h) ((h)->next_closing = NULL) -#endif - -#define uv__handle_init(loop_, h, type_) \ - do { \ - (h)->loop = (loop_); \ - (h)->type = (type_); \ - (h)->flags = UV__HANDLE_REF; /* Ref the loop when active. */ \ - QUEUE_INSERT_TAIL(&(loop_)->handle_queue, &(h)->handle_queue); \ - uv__handle_platform_init(h); \ - } \ - while (0) - -#endif /* UV_COMMON_H_ */ diff --git a/libuv/src/version.c b/libuv/src/version.c deleted file mode 100644 index ff91a46..0000000 --- a/libuv/src/version.c +++ /dev/null @@ -1,49 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" - -#define UV_VERSION ((UV_VERSION_MAJOR << 16) | \ - (UV_VERSION_MINOR << 8) | \ - (UV_VERSION_PATCH)) - -#define UV_STRINGIFY(v) UV_STRINGIFY_HELPER(v) -#define UV_STRINGIFY_HELPER(v) #v - -#define UV_VERSION_STRING_BASE UV_STRINGIFY(UV_VERSION_MAJOR) "." \ - UV_STRINGIFY(UV_VERSION_MINOR) "." \ - UV_STRINGIFY(UV_VERSION_PATCH) - -#if UV_VERSION_IS_RELEASE -# define UV_VERSION_STRING UV_VERSION_STRING_BASE -#else -# define UV_VERSION_STRING UV_VERSION_STRING_BASE "-" UV_VERSION_SUFFIX -#endif - - -unsigned int uv_version(void) { - return UV_VERSION; -} - - -const char* uv_version_string(void) { - return UV_VERSION_STRING; -} diff --git a/libuv/src/win/async.c b/libuv/src/win/async.c deleted file mode 100644 index ad240ab..0000000 --- a/libuv/src/win/async.c +++ /dev/null @@ -1,99 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include - -#include "uv.h" -#include "internal.h" -#include "atomicops-inl.h" -#include "handle-inl.h" -#include "req-inl.h" - - -void uv_async_endgame(uv_loop_t* loop, uv_async_t* handle) { - if (handle->flags & UV__HANDLE_CLOSING && - !handle->async_sent) { - assert(!(handle->flags & UV_HANDLE_CLOSED)); - uv__handle_close(handle); - } -} - - -int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) { - uv_req_t* req; - - uv__handle_init(loop, (uv_handle_t*) handle, UV_ASYNC); - handle->async_sent = 0; - handle->async_cb = async_cb; - - req = &handle->async_req; - uv_req_init(loop, req); - req->type = UV_WAKEUP; - req->data = handle; - - uv__handle_start(handle); - - return 0; -} - - -void uv_async_close(uv_loop_t* loop, uv_async_t* handle) { - if (!((uv_async_t*)handle)->async_sent) { - uv_want_endgame(loop, (uv_handle_t*) handle); - } - - uv__handle_closing(handle); -} - - -int uv_async_send(uv_async_t* handle) { - uv_loop_t* loop = handle->loop; - - if (handle->type != UV_ASYNC) { - /* Can't set errno because that's not thread-safe. */ - return -1; - } - - /* The user should make sure never to call uv_async_send to a closing */ - /* or closed handle. */ - assert(!(handle->flags & UV__HANDLE_CLOSING)); - - if (!uv__atomic_exchange_set(&handle->async_sent)) { - POST_COMPLETION_FOR_REQ(loop, &handle->async_req); - } - - return 0; -} - - -void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle, - uv_req_t* req) { - assert(handle->type == UV_ASYNC); - assert(req->type == UV_WAKEUP); - - handle->async_sent = 0; - - if (handle->flags & UV__HANDLE_CLOSING) { - uv_want_endgame(loop, (uv_handle_t*)handle); - } else if (handle->async_cb != NULL) { - handle->async_cb(handle); - } -} diff --git a/libuv/src/win/atomicops-inl.h b/libuv/src/win/atomicops-inl.h deleted file mode 100644 index 61e0060..0000000 --- a/libuv/src/win/atomicops-inl.h +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_WIN_ATOMICOPS_INL_H_ -#define UV_WIN_ATOMICOPS_INL_H_ - -#include "uv.h" - - -/* Atomic set operation on char */ -#ifdef _MSC_VER /* MSVC */ - -/* _InterlockedOr8 is supported by MSVC on x32 and x64. It is slightly less */ -/* efficient than InterlockedExchange, but InterlockedExchange8 does not */ -/* exist, and interlocked operations on larger targets might require the */ -/* target to be aligned. */ -#pragma intrinsic(_InterlockedOr8) - -static char __declspec(inline) uv__atomic_exchange_set(char volatile* target) { - return _InterlockedOr8(target, 1); -} - -#else /* GCC */ - -/* Mingw-32 version, hopefully this works for 64-bit gcc as well. */ -static inline char uv__atomic_exchange_set(char volatile* target) { - const char one = 1; - char old_value; - __asm__ __volatile__ ("lock xchgb %0, %1\n\t" - : "=r"(old_value), "=m"(*target) - : "0"(one), "m"(*target) - : "memory"); - return old_value; -} - -#endif - -#endif /* UV_WIN_ATOMICOPS_INL_H_ */ diff --git a/libuv/src/win/core.c b/libuv/src/win/core.c deleted file mode 100644 index a101159..0000000 --- a/libuv/src/win/core.c +++ /dev/null @@ -1,445 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR) -#include -#endif - -#include "uv.h" -#include "internal.h" -#include "handle-inl.h" -#include "req-inl.h" - - -static uv_loop_t default_loop_struct; -static uv_loop_t* default_loop_ptr; - -/* uv_once initialization guards */ -static uv_once_t uv_init_guard_ = UV_ONCE_INIT; - - -#if defined(_DEBUG) && (defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR)) -/* Our crt debug report handler allows us to temporarily disable asserts - * just for the current thread. - */ - -UV_THREAD_LOCAL int uv__crt_assert_enabled = TRUE; - -static int uv__crt_dbg_report_handler(int report_type, char *message, int *ret_val) { - if (uv__crt_assert_enabled || report_type != _CRT_ASSERT) - return FALSE; - - if (ret_val) { - /* Set ret_val to 0 to continue with normal execution. - * Set ret_val to 1 to trigger a breakpoint. - */ - - if(IsDebuggerPresent()) - *ret_val = 1; - else - *ret_val = 0; - } - - /* Don't call _CrtDbgReport. */ - return TRUE; -} -#else -UV_THREAD_LOCAL int uv__crt_assert_enabled = FALSE; -#endif - - -#if !defined(__MINGW32__) || __MSVCRT_VERSION__ >= 0x800 -static void uv__crt_invalid_parameter_handler(const wchar_t* expression, - const wchar_t* function, const wchar_t * file, unsigned int line, - uintptr_t reserved) { - /* No-op. */ -} -#endif - - -static void uv_init(void) { - /* Tell Windows that we will handle critical errors. */ - SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | - SEM_NOOPENFILEERRORBOX); - - /* Tell the CRT to not exit the application when an invalid parameter is - * passed. The main issue is that invalid FDs will trigger this behavior. - */ -#if !defined(__MINGW32__) || __MSVCRT_VERSION__ >= 0x800 - _set_invalid_parameter_handler(uv__crt_invalid_parameter_handler); -#endif - - /* We also need to setup our debug report handler because some CRT - * functions (eg _get_osfhandle) raise an assert when called with invalid - * FDs even though they return the proper error code in the release build. - */ -#if defined(_DEBUG) && (defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR)) - _CrtSetReportHook(uv__crt_dbg_report_handler); -#endif - - /* Fetch winapi function pointers. This must be done first because other - * initialization code might need these function pointers to be loaded. - */ - uv_winapi_init(); - - /* Initialize winsock */ - uv_winsock_init(); - - /* Initialize FS */ - uv_fs_init(); - - /* Initialize signal stuff */ - uv_signals_init(); - - /* Initialize console */ - uv_console_init(); - - /* Initialize utilities */ - uv__util_init(); -} - - -int uv_loop_init(uv_loop_t* loop) { - /* Initialize libuv itself first */ - uv__once_init(); - - /* Create an I/O completion port */ - loop->iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1); - if (loop->iocp == NULL) - return uv_translate_sys_error(GetLastError()); - - /* To prevent uninitialized memory access, loop->time must be initialized - * to zero before calling uv_update_time for the first time. - */ - loop->time = 0; - uv_update_time(loop); - - QUEUE_INIT(&loop->wq); - QUEUE_INIT(&loop->handle_queue); - QUEUE_INIT(&loop->active_reqs); - loop->active_handles = 0; - - loop->pending_reqs_tail = NULL; - - loop->endgame_handles = NULL; - - RB_INIT(&loop->timers); - - loop->check_handles = NULL; - loop->prepare_handles = NULL; - loop->idle_handles = NULL; - - loop->next_prepare_handle = NULL; - loop->next_check_handle = NULL; - loop->next_idle_handle = NULL; - - memset(&loop->poll_peer_sockets, 0, sizeof loop->poll_peer_sockets); - - loop->active_tcp_streams = 0; - loop->active_udp_streams = 0; - - loop->timer_counter = 0; - loop->stop_flag = 0; - - if (uv_mutex_init(&loop->wq_mutex)) - abort(); - - if (uv_async_init(loop, &loop->wq_async, uv__work_done)) - abort(); - - uv__handle_unref(&loop->wq_async); - loop->wq_async.flags |= UV__HANDLE_INTERNAL; - - return 0; -} - - -void uv__once_init(void) { - uv_once(&uv_init_guard_, uv_init); -} - - -void uv__loop_close(uv_loop_t* loop) { - size_t i; - - /* close the async handle without needing an extra loop iteration */ - assert(!loop->wq_async.async_sent); - loop->wq_async.close_cb = NULL; - uv__handle_closing(&loop->wq_async); - uv__handle_close(&loop->wq_async); - - for (i = 0; i < ARRAY_SIZE(loop->poll_peer_sockets); i++) { - SOCKET sock = loop->poll_peer_sockets[i]; - if (sock != 0 && sock != INVALID_SOCKET) - closesocket(sock); - } - - uv_mutex_lock(&loop->wq_mutex); - assert(QUEUE_EMPTY(&loop->wq) && "thread pool work queue not empty!"); - assert(!uv__has_active_reqs(loop)); - uv_mutex_unlock(&loop->wq_mutex); - uv_mutex_destroy(&loop->wq_mutex); - - CloseHandle(loop->iocp); -} - - -int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap) { - return UV_ENOSYS; -} - - -int uv_backend_fd(const uv_loop_t* loop) { - return -1; -} - - -int uv_backend_timeout(const uv_loop_t* loop) { - if (loop->stop_flag != 0) - return 0; - - if (!uv__has_active_handles(loop) && !uv__has_active_reqs(loop)) - return 0; - - if (loop->pending_reqs_tail) - return 0; - - if (loop->endgame_handles) - return 0; - - if (loop->idle_handles) - return 0; - - return uv__next_timeout(loop); -} - - -static void uv_poll(uv_loop_t* loop, DWORD timeout) { - DWORD bytes; - ULONG_PTR key; - OVERLAPPED* overlapped; - uv_req_t* req; - - GetQueuedCompletionStatus(loop->iocp, - &bytes, - &key, - &overlapped, - timeout); - - if (overlapped) { - /* Package was dequeued */ - req = uv_overlapped_to_req(overlapped); - uv_insert_pending_req(loop, req); - - /* Some time might have passed waiting for I/O, - * so update the loop time here. - */ - uv_update_time(loop); - } else if (GetLastError() != WAIT_TIMEOUT) { - /* Serious error */ - uv_fatal_error(GetLastError(), "GetQueuedCompletionStatus"); - } else if (timeout > 0) { - /* GetQueuedCompletionStatus can occasionally return a little early. - * Make sure that the desired timeout is reflected in the loop time. - */ - uv__time_forward(loop, timeout); - } -} - - -static void uv_poll_ex(uv_loop_t* loop, DWORD timeout) { - BOOL success; - uv_req_t* req; - OVERLAPPED_ENTRY overlappeds[128]; - ULONG count; - ULONG i; - - success = pGetQueuedCompletionStatusEx(loop->iocp, - overlappeds, - ARRAY_SIZE(overlappeds), - &count, - timeout, - FALSE); - - if (success) { - for (i = 0; i < count; i++) { - /* Package was dequeued */ - req = uv_overlapped_to_req(overlappeds[i].lpOverlapped); - uv_insert_pending_req(loop, req); - } - - /* Some time might have passed waiting for I/O, - * so update the loop time here. - */ - uv_update_time(loop); - } else if (GetLastError() != WAIT_TIMEOUT) { - /* Serious error */ - uv_fatal_error(GetLastError(), "GetQueuedCompletionStatusEx"); - } else if (timeout > 0) { - /* GetQueuedCompletionStatus can occasionally return a little early. - * Make sure that the desired timeout is reflected in the loop time. - */ - uv__time_forward(loop, timeout); - } -} - - -static int uv__loop_alive(const uv_loop_t* loop) { - return loop->active_handles > 0 || - !QUEUE_EMPTY(&loop->active_reqs) || - loop->endgame_handles != NULL; -} - - -int uv_loop_alive(const uv_loop_t* loop) { - return uv__loop_alive(loop); -} - - -int uv_run(uv_loop_t *loop, uv_run_mode mode) { - DWORD timeout; - int r; - int ran_pending; - void (*poll)(uv_loop_t* loop, DWORD timeout); - - if (pGetQueuedCompletionStatusEx) - poll = &uv_poll_ex; - else - poll = &uv_poll; - - r = uv__loop_alive(loop); - if (!r) - uv_update_time(loop); - - while (r != 0 && loop->stop_flag == 0) { - uv_update_time(loop); - uv_process_timers(loop); - - ran_pending = uv_process_reqs(loop); - uv_idle_invoke(loop); - uv_prepare_invoke(loop); - - timeout = 0; - if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT) - timeout = uv_backend_timeout(loop); - - (*poll)(loop, timeout); - - uv_check_invoke(loop); - uv_process_endgames(loop); - - if (mode == UV_RUN_ONCE) { - /* UV_RUN_ONCE implies forward progress: at least one callback must have - * been invoked when it returns. uv__io_poll() can return without doing - * I/O (meaning: no callbacks) when its timeout expires - which means we - * have pending timers that satisfy the forward progress constraint. - * - * UV_RUN_NOWAIT makes no guarantees about progress so it's omitted from - * the check. - */ - uv_process_timers(loop); - } - - r = uv__loop_alive(loop); - if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT) - break; - } - - /* The if statement lets the compiler compile it to a conditional store. - * Avoids dirtying a cache line. - */ - if (loop->stop_flag != 0) - loop->stop_flag = 0; - - return r; -} - - -int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd) { - uv_os_fd_t fd_out; - - switch (handle->type) { - case UV_TCP: - fd_out = (uv_os_fd_t)((uv_tcp_t*) handle)->socket; - break; - - case UV_NAMED_PIPE: - fd_out = ((uv_pipe_t*) handle)->handle; - break; - - case UV_TTY: - fd_out = ((uv_tty_t*) handle)->handle; - break; - - case UV_UDP: - fd_out = (uv_os_fd_t)((uv_udp_t*) handle)->socket; - break; - - case UV_POLL: - fd_out = (uv_os_fd_t)((uv_poll_t*) handle)->socket; - break; - - default: - return UV_EINVAL; - } - - if (uv_is_closing(handle) || fd_out == INVALID_HANDLE_VALUE) - return UV_EBADF; - - *fd = fd_out; - return 0; -} - - -int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) { - int r; - int len; - SOCKET socket; - - if (handle == NULL || value == NULL) - return UV_EINVAL; - - if (handle->type == UV_TCP) - socket = ((uv_tcp_t*) handle)->socket; - else if (handle->type == UV_UDP) - socket = ((uv_udp_t*) handle)->socket; - else - return UV_ENOTSUP; - - len = sizeof(*value); - - if (*value == 0) - r = getsockopt(socket, SOL_SOCKET, optname, (char*) value, &len); - else - r = setsockopt(socket, SOL_SOCKET, optname, (const char*) value, len); - - if (r == SOCKET_ERROR) - return uv_translate_sys_error(WSAGetLastError()); - - return 0; -} diff --git a/libuv/src/win/dl.c b/libuv/src/win/dl.c deleted file mode 100644 index e5f3407..0000000 --- a/libuv/src/win/dl.c +++ /dev/null @@ -1,113 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "internal.h" - -static int uv__dlerror(uv_lib_t* lib, int errorno); - - -int uv_dlopen(const char* filename, uv_lib_t* lib) { - WCHAR filename_w[32768]; - - lib->handle = NULL; - lib->errmsg = NULL; - - if (!uv_utf8_to_utf16(filename, filename_w, ARRAY_SIZE(filename_w))) { - return uv__dlerror(lib, GetLastError()); - } - - lib->handle = LoadLibraryExW(filename_w, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); - if (lib->handle == NULL) { - return uv__dlerror(lib, GetLastError()); - } - - return 0; -} - - -void uv_dlclose(uv_lib_t* lib) { - if (lib->errmsg) { - LocalFree((void*)lib->errmsg); - lib->errmsg = NULL; - } - - if (lib->handle) { - /* Ignore errors. No good way to signal them without leaking memory. */ - FreeLibrary(lib->handle); - lib->handle = NULL; - } -} - - -int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr) { - *ptr = (void*) GetProcAddress(lib->handle, name); - return uv__dlerror(lib, *ptr ? 0 : GetLastError()); -} - - -const char* uv_dlerror(const uv_lib_t* lib) { - return lib->errmsg ? lib->errmsg : "no error"; -} - - -static void uv__format_fallback_error(uv_lib_t* lib, int errorno){ - DWORD_PTR args[1] = { (DWORD_PTR) errorno }; - LPSTR fallback_error = "error: %1!d!"; - - FormatMessageA(FORMAT_MESSAGE_FROM_STRING | - FORMAT_MESSAGE_ARGUMENT_ARRAY | - FORMAT_MESSAGE_ALLOCATE_BUFFER, - fallback_error, 0, 0, - (LPSTR) &lib->errmsg, - 0, (va_list*) args); -} - - - -static int uv__dlerror(uv_lib_t* lib, int errorno) { - DWORD res; - - if (lib->errmsg) { - LocalFree((void*)lib->errmsg); - lib->errmsg = NULL; - } - - if (errorno) { - res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno, - MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), - (LPSTR) &lib->errmsg, 0, NULL); - if (!res && GetLastError() == ERROR_MUI_FILE_NOT_FOUND) { - res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno, - 0, (LPSTR) &lib->errmsg, 0, NULL); - } - - if (!res) { - uv__format_fallback_error(lib, errorno); - } - } - - return errorno ? -1 : 0; -} diff --git a/libuv/src/win/error.c b/libuv/src/win/error.c deleted file mode 100644 index 5c55147..0000000 --- a/libuv/src/win/error.c +++ /dev/null @@ -1,170 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include - -#include "uv.h" -#include "internal.h" - - -/* - * Display an error message and abort the event loop. - */ -void uv_fatal_error(const int errorno, const char* syscall) { - char* buf = NULL; - const char* errmsg; - - FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&buf, 0, NULL); - - if (buf) { - errmsg = buf; - } else { - errmsg = "Unknown error"; - } - - /* FormatMessage messages include a newline character already, */ - /* so don't add another. */ - if (syscall) { - fprintf(stderr, "%s: (%d) %s", syscall, errorno, errmsg); - } else { - fprintf(stderr, "(%d) %s", errorno, errmsg); - } - - if (buf) { - LocalFree(buf); - } - - *((char*)NULL) = 0xff; /* Force debug break */ - abort(); -} - - -int uv_translate_sys_error(int sys_errno) { - if (sys_errno <= 0) { - return sys_errno; /* If < 0 then it's already a libuv error. */ - } - - switch (sys_errno) { - case ERROR_NOACCESS: return UV_EACCES; - case WSAEACCES: return UV_EACCES; - case ERROR_ADDRESS_ALREADY_ASSOCIATED: return UV_EADDRINUSE; - case WSAEADDRINUSE: return UV_EADDRINUSE; - case WSAEADDRNOTAVAIL: return UV_EADDRNOTAVAIL; - case WSAEAFNOSUPPORT: return UV_EAFNOSUPPORT; - case WSAEWOULDBLOCK: return UV_EAGAIN; - case WSAEALREADY: return UV_EALREADY; - case ERROR_INVALID_FLAGS: return UV_EBADF; - case ERROR_INVALID_HANDLE: return UV_EBADF; - case ERROR_LOCK_VIOLATION: return UV_EBUSY; - case ERROR_PIPE_BUSY: return UV_EBUSY; - case ERROR_SHARING_VIOLATION: return UV_EBUSY; - case ERROR_OPERATION_ABORTED: return UV_ECANCELED; - case WSAEINTR: return UV_ECANCELED; - case ERROR_NO_UNICODE_TRANSLATION: return UV_ECHARSET; - case ERROR_CONNECTION_ABORTED: return UV_ECONNABORTED; - case WSAECONNABORTED: return UV_ECONNABORTED; - case ERROR_CONNECTION_REFUSED: return UV_ECONNREFUSED; - case WSAECONNREFUSED: return UV_ECONNREFUSED; - case ERROR_NETNAME_DELETED: return UV_ECONNRESET; - case WSAECONNRESET: return UV_ECONNRESET; - case ERROR_ALREADY_EXISTS: return UV_EEXIST; - case ERROR_FILE_EXISTS: return UV_EEXIST; - case ERROR_BUFFER_OVERFLOW: return UV_EFAULT; - case WSAEFAULT: return UV_EFAULT; - case ERROR_HOST_UNREACHABLE: return UV_EHOSTUNREACH; - case WSAEHOSTUNREACH: return UV_EHOSTUNREACH; - case ERROR_INSUFFICIENT_BUFFER: return UV_EINVAL; - case ERROR_INVALID_DATA: return UV_EINVAL; - case ERROR_INVALID_PARAMETER: return UV_EINVAL; - case ERROR_SYMLINK_NOT_SUPPORTED: return UV_EINVAL; - case WSAEINVAL: return UV_EINVAL; - case WSAEPFNOSUPPORT: return UV_EINVAL; - case WSAESOCKTNOSUPPORT: return UV_EINVAL; - case ERROR_BEGINNING_OF_MEDIA: return UV_EIO; - case ERROR_BUS_RESET: return UV_EIO; - case ERROR_CRC: return UV_EIO; - case ERROR_DEVICE_DOOR_OPEN: return UV_EIO; - case ERROR_DEVICE_REQUIRES_CLEANING: return UV_EIO; - case ERROR_DISK_CORRUPT: return UV_EIO; - case ERROR_EOM_OVERFLOW: return UV_EIO; - case ERROR_FILEMARK_DETECTED: return UV_EIO; - case ERROR_GEN_FAILURE: return UV_EIO; - case ERROR_INVALID_BLOCK_LENGTH: return UV_EIO; - case ERROR_IO_DEVICE: return UV_EIO; - case ERROR_NO_DATA_DETECTED: return UV_EIO; - case ERROR_NO_SIGNAL_SENT: return UV_EIO; - case ERROR_OPEN_FAILED: return UV_EIO; - case ERROR_SETMARK_DETECTED: return UV_EIO; - case ERROR_SIGNAL_REFUSED: return UV_EIO; - case WSAEISCONN: return UV_EISCONN; - case ERROR_CANT_RESOLVE_FILENAME: return UV_ELOOP; - case ERROR_TOO_MANY_OPEN_FILES: return UV_EMFILE; - case WSAEMFILE: return UV_EMFILE; - case WSAEMSGSIZE: return UV_EMSGSIZE; - case ERROR_FILENAME_EXCED_RANGE: return UV_ENAMETOOLONG; - case ERROR_NETWORK_UNREACHABLE: return UV_ENETUNREACH; - case WSAENETUNREACH: return UV_ENETUNREACH; - case WSAENOBUFS: return UV_ENOBUFS; - case ERROR_DIRECTORY: return UV_ENOENT; - case ERROR_FILE_NOT_FOUND: return UV_ENOENT; - case ERROR_INVALID_NAME: return UV_ENOENT; - case ERROR_INVALID_DRIVE: return UV_ENOENT; - case ERROR_INVALID_REPARSE_DATA: return UV_ENOENT; - case ERROR_MOD_NOT_FOUND: return UV_ENOENT; - case ERROR_PATH_NOT_FOUND: return UV_ENOENT; - case WSAHOST_NOT_FOUND: return UV_ENOENT; - case WSANO_DATA: return UV_ENOENT; - case ERROR_NOT_ENOUGH_MEMORY: return UV_ENOMEM; - case ERROR_OUTOFMEMORY: return UV_ENOMEM; - case ERROR_CANNOT_MAKE: return UV_ENOSPC; - case ERROR_DISK_FULL: return UV_ENOSPC; - case ERROR_EA_TABLE_FULL: return UV_ENOSPC; - case ERROR_END_OF_MEDIA: return UV_ENOSPC; - case ERROR_HANDLE_DISK_FULL: return UV_ENOSPC; - case ERROR_NOT_CONNECTED: return UV_ENOTCONN; - case WSAENOTCONN: return UV_ENOTCONN; - case ERROR_DIR_NOT_EMPTY: return UV_ENOTEMPTY; - case WSAENOTSOCK: return UV_ENOTSOCK; - case ERROR_NOT_SUPPORTED: return UV_ENOTSUP; - case ERROR_BROKEN_PIPE: return UV_EOF; - case ERROR_ACCESS_DENIED: return UV_EPERM; - case ERROR_PRIVILEGE_NOT_HELD: return UV_EPERM; - case ERROR_BAD_PIPE: return UV_EPIPE; - case ERROR_NO_DATA: return UV_EPIPE; - case ERROR_PIPE_NOT_CONNECTED: return UV_EPIPE; - case WSAESHUTDOWN: return UV_EPIPE; - case WSAEPROTONOSUPPORT: return UV_EPROTONOSUPPORT; - case ERROR_WRITE_PROTECT: return UV_EROFS; - case ERROR_SEM_TIMEOUT: return UV_ETIMEDOUT; - case WSAETIMEDOUT: return UV_ETIMEDOUT; - case ERROR_NOT_SAME_DEVICE: return UV_EXDEV; - case ERROR_INVALID_FUNCTION: return UV_EISDIR; - case ERROR_META_EXPANSION_TOO_LONG: return UV_E2BIG; - default: return UV_UNKNOWN; - } -} diff --git a/libuv/src/win/fs-event.c b/libuv/src/win/fs-event.c deleted file mode 100644 index 7ad99a8..0000000 --- a/libuv/src/win/fs-event.c +++ /dev/null @@ -1,527 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include - -#include "uv.h" -#include "internal.h" -#include "handle-inl.h" -#include "req-inl.h" - - -const unsigned int uv_directory_watcher_buffer_size = 4096; - - -static void uv_fs_event_queue_readdirchanges(uv_loop_t* loop, - uv_fs_event_t* handle) { - assert(handle->dir_handle != INVALID_HANDLE_VALUE); - assert(!handle->req_pending); - - memset(&(handle->req.overlapped), 0, sizeof(handle->req.overlapped)); - if (!ReadDirectoryChangesW(handle->dir_handle, - handle->buffer, - uv_directory_watcher_buffer_size, - FALSE, - FILE_NOTIFY_CHANGE_FILE_NAME | - FILE_NOTIFY_CHANGE_DIR_NAME | - FILE_NOTIFY_CHANGE_ATTRIBUTES | - FILE_NOTIFY_CHANGE_SIZE | - FILE_NOTIFY_CHANGE_LAST_WRITE | - FILE_NOTIFY_CHANGE_LAST_ACCESS | - FILE_NOTIFY_CHANGE_CREATION | - FILE_NOTIFY_CHANGE_SECURITY, - NULL, - &handle->req.overlapped, - NULL)) { - /* Make this req pending reporting an error. */ - SET_REQ_ERROR(&handle->req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)&handle->req); - } - - handle->req_pending = 1; -} - - -static int uv_split_path(const WCHAR* filename, WCHAR** dir, - WCHAR** file) { - int len = wcslen(filename); - int i = len; - while (i > 0 && filename[--i] != '\\' && filename[i] != '/'); - - if (i == 0) { - if (dir) { - *dir = (WCHAR*)malloc((MAX_PATH + 1) * sizeof(WCHAR)); - if (!*dir) { - uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); - } - - if (!GetCurrentDirectoryW(MAX_PATH, *dir)) { - free(*dir); - *dir = NULL; - return -1; - } - } - - *file = wcsdup(filename); - } else { - if (dir) { - *dir = (WCHAR*)malloc((i + 1) * sizeof(WCHAR)); - if (!*dir) { - uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); - } - wcsncpy(*dir, filename, i); - (*dir)[i] = L'\0'; - } - - *file = (WCHAR*)malloc((len - i) * sizeof(WCHAR)); - if (!*file) { - uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); - } - wcsncpy(*file, filename + i + 1, len - i - 1); - (*file)[len - i - 1] = L'\0'; - } - - return 0; -} - - -int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { - uv__handle_init(loop, (uv_handle_t*) handle, UV_FS_EVENT); - handle->dir_handle = INVALID_HANDLE_VALUE; - handle->buffer = NULL; - handle->req_pending = 0; - handle->filew = NULL; - handle->short_filew = NULL; - handle->dirw = NULL; - - uv_req_init(loop, (uv_req_t*)&handle->req); - handle->req.type = UV_FS_EVENT_REQ; - handle->req.data = handle; - - return 0; -} - - -int uv_fs_event_start(uv_fs_event_t* handle, - uv_fs_event_cb cb, - const char* path, - unsigned int flags) { - int name_size, is_path_dir; - DWORD attr, last_error; - WCHAR* dir = NULL, *dir_to_watch, *pathw = NULL; - WCHAR short_path[MAX_PATH]; - - if (uv__is_active(handle)) - return UV_EINVAL; - - handle->cb = cb; - handle->path = strdup(path); - if (!handle->path) { - uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); - } - - uv__handle_start(handle); - - /* Convert name to UTF16. */ - name_size = uv_utf8_to_utf16(path, NULL, 0) * sizeof(WCHAR); - pathw = (WCHAR*)malloc(name_size); - if (!pathw) { - uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); - } - - if (!uv_utf8_to_utf16(path, pathw, - name_size / sizeof(WCHAR))) { - return uv_translate_sys_error(GetLastError()); - } - - /* Determine whether path is a file or a directory. */ - attr = GetFileAttributesW(pathw); - if (attr == INVALID_FILE_ATTRIBUTES) { - last_error = GetLastError(); - goto error; - } - - is_path_dir = (attr & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0; - - if (is_path_dir) { - /* path is a directory, so that's the directory that we will watch. */ - handle->dirw = pathw; - dir_to_watch = pathw; - } else { - /* - * path is a file. So we split path into dir & file parts, and - * watch the dir directory. - */ - - /* Convert to short path. */ - if (!GetShortPathNameW(pathw, short_path, ARRAY_SIZE(short_path))) { - last_error = GetLastError(); - goto error; - } - - if (uv_split_path(pathw, &dir, &handle->filew) != 0) { - last_error = GetLastError(); - goto error; - } - - if (uv_split_path(short_path, NULL, &handle->short_filew) != 0) { - last_error = GetLastError(); - goto error; - } - - dir_to_watch = dir; - free(pathw); - pathw = NULL; - } - - handle->dir_handle = CreateFileW(dir_to_watch, - FILE_LIST_DIRECTORY, - FILE_SHARE_READ | FILE_SHARE_DELETE | - FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS | - FILE_FLAG_OVERLAPPED, - NULL); - - if (dir) { - free(dir); - dir = NULL; - } - - if (handle->dir_handle == INVALID_HANDLE_VALUE) { - last_error = GetLastError(); - goto error; - } - - if (CreateIoCompletionPort(handle->dir_handle, - handle->loop->iocp, - (ULONG_PTR)handle, - 0) == NULL) { - last_error = GetLastError(); - goto error; - } - - if (!handle->buffer) { - handle->buffer = (char*)_aligned_malloc(uv_directory_watcher_buffer_size, - sizeof(DWORD)); - } - if (!handle->buffer) { - uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); - } - - memset(&(handle->req.overlapped), 0, sizeof(handle->req.overlapped)); - - if (!ReadDirectoryChangesW(handle->dir_handle, - handle->buffer, - uv_directory_watcher_buffer_size, - FALSE, - FILE_NOTIFY_CHANGE_FILE_NAME | - FILE_NOTIFY_CHANGE_DIR_NAME | - FILE_NOTIFY_CHANGE_ATTRIBUTES | - FILE_NOTIFY_CHANGE_SIZE | - FILE_NOTIFY_CHANGE_LAST_WRITE | - FILE_NOTIFY_CHANGE_LAST_ACCESS | - FILE_NOTIFY_CHANGE_CREATION | - FILE_NOTIFY_CHANGE_SECURITY, - NULL, - &handle->req.overlapped, - NULL)) { - last_error = GetLastError(); - goto error; - } - - handle->req_pending = 1; - return 0; - -error: - if (handle->path) { - free(handle->path); - handle->path = NULL; - } - - if (handle->filew) { - free(handle->filew); - handle->filew = NULL; - } - - if (handle->short_filew) { - free(handle->short_filew); - handle->short_filew = NULL; - } - - free(pathw); - - if (handle->dir_handle != INVALID_HANDLE_VALUE) { - CloseHandle(handle->dir_handle); - handle->dir_handle = INVALID_HANDLE_VALUE; - } - - if (handle->buffer) { - _aligned_free(handle->buffer); - handle->buffer = NULL; - } - - return uv_translate_sys_error(last_error); -} - - -int uv_fs_event_stop(uv_fs_event_t* handle) { - if (!uv__is_active(handle)) - return 0; - - if (handle->dir_handle != INVALID_HANDLE_VALUE) { - CloseHandle(handle->dir_handle); - handle->dir_handle = INVALID_HANDLE_VALUE; - } - - uv__handle_stop(handle); - - if (handle->filew) { - free(handle->filew); - handle->filew = NULL; - } - - if (handle->short_filew) { - free(handle->short_filew); - handle->short_filew = NULL; - } - - if (handle->path) { - free(handle->path); - handle->path = NULL; - } - - if (handle->dirw) { - free(handle->dirw); - handle->dirw = NULL; - } - - return 0; -} - - -void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, - uv_fs_event_t* handle) { - FILE_NOTIFY_INFORMATION* file_info; - int err, sizew, size, result; - char* filename = NULL; - WCHAR* filenamew, *long_filenamew = NULL; - DWORD offset = 0; - - assert(req->type == UV_FS_EVENT_REQ); - assert(handle->req_pending); - handle->req_pending = 0; - - /* Don't report any callbacks if: - * - We're closing, just push the handle onto the endgame queue - * - We are not active, just ignore the callback - */ - if (!uv__is_active(handle)) { - if (handle->flags & UV__HANDLE_CLOSING) { - uv_want_endgame(loop, (uv_handle_t*) handle); - } - return; - } - - file_info = (FILE_NOTIFY_INFORMATION*)(handle->buffer + offset); - - if (REQ_SUCCESS(req)) { - if (req->overlapped.InternalHigh > 0) { - do { - file_info = (FILE_NOTIFY_INFORMATION*)((char*)file_info + offset); - assert(!filename); - assert(!long_filenamew); - - /* - * Fire the event only if we were asked to watch a directory, - * or if the filename filter matches. - */ - if (handle->dirw || - _wcsnicmp(handle->filew, file_info->FileName, - file_info->FileNameLength / sizeof(WCHAR)) == 0 || - _wcsnicmp(handle->short_filew, file_info->FileName, - file_info->FileNameLength / sizeof(WCHAR)) == 0) { - - if (handle->dirw) { - /* - * We attempt to convert the file name to its long form for - * events that still point to valid files on disk. - * For removed and renamed events, we do not provide the file name. - */ - if (file_info->Action != FILE_ACTION_REMOVED && - file_info->Action != FILE_ACTION_RENAMED_OLD_NAME) { - /* Construct a full path to the file. */ - size = wcslen(handle->dirw) + - file_info->FileNameLength / sizeof(WCHAR) + 2; - - filenamew = (WCHAR*)malloc(size * sizeof(WCHAR)); - if (!filenamew) { - uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); - } - - _snwprintf(filenamew, size, L"%s\\%.*s", handle->dirw, - file_info->FileNameLength / sizeof(WCHAR), - file_info->FileName); - - filenamew[size - 1] = L'\0'; - - /* Convert to long name. */ - size = GetLongPathNameW(filenamew, NULL, 0); - - if (size) { - long_filenamew = (WCHAR*)malloc(size * sizeof(WCHAR)); - if (!long_filenamew) { - uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); - } - - size = GetLongPathNameW(filenamew, long_filenamew, size); - if (size) { - long_filenamew[size] = '\0'; - } else { - free(long_filenamew); - long_filenamew = NULL; - } - } - - free(filenamew); - - if (long_filenamew) { - /* Get the file name out of the long path. */ - result = uv_split_path(long_filenamew, NULL, &filenamew); - free(long_filenamew); - - if (result == 0) { - long_filenamew = filenamew; - sizew = -1; - } else { - long_filenamew = NULL; - } - } - - /* - * If we couldn't get the long name - just use the name - * provided by ReadDirectoryChangesW. - */ - if (!long_filenamew) { - filenamew = file_info->FileName; - sizew = file_info->FileNameLength / sizeof(WCHAR); - } - } else { - /* Removed or renamed callbacks don't provide filename. */ - filenamew = NULL; - } - } else { - /* We already have the long name of the file, so just use it. */ - filenamew = handle->filew; - sizew = -1; - } - - if (filenamew) { - /* Convert the filename to utf8. */ - size = uv_utf16_to_utf8(filenamew, - sizew, - NULL, - 0); - if (size) { - filename = (char*)malloc(size + 1); - if (!filename) { - uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); - } - - size = uv_utf16_to_utf8(filenamew, - sizew, - filename, - size); - if (size) { - filename[size] = '\0'; - } else { - free(filename); - filename = NULL; - } - } - } - - switch (file_info->Action) { - case FILE_ACTION_ADDED: - case FILE_ACTION_REMOVED: - case FILE_ACTION_RENAMED_OLD_NAME: - case FILE_ACTION_RENAMED_NEW_NAME: - handle->cb(handle, filename, UV_RENAME, 0); - break; - - case FILE_ACTION_MODIFIED: - handle->cb(handle, filename, UV_CHANGE, 0); - break; - } - - free(filename); - filename = NULL; - free(long_filenamew); - long_filenamew = NULL; - } - - offset = file_info->NextEntryOffset; - } while (offset && !(handle->flags & UV__HANDLE_CLOSING)); - } else { - handle->cb(handle, NULL, UV_CHANGE, 0); - } - } else { - err = GET_REQ_ERROR(req); - handle->cb(handle, NULL, 0, uv_translate_sys_error(err)); - } - - if (!(handle->flags & UV__HANDLE_CLOSING)) { - uv_fs_event_queue_readdirchanges(loop, handle); - } else { - uv_want_endgame(loop, (uv_handle_t*)handle); - } -} - - -void uv_fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle) { - uv_fs_event_stop(handle); - - uv__handle_closing(handle); - - if (!handle->req_pending) { - uv_want_endgame(loop, (uv_handle_t*)handle); - } - -} - - -void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle) { - if ((handle->flags & UV__HANDLE_CLOSING) && !handle->req_pending) { - assert(!(handle->flags & UV_HANDLE_CLOSED)); - - if (handle->buffer) { - _aligned_free(handle->buffer); - handle->buffer = NULL; - } - - uv__handle_close(handle); - } -} diff --git a/libuv/src/win/fs.c b/libuv/src/win/fs.c deleted file mode 100644 index 33bc9da..0000000 --- a/libuv/src/win/fs.c +++ /dev/null @@ -1,2311 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "uv.h" -#include "internal.h" -#include "req-inl.h" -#include "handle-inl.h" - -#include - - -#define UV_FS_FREE_PATHS 0x0002 -#define UV_FS_FREE_PTR 0x0008 -#define UV_FS_CLEANEDUP 0x0010 - - -#define QUEUE_FS_TP_JOB(loop, req) \ - do { \ - uv__req_register(loop, req); \ - uv__work_submit((loop), &(req)->work_req, uv__fs_work, uv__fs_done); \ - } while (0) - -#define SET_REQ_RESULT(req, result_value) \ - do { \ - req->result = (result_value); \ - if (req->result == -1) { \ - req->sys_errno_ = _doserrno; \ - req->result = uv_translate_sys_error(req->sys_errno_); \ - } \ - } while (0) - -#define SET_REQ_WIN32_ERROR(req, sys_errno) \ - do { \ - req->sys_errno_ = (sys_errno); \ - req->result = uv_translate_sys_error(req->sys_errno_); \ - } while (0) - -#define SET_REQ_UV_ERROR(req, uv_errno, sys_errno) \ - do { \ - req->result = (uv_errno); \ - req->sys_errno_ = (sys_errno); \ - } while (0) - -#define VERIFY_FD(fd, req) \ - if (fd == -1) { \ - req->result = UV_EBADF; \ - req->sys_errno_ = ERROR_INVALID_HANDLE; \ - return; \ - } - -#define FILETIME_TO_UINT(filetime) \ - (*((uint64_t*) &(filetime)) - 116444736000000000ULL) - -#define FILETIME_TO_TIME_T(filetime) \ - (FILETIME_TO_UINT(filetime) / 10000000ULL) - -#define FILETIME_TO_TIME_NS(filetime, secs) \ - ((FILETIME_TO_UINT(filetime) - (secs * 10000000ULL)) * 100) - -#define FILETIME_TO_TIMESPEC(ts, filetime) \ - do { \ - (ts).tv_sec = (long) FILETIME_TO_TIME_T(filetime); \ - (ts).tv_nsec = (long) FILETIME_TO_TIME_NS(filetime, (ts).tv_sec); \ - } while(0) - -#define TIME_T_TO_FILETIME(time, filetime_ptr) \ - do { \ - uint64_t bigtime = ((int64_t) (time) * 10000000LL) + \ - 116444736000000000ULL; \ - (filetime_ptr)->dwLowDateTime = bigtime & 0xFFFFFFFF; \ - (filetime_ptr)->dwHighDateTime = bigtime >> 32; \ - } while(0) - -#define IS_SLASH(c) ((c) == L'\\' || (c) == L'/') -#define IS_LETTER(c) (((c) >= L'a' && (c) <= L'z') || \ - ((c) >= L'A' && (c) <= L'Z')) - -const WCHAR JUNCTION_PREFIX[] = L"\\??\\"; -const WCHAR JUNCTION_PREFIX_LEN = 4; - -const WCHAR LONG_PATH_PREFIX[] = L"\\\\?\\"; -const WCHAR LONG_PATH_PREFIX_LEN = 4; - - -void uv_fs_init() { - _fmode = _O_BINARY; -} - - -INLINE static int fs__capture_path(uv_loop_t* loop, uv_fs_t* req, - const char* path, const char* new_path, const int copy_path) { - char* buf; - char* pos; - ssize_t buf_sz = 0, path_len, pathw_len = 0, new_pathw_len = 0; - - /* new_path can only be set if path is also set. */ - assert(new_path == NULL || path != NULL); - - if (path != NULL) { - pathw_len = MultiByteToWideChar(CP_UTF8, - 0, - path, - -1, - NULL, - 0); - if (pathw_len == 0) { - return GetLastError(); - } - - buf_sz += pathw_len * sizeof(WCHAR); - } - - if (path != NULL && copy_path) { - path_len = 1 + strlen(path); - buf_sz += path_len; - } - - if (new_path != NULL) { - new_pathw_len = MultiByteToWideChar(CP_UTF8, - 0, - new_path, - -1, - NULL, - 0); - if (new_pathw_len == 0) { - return GetLastError(); - } - - buf_sz += new_pathw_len * sizeof(WCHAR); - } - - - if (buf_sz == 0) { - req->pathw = NULL; - req->new_pathw = NULL; - req->path = NULL; - return 0; - } - - buf = (char*) malloc(buf_sz); - if (buf == NULL) { - return ERROR_OUTOFMEMORY; - } - - pos = buf; - - if (path != NULL) { - DWORD r = MultiByteToWideChar(CP_UTF8, - 0, - path, - -1, - (WCHAR*) pos, - pathw_len); - assert(r == (DWORD) pathw_len); - req->pathw = (WCHAR*) pos; - pos += r * sizeof(WCHAR); - } else { - req->pathw = NULL; - } - - if (new_path != NULL) { - DWORD r = MultiByteToWideChar(CP_UTF8, - 0, - new_path, - -1, - (WCHAR*) pos, - new_pathw_len); - assert(r == (DWORD) new_pathw_len); - req->new_pathw = (WCHAR*) pos; - pos += r * sizeof(WCHAR); - } else { - req->new_pathw = NULL; - } - - if (!copy_path) { - req->path = path; - } else if (path) { - memcpy(pos, path, path_len); - assert(path_len == buf_sz - (pos - buf)); - req->path = pos; - } else { - req->path = NULL; - } - - req->flags |= UV_FS_FREE_PATHS; - - return 0; -} - - - -INLINE static void uv_fs_req_init(uv_loop_t* loop, uv_fs_t* req, - uv_fs_type fs_type, const uv_fs_cb cb) { - uv_req_init(loop, (uv_req_t*) req); - - req->type = UV_FS; - req->loop = loop; - req->flags = 0; - req->fs_type = fs_type; - req->result = 0; - req->ptr = NULL; - req->path = NULL; - req->cb = cb; -} - - -INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr, - uint64_t* target_len_ptr) { - char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; - REPARSE_DATA_BUFFER* reparse_data = (REPARSE_DATA_BUFFER*) buffer; - WCHAR *w_target; - DWORD w_target_len; - char* target; - int target_len; - DWORD bytes; - - if (!DeviceIoControl(handle, - FSCTL_GET_REPARSE_POINT, - NULL, - 0, - buffer, - sizeof buffer, - &bytes, - NULL)) { - return -1; - } - - if (reparse_data->ReparseTag == IO_REPARSE_TAG_SYMLINK) { - /* Real symlink */ - w_target = reparse_data->SymbolicLinkReparseBuffer.PathBuffer + - (reparse_data->SymbolicLinkReparseBuffer.SubstituteNameOffset / - sizeof(WCHAR)); - w_target_len = - reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength / - sizeof(WCHAR); - - /* Real symlinks can contain pretty much everything, but the only thing */ - /* we really care about is undoing the implicit conversion to an NT */ - /* namespaced path that CreateSymbolicLink will perform on absolute */ - /* paths. If the path is win32-namespaced then the user must have */ - /* explicitly made it so, and we better just return the unmodified */ - /* reparse data. */ - if (w_target_len >= 4 && - w_target[0] == L'\\' && - w_target[1] == L'?' && - w_target[2] == L'?' && - w_target[3] == L'\\') { - /* Starts with \??\ */ - if (w_target_len >= 6 && - ((w_target[4] >= L'A' && w_target[4] <= L'Z') || - (w_target[4] >= L'a' && w_target[4] <= L'z')) && - w_target[5] == L':' && - (w_target_len == 6 || w_target[6] == L'\\')) { - /* \??\:\ */ - w_target += 4; - w_target_len -= 4; - - } else if (w_target_len >= 8 && - (w_target[4] == L'U' || w_target[4] == L'u') && - (w_target[5] == L'N' || w_target[5] == L'n') && - (w_target[6] == L'C' || w_target[6] == L'c') && - w_target[7] == L'\\') { - /* \??\UNC\\\ - make sure the final path looks like */ - /* \\\\ */ - w_target += 6; - w_target[0] = L'\\'; - w_target_len -= 6; - } - } - - } else if (reparse_data->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) { - /* Junction. */ - w_target = reparse_data->MountPointReparseBuffer.PathBuffer + - (reparse_data->MountPointReparseBuffer.SubstituteNameOffset / - sizeof(WCHAR)); - w_target_len = reparse_data->MountPointReparseBuffer.SubstituteNameLength / - sizeof(WCHAR); - - /* Only treat junctions that look like \??\:\ as symlink. */ - /* Junctions can also be used as mount points, like \??\Volume{}, */ - /* but that's confusing for programs since they wouldn't be able to */ - /* actually understand such a path when returned by uv_readlink(). */ - /* UNC paths are never valid for junctions so we don't care about them. */ - if (!(w_target_len >= 6 && - w_target[0] == L'\\' && - w_target[1] == L'?' && - w_target[2] == L'?' && - w_target[3] == L'\\' && - ((w_target[4] >= L'A' && w_target[4] <= L'Z') || - (w_target[4] >= L'a' && w_target[4] <= L'z')) && - w_target[5] == L':' && - (w_target_len == 6 || w_target[6] == L'\\'))) { - SetLastError(ERROR_SYMLINK_NOT_SUPPORTED); - return -1; - } - - /* Remove leading \??\ */ - w_target += 4; - w_target_len -= 4; - - } else { - /* Reparse tag does not indicate a symlink. */ - SetLastError(ERROR_SYMLINK_NOT_SUPPORTED); - return -1; - } - - /* If needed, compute the length of the target. */ - if (target_ptr != NULL || target_len_ptr != NULL) { - /* Compute the length of the target. */ - target_len = WideCharToMultiByte(CP_UTF8, - 0, - w_target, - w_target_len, - NULL, - 0, - NULL, - NULL); - if (target_len == 0) { - return -1; - } - } - - /* If requested, allocate memory and convert to UTF8. */ - if (target_ptr != NULL) { - int r; - target = (char*) malloc(target_len + 1); - if (target == NULL) { - SetLastError(ERROR_OUTOFMEMORY); - return -1; - } - - r = WideCharToMultiByte(CP_UTF8, - 0, - w_target, - w_target_len, - target, - target_len, - NULL, - NULL); - assert(r == target_len); - target[target_len] = '\0'; - - *target_ptr = target; - } - - if (target_len_ptr != NULL) { - *target_len_ptr = target_len; - } - - return 0; -} - - -void fs__open(uv_fs_t* req) { - DWORD access; - DWORD share; - DWORD disposition; - DWORD attributes = 0; - HANDLE file; - int fd, current_umask; - int flags = req->file_flags; - - /* Obtain the active umask. umask() never fails and returns the previous */ - /* umask. */ - current_umask = umask(0); - umask(current_umask); - - /* convert flags and mode to CreateFile parameters */ - switch (flags & (_O_RDONLY | _O_WRONLY | _O_RDWR)) { - case _O_RDONLY: - access = FILE_GENERIC_READ; - attributes |= FILE_FLAG_BACKUP_SEMANTICS; - break; - case _O_WRONLY: - access = FILE_GENERIC_WRITE; - break; - case _O_RDWR: - access = FILE_GENERIC_READ | FILE_GENERIC_WRITE; - break; - default: - goto einval; - } - - if (flags & _O_APPEND) { - access &= ~FILE_WRITE_DATA; - access |= FILE_APPEND_DATA; - attributes &= ~FILE_FLAG_BACKUP_SEMANTICS; - } - - /* - * Here is where we deviate significantly from what CRT's _open() - * does. We indiscriminately use all the sharing modes, to match - * UNIX semantics. In particular, this ensures that the file can - * be deleted even whilst it's open, fixing issue #1449. - */ - share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; - - switch (flags & (_O_CREAT | _O_EXCL | _O_TRUNC)) { - case 0: - case _O_EXCL: - disposition = OPEN_EXISTING; - break; - case _O_CREAT: - disposition = OPEN_ALWAYS; - break; - case _O_CREAT | _O_EXCL: - case _O_CREAT | _O_TRUNC | _O_EXCL: - disposition = CREATE_NEW; - break; - case _O_TRUNC: - case _O_TRUNC | _O_EXCL: - disposition = TRUNCATE_EXISTING; - break; - case _O_CREAT | _O_TRUNC: - disposition = CREATE_ALWAYS; - break; - default: - goto einval; - } - - attributes |= FILE_ATTRIBUTE_NORMAL; - if (flags & _O_CREAT) { - if (!((req->mode & ~current_umask) & _S_IWRITE)) { - attributes |= FILE_ATTRIBUTE_READONLY; - } - } - - if (flags & _O_TEMPORARY ) { - attributes |= FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_TEMPORARY; - access |= DELETE; - } - - if (flags & _O_SHORT_LIVED) { - attributes |= FILE_ATTRIBUTE_TEMPORARY; - } - - switch (flags & (_O_SEQUENTIAL | _O_RANDOM)) { - case 0: - break; - case _O_SEQUENTIAL: - attributes |= FILE_FLAG_SEQUENTIAL_SCAN; - break; - case _O_RANDOM: - attributes |= FILE_FLAG_RANDOM_ACCESS; - break; - default: - goto einval; - } - - /* Setting this flag makes it possible to open a directory. */ - attributes |= FILE_FLAG_BACKUP_SEMANTICS; - - file = CreateFileW(req->pathw, - access, - share, - NULL, - disposition, - attributes, - NULL); - if (file == INVALID_HANDLE_VALUE) { - DWORD error = GetLastError(); - if (error == ERROR_FILE_EXISTS && (flags & _O_CREAT) && - !(flags & _O_EXCL)) { - /* Special case: when ERROR_FILE_EXISTS happens and O_CREAT was */ - /* specified, it means the path referred to a directory. */ - SET_REQ_UV_ERROR(req, UV_EISDIR, error); - } else { - SET_REQ_WIN32_ERROR(req, GetLastError()); - } - return; - } - - fd = _open_osfhandle((intptr_t) file, flags); - if (fd < 0) { - /* The only known failure mode for _open_osfhandle() is EMFILE, in which - * case GetLastError() will return zero. However we'll try to handle other - * errors as well, should they ever occur. - */ - if (errno == EMFILE) - SET_REQ_UV_ERROR(req, UV_EMFILE, ERROR_TOO_MANY_OPEN_FILES); - else if (GetLastError() != ERROR_SUCCESS) - SET_REQ_WIN32_ERROR(req, GetLastError()); - else - SET_REQ_WIN32_ERROR(req, UV_UNKNOWN); - return; - } - - SET_REQ_RESULT(req, fd); - return; - - einval: - SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER); -} - -void fs__close(uv_fs_t* req) { - int fd = req->fd; - int result; - - VERIFY_FD(fd, req); - - result = _close(fd); - SET_REQ_RESULT(req, result); -} - - -void fs__read(uv_fs_t* req) { - int fd = req->fd; - int64_t offset = req->offset; - HANDLE handle; - OVERLAPPED overlapped, *overlapped_ptr; - LARGE_INTEGER offset_; - DWORD bytes; - DWORD error; - int result; - unsigned int index; - - VERIFY_FD(fd, req); - - handle = uv__get_osfhandle(fd); - - if (handle == INVALID_HANDLE_VALUE) { - SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE); - return; - } - - if (offset != -1) { - memset(&overlapped, 0, sizeof overlapped); - overlapped_ptr = &overlapped; - } else { - overlapped_ptr = NULL; - } - - index = 0; - bytes = 0; - do { - DWORD incremental_bytes; - - if (offset != -1) { - offset_.QuadPart = offset + bytes; - overlapped.Offset = offset_.LowPart; - overlapped.OffsetHigh = offset_.HighPart; - } - - result = ReadFile(handle, - req->bufs[index].base, - req->bufs[index].len, - &incremental_bytes, - overlapped_ptr); - bytes += incremental_bytes; - ++index; - } while (result && index < req->nbufs); - - if (result || bytes > 0) { - SET_REQ_RESULT(req, bytes); - } else { - error = GetLastError(); - if (error == ERROR_HANDLE_EOF) { - SET_REQ_RESULT(req, bytes); - } else { - SET_REQ_WIN32_ERROR(req, error); - } - } -} - - -void fs__write(uv_fs_t* req) { - int fd = req->fd; - int64_t offset = req->offset; - HANDLE handle; - OVERLAPPED overlapped, *overlapped_ptr; - LARGE_INTEGER offset_; - DWORD bytes; - int result; - unsigned int index; - - VERIFY_FD(fd, req); - - handle = uv__get_osfhandle(fd); - if (handle == INVALID_HANDLE_VALUE) { - SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE); - return; - } - - if (offset != -1) { - memset(&overlapped, 0, sizeof overlapped); - overlapped_ptr = &overlapped; - } else { - overlapped_ptr = NULL; - } - - index = 0; - bytes = 0; - do { - DWORD incremental_bytes; - - if (offset != -1) { - offset_.QuadPart = offset + bytes; - overlapped.Offset = offset_.LowPart; - overlapped.OffsetHigh = offset_.HighPart; - } - - result = WriteFile(handle, - req->bufs[index].base, - req->bufs[index].len, - &incremental_bytes, - overlapped_ptr); - bytes += incremental_bytes; - ++index; - } while (result && index < req->nbufs); - - if (result || bytes > 0) { - SET_REQ_RESULT(req, bytes); - } else { - SET_REQ_WIN32_ERROR(req, GetLastError()); - } -} - - -void fs__rmdir(uv_fs_t* req) { - int result = _wrmdir(req->pathw); - SET_REQ_RESULT(req, result); -} - - -void fs__unlink(uv_fs_t* req) { - const WCHAR* pathw = req->pathw; - HANDLE handle; - BY_HANDLE_FILE_INFORMATION info; - FILE_DISPOSITION_INFORMATION disposition; - IO_STATUS_BLOCK iosb; - NTSTATUS status; - - handle = CreateFileW(pathw, - FILE_READ_ATTRIBUTES | DELETE, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, - OPEN_EXISTING, - FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, - NULL); - - if (handle == INVALID_HANDLE_VALUE) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - return; - } - - if (!GetFileInformationByHandle(handle, &info)) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - CloseHandle(handle); - return; - } - - if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - /* Do not allow deletion of directories, unless it is a symlink. When */ - /* the path refers to a non-symlink directory, report EPERM as mandated */ - /* by POSIX.1. */ - - /* Check if it is a reparse point. If it's not, it's a normal directory. */ - if (!(info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { - SET_REQ_WIN32_ERROR(req, ERROR_ACCESS_DENIED); - CloseHandle(handle); - return; - } - - /* Read the reparse point and check if it is a valid symlink. */ - /* If not, don't unlink. */ - if (fs__readlink_handle(handle, NULL, NULL) < 0) { - DWORD error = GetLastError(); - if (error == ERROR_SYMLINK_NOT_SUPPORTED) - error = ERROR_ACCESS_DENIED; - SET_REQ_WIN32_ERROR(req, error); - CloseHandle(handle); - return; - } - } - - /* Try to set the delete flag. */ - disposition.DeleteFile = TRUE; - status = pNtSetInformationFile(handle, - &iosb, - &disposition, - sizeof disposition, - FileDispositionInformation); - if (NT_SUCCESS(status)) { - SET_REQ_SUCCESS(req); - } else { - SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status)); - } - - CloseHandle(handle); -} - - -void fs__mkdir(uv_fs_t* req) { - /* TODO: use req->mode. */ - int result = _wmkdir(req->pathw); - SET_REQ_RESULT(req, result); -} - - -/* OpenBSD original: lib/libc/stdio/mktemp.c */ -void fs__mkdtemp(uv_fs_t* req) { - static const WCHAR *tempchars = - L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - static const size_t num_chars = 62; - static const size_t num_x = 6; - WCHAR *cp, *ep; - unsigned int tries, i; - size_t len; - HCRYPTPROV h_crypt_prov; - uint64_t v; - BOOL released; - - len = wcslen(req->pathw); - ep = req->pathw + len; - if (len < num_x || wcsncmp(ep - num_x, L"XXXXXX", num_x)) { - SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER); - return; - } - - if (!CryptAcquireContext(&h_crypt_prov, NULL, NULL, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT)) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - return; - } - - tries = TMP_MAX; - do { - if (!CryptGenRandom(h_crypt_prov, sizeof(v), (BYTE*) &v)) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - break; - } - - cp = ep - num_x; - for (i = 0; i < num_x; i++) { - *cp++ = tempchars[v % num_chars]; - v /= num_chars; - } - - if (_wmkdir(req->pathw) == 0) { - len = strlen(req->path); - wcstombs((char*) req->path + len - num_x, ep - num_x, num_x); - SET_REQ_RESULT(req, 0); - break; - } else if (errno != EEXIST) { - SET_REQ_RESULT(req, -1); - break; - } - } while (--tries); - - released = CryptReleaseContext(h_crypt_prov, 0); - assert(released); - if (tries == 0) { - SET_REQ_RESULT(req, -1); - } -} - - -void fs__scandir(uv_fs_t* req) { - static const size_t dirents_initial_size = 32; - - HANDLE dir_handle = INVALID_HANDLE_VALUE; - - uv__dirent_t** dirents = NULL; - size_t dirents_size = 0; - size_t dirents_used = 0; - - IO_STATUS_BLOCK iosb; - NTSTATUS status; - - /* Buffer to hold directory entries returned by NtQueryDirectoryFile. - * It's important that this buffer can hold at least one entry, regardless - * of the length of the file names present in the enumerated directory. - * A file name is at most 256 WCHARs long. - * According to MSDN, the buffer must be aligned at an 8-byte boundary. - */ - __declspec(align(8)) char buffer[8192]; - - STATIC_ASSERT(sizeof buffer >= - sizeof(FILE_DIRECTORY_INFORMATION) + 256 * sizeof(WCHAR)); - - /* Open the directory. */ - dir_handle = - CreateFileW(req->pathw, - FILE_LIST_DIRECTORY | SYNCHRONIZE, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS, - NULL); - if (dir_handle == INVALID_HANDLE_VALUE) - goto win32_error; - - /* Read the first chunk. */ - status = pNtQueryDirectoryFile(dir_handle, - NULL, - NULL, - NULL, - &iosb, - &buffer, - sizeof buffer, - FileDirectoryInformation, - FALSE, - NULL, - TRUE); - - /* If the handle is not a directory, we'll get STATUS_INVALID_PARAMETER. - * This should be reported back as UV_ENOTDIR. - */ - if (status == STATUS_INVALID_PARAMETER) - goto not_a_directory_error; - - while (NT_SUCCESS(status)) { - char* position = buffer; - size_t next_entry_offset = 0; - - do { - FILE_DIRECTORY_INFORMATION* info; - uv__dirent_t* dirent; - - size_t wchar_len; - size_t utf8_len; - - /* Obtain a pointer to the current directory entry. */ - position += next_entry_offset; - info = (FILE_DIRECTORY_INFORMATION*) position; - - /* Fetch the offset to the next directory entry. */ - next_entry_offset = info->NextEntryOffset; - - /* Compute the length of the filename in WCHARs. */ - wchar_len = info->FileNameLength / sizeof info->FileName[0]; - - /* Skip over '.' and '..' entries. */ - if (wchar_len == 1 && info->FileName[0] == L'.') - continue; - if (wchar_len == 2 && info->FileName[0] == L'.' && - info->FileName[1] == L'.') - continue; - - /* Compute the space required to store the filename as UTF-8. */ - utf8_len = WideCharToMultiByte( - CP_UTF8, 0, &info->FileName[0], wchar_len, NULL, 0, NULL, NULL); - if (utf8_len == 0) - goto win32_error; - - /* Resize the dirent array if needed. */ - if (dirents_used >= dirents_size) { - size_t new_dirents_size = - dirents_size == 0 ? dirents_initial_size : dirents_size << 1; - uv__dirent_t** new_dirents = - realloc(dirents, new_dirents_size * sizeof *dirents); - - if (new_dirents == NULL) - goto out_of_memory_error; - - dirents_size = new_dirents_size; - dirents = new_dirents; - } - - /* Allocate space for the uv dirent structure. The dirent structure - * includes room for the first character of the filename, but `utf8_len` - * doesn't count the NULL terminator at this point. - */ - dirent = malloc(sizeof *dirent + utf8_len); - if (dirent == NULL) - goto out_of_memory_error; - - dirents[dirents_used++] = dirent; - - /* Convert file name to UTF-8. */ - if (WideCharToMultiByte(CP_UTF8, - 0, - &info->FileName[0], - wchar_len, - &dirent->d_name[0], - utf8_len, - NULL, - NULL) == 0) - goto win32_error; - - /* Add a null terminator to the filename. */ - dirent->d_name[utf8_len] = '\0'; - - /* Fill out the type field. */ - if (info->FileAttributes & FILE_ATTRIBUTE_DEVICE) - dirent->d_type = UV__DT_CHAR; - else if (info->FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) - dirent->d_type = UV__DT_LINK; - else if (info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) - dirent->d_type = UV__DT_DIR; - else - dirent->d_type = UV__DT_FILE; - } while (next_entry_offset != 0); - - /* Read the next chunk. */ - status = pNtQueryDirectoryFile(dir_handle, - NULL, - NULL, - NULL, - &iosb, - &buffer, - sizeof buffer, - FileDirectoryInformation, - FALSE, - NULL, - FALSE); - - /* After the first pNtQueryDirectoryFile call, the function may return - * STATUS_SUCCESS even if the buffer was too small to hold at least one - * directory entry. - */ - if (status == STATUS_SUCCESS && iosb.Information == 0) - status = STATUS_BUFFER_OVERFLOW; - } - - if (status != STATUS_NO_MORE_FILES) - goto nt_error; - - CloseHandle(dir_handle); - - /* Store the result in the request object. */ - req->ptr = dirents; - if (dirents != NULL) - req->flags |= UV_FS_FREE_PTR; - - SET_REQ_RESULT(req, dirents_used); - - /* `nbufs` will be used as index by uv_fs_scandir_next. */ - req->nbufs = 0; - - return; - -nt_error: - SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status)); - goto cleanup; - -win32_error: - SET_REQ_WIN32_ERROR(req, GetLastError()); - goto cleanup; - -not_a_directory_error: - SET_REQ_UV_ERROR(req, UV_ENOTDIR, ERROR_DIRECTORY); - goto cleanup; - -out_of_memory_error: - SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY); - goto cleanup; - -cleanup: - if (dir_handle != INVALID_HANDLE_VALUE) - CloseHandle(dir_handle); - while (dirents_used > 0) - free(dirents[--dirents_used]); - if (dirents != NULL) - free(dirents); -} - - -INLINE static int fs__stat_handle(HANDLE handle, uv_stat_t* statbuf) { - FILE_ALL_INFORMATION file_info; - FILE_FS_VOLUME_INFORMATION volume_info; - NTSTATUS nt_status; - IO_STATUS_BLOCK io_status; - - nt_status = pNtQueryInformationFile(handle, - &io_status, - &file_info, - sizeof file_info, - FileAllInformation); - - /* Buffer overflow (a warning status code) is expected here. */ - if (NT_ERROR(nt_status)) { - SetLastError(pRtlNtStatusToDosError(nt_status)); - return -1; - } - - nt_status = pNtQueryVolumeInformationFile(handle, - &io_status, - &volume_info, - sizeof volume_info, - FileFsVolumeInformation); - - /* Buffer overflow (a warning status code) is expected here. */ - if (io_status.Status == STATUS_NOT_IMPLEMENTED) { - statbuf->st_dev = 0; - } else if (NT_ERROR(nt_status)) { - SetLastError(pRtlNtStatusToDosError(nt_status)); - return -1; - } else { - statbuf->st_dev = volume_info.VolumeSerialNumber; - } - - /* Todo: st_mode should probably always be 0666 for everyone. We might also - * want to report 0777 if the file is a .exe or a directory. - * - * Currently it's based on whether the 'readonly' attribute is set, which - * makes little sense because the semantics are so different: the 'read-only' - * flag is just a way for a user to protect against accidental deletion, and - * serves no security purpose. Windows uses ACLs for that. - * - * Also people now use uv_fs_chmod() to take away the writable bit for good - * reasons. Windows however just makes the file read-only, which makes it - * impossible to delete the file afterwards, since read-only files can't be - * deleted. - * - * IOW it's all just a clusterfuck and we should think of something that - * makes slightly more sense. - * - * And uv_fs_chmod should probably just fail on windows or be a total no-op. - * There's nothing sensible it can do anyway. - */ - statbuf->st_mode = 0; - - if (file_info.BasicInformation.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - statbuf->st_mode |= S_IFLNK; - if (fs__readlink_handle(handle, NULL, &statbuf->st_size) != 0) - return -1; - - } else if (file_info.BasicInformation.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - statbuf->st_mode |= _S_IFDIR; - statbuf->st_size = 0; - - } else { - statbuf->st_mode |= _S_IFREG; - statbuf->st_size = file_info.StandardInformation.EndOfFile.QuadPart; - } - - if (file_info.BasicInformation.FileAttributes & FILE_ATTRIBUTE_READONLY) - statbuf->st_mode |= _S_IREAD | (_S_IREAD >> 3) | (_S_IREAD >> 6); - else - statbuf->st_mode |= (_S_IREAD | _S_IWRITE) | ((_S_IREAD | _S_IWRITE) >> 3) | - ((_S_IREAD | _S_IWRITE) >> 6); - - FILETIME_TO_TIMESPEC(statbuf->st_atim, file_info.BasicInformation.LastAccessTime); - FILETIME_TO_TIMESPEC(statbuf->st_ctim, file_info.BasicInformation.ChangeTime); - FILETIME_TO_TIMESPEC(statbuf->st_mtim, file_info.BasicInformation.LastWriteTime); - FILETIME_TO_TIMESPEC(statbuf->st_birthtim, file_info.BasicInformation.CreationTime); - - statbuf->st_ino = file_info.InternalInformation.IndexNumber.QuadPart; - - /* st_blocks contains the on-disk allocation size in 512-byte units. */ - statbuf->st_blocks = - file_info.StandardInformation.AllocationSize.QuadPart >> 9ULL; - - statbuf->st_nlink = file_info.StandardInformation.NumberOfLinks; - - /* The st_blksize is supposed to be the 'optimal' number of bytes for reading - * and writing to the disk. That is, for any definition of 'optimal' - it's - * supposed to at least avoid read-update-write behavior when writing to the - * disk. - * - * However nobody knows this and even fewer people actually use this value, - * and in order to fill it out we'd have to make another syscall to query the - * volume for FILE_FS_SECTOR_SIZE_INFORMATION. - * - * Therefore we'll just report a sensible value that's quite commonly okay - * on modern hardware. - */ - statbuf->st_blksize = 2048; - - /* Todo: set st_flags to something meaningful. Also provide a wrapper for - * chattr(2). - */ - statbuf->st_flags = 0; - - /* Windows has nothing sensible to say about these values, so they'll just - * remain empty. - */ - statbuf->st_gid = 0; - statbuf->st_uid = 0; - statbuf->st_rdev = 0; - statbuf->st_gen = 0; - - return 0; -} - - -INLINE static void fs__stat_prepare_path(WCHAR* pathw) { - size_t len = wcslen(pathw); - - /* TODO: ignore namespaced paths. */ - if (len > 1 && pathw[len - 2] != L':' && - (pathw[len - 1] == L'\\' || pathw[len - 1] == L'/')) { - pathw[len - 1] = '\0'; - } -} - - -INLINE static void fs__stat_impl(uv_fs_t* req, int do_lstat) { - HANDLE handle; - DWORD flags; - - flags = FILE_FLAG_BACKUP_SEMANTICS; - if (do_lstat) { - flags |= FILE_FLAG_OPEN_REPARSE_POINT; - } - - handle = CreateFileW(req->pathw, - FILE_READ_ATTRIBUTES, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, - OPEN_EXISTING, - flags, - NULL); - if (handle == INVALID_HANDLE_VALUE) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - return; - } - - if (fs__stat_handle(handle, &req->statbuf) != 0) { - DWORD error = GetLastError(); - if (do_lstat && error == ERROR_SYMLINK_NOT_SUPPORTED) { - /* We opened a reparse point but it was not a symlink. Try again. */ - fs__stat_impl(req, 0); - - } else { - /* Stat failed. */ - SET_REQ_WIN32_ERROR(req, GetLastError()); - } - - CloseHandle(handle); - return; - } - - req->ptr = &req->statbuf; - req->result = 0; - CloseHandle(handle); -} - - -static void fs__stat(uv_fs_t* req) { - fs__stat_prepare_path(req->pathw); - fs__stat_impl(req, 0); -} - - -static void fs__lstat(uv_fs_t* req) { - fs__stat_prepare_path(req->pathw); - fs__stat_impl(req, 1); -} - - -static void fs__fstat(uv_fs_t* req) { - int fd = req->fd; - HANDLE handle; - - VERIFY_FD(fd, req); - - handle = uv__get_osfhandle(fd); - - if (handle == INVALID_HANDLE_VALUE) { - SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE); - return; - } - - if (fs__stat_handle(handle, &req->statbuf) != 0) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - return; - } - - req->ptr = &req->statbuf; - req->result = 0; -} - - -static void fs__rename(uv_fs_t* req) { - if (!MoveFileExW(req->pathw, req->new_pathw, MOVEFILE_REPLACE_EXISTING)) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - return; - } - - SET_REQ_RESULT(req, 0); -} - - -INLINE static void fs__sync_impl(uv_fs_t* req) { - int fd = req->fd; - int result; - - VERIFY_FD(fd, req); - - result = FlushFileBuffers(uv__get_osfhandle(fd)) ? 0 : -1; - if (result == -1) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - } else { - SET_REQ_RESULT(req, result); - } -} - - -static void fs__fsync(uv_fs_t* req) { - fs__sync_impl(req); -} - - -static void fs__fdatasync(uv_fs_t* req) { - fs__sync_impl(req); -} - - -static void fs__ftruncate(uv_fs_t* req) { - int fd = req->fd; - HANDLE handle; - NTSTATUS status; - IO_STATUS_BLOCK io_status; - FILE_END_OF_FILE_INFORMATION eof_info; - - VERIFY_FD(fd, req); - - handle = uv__get_osfhandle(fd); - - eof_info.EndOfFile.QuadPart = req->offset; - - status = pNtSetInformationFile(handle, - &io_status, - &eof_info, - sizeof eof_info, - FileEndOfFileInformation); - - if (NT_SUCCESS(status)) { - SET_REQ_RESULT(req, 0); - } else { - SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status)); - } -} - - -static void fs__sendfile(uv_fs_t* req) { - int fd_in = req->fd, fd_out = req->fd_out; - size_t length = req->bufsml[0].len; - int64_t offset = req->offset; - const size_t max_buf_size = 65536; - size_t buf_size = length < max_buf_size ? length : max_buf_size; - int n, result = 0; - int64_t result_offset = 0; - char* buf = (char*) malloc(buf_size); - if (!buf) { - uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); - } - - if (offset != -1) { - result_offset = _lseeki64(fd_in, offset, SEEK_SET); - } - - if (result_offset == -1) { - result = -1; - } else { - while (length > 0) { - n = _read(fd_in, buf, length < buf_size ? length : buf_size); - if (n == 0) { - break; - } else if (n == -1) { - result = -1; - break; - } - - length -= n; - - n = _write(fd_out, buf, n); - if (n == -1) { - result = -1; - break; - } - - result += n; - } - } - - free(buf); - - SET_REQ_RESULT(req, result); -} - - -static void fs__access(uv_fs_t* req) { - DWORD attr = GetFileAttributesW(req->pathw); - - if (attr == INVALID_FILE_ATTRIBUTES) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - return; - } - - if ((req->flags & W_OK) && - ((attr & FILE_ATTRIBUTE_READONLY) || - (attr & FILE_ATTRIBUTE_DIRECTORY))) { - SET_REQ_WIN32_ERROR(req, UV_EPERM); - return; - } - - SET_REQ_RESULT(req, 0); -} - - -static void fs__chmod(uv_fs_t* req) { - int result = _wchmod(req->pathw, req->mode); - SET_REQ_RESULT(req, result); -} - - -static void fs__fchmod(uv_fs_t* req) { - int fd = req->fd; - HANDLE handle; - NTSTATUS nt_status; - IO_STATUS_BLOCK io_status; - FILE_BASIC_INFORMATION file_info; - - VERIFY_FD(fd, req); - - handle = uv__get_osfhandle(fd); - - nt_status = pNtQueryInformationFile(handle, - &io_status, - &file_info, - sizeof file_info, - FileBasicInformation); - - if (!NT_SUCCESS(nt_status)) { - SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status)); - return; - } - - if (req->mode & _S_IWRITE) { - file_info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY; - } else { - file_info.FileAttributes |= FILE_ATTRIBUTE_READONLY; - } - - nt_status = pNtSetInformationFile(handle, - &io_status, - &file_info, - sizeof file_info, - FileBasicInformation); - - if (!NT_SUCCESS(nt_status)) { - SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status)); - return; - } - - SET_REQ_SUCCESS(req); -} - - -INLINE static int fs__utime_handle(HANDLE handle, double atime, double mtime) { - FILETIME filetime_a, filetime_m; - - TIME_T_TO_FILETIME((time_t) atime, &filetime_a); - TIME_T_TO_FILETIME((time_t) mtime, &filetime_m); - - if (!SetFileTime(handle, NULL, &filetime_a, &filetime_m)) { - return -1; - } - - return 0; -} - - -static void fs__utime(uv_fs_t* req) { - HANDLE handle; - - handle = CreateFileW(req->pathw, - FILE_WRITE_ATTRIBUTES, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS, - NULL); - - if (handle == INVALID_HANDLE_VALUE) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - return; - } - - if (fs__utime_handle(handle, req->atime, req->mtime) != 0) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - CloseHandle(handle); - return; - } - - CloseHandle(handle); - - req->result = 0; -} - - -static void fs__futime(uv_fs_t* req) { - int fd = req->fd; - HANDLE handle; - VERIFY_FD(fd, req); - - handle = uv__get_osfhandle(fd); - - if (handle == INVALID_HANDLE_VALUE) { - SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE); - return; - } - - if (fs__utime_handle(handle, req->atime, req->mtime) != 0) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - return; - } - - req->result = 0; -} - - -static void fs__link(uv_fs_t* req) { - DWORD r = CreateHardLinkW(req->new_pathw, req->pathw, NULL); - if (r == 0) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - } else { - req->result = 0; - } -} - - -static void fs__create_junction(uv_fs_t* req, const WCHAR* path, - const WCHAR* new_path) { - HANDLE handle = INVALID_HANDLE_VALUE; - REPARSE_DATA_BUFFER *buffer = NULL; - int created = 0; - int target_len; - int is_absolute, is_long_path; - int needed_buf_size, used_buf_size, used_data_size, path_buf_len; - int start, len, i; - int add_slash; - DWORD bytes; - WCHAR* path_buf; - - target_len = wcslen(path); - is_long_path = wcsncmp(path, LONG_PATH_PREFIX, LONG_PATH_PREFIX_LEN) == 0; - - if (is_long_path) { - is_absolute = 1; - } else { - is_absolute = target_len >= 3 && IS_LETTER(path[0]) && - path[1] == L':' && IS_SLASH(path[2]); - } - - if (!is_absolute) { - /* Not supporting relative paths */ - SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_NOT_SUPPORTED); - return; - } - - /* Do a pessimistic calculation of the required buffer size */ - needed_buf_size = - FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) + - JUNCTION_PREFIX_LEN * sizeof(WCHAR) + - 2 * (target_len + 2) * sizeof(WCHAR); - - /* Allocate the buffer */ - buffer = (REPARSE_DATA_BUFFER*)malloc(needed_buf_size); - if (!buffer) { - uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); - } - - /* Grab a pointer to the part of the buffer where filenames go */ - path_buf = (WCHAR*)&(buffer->MountPointReparseBuffer.PathBuffer); - path_buf_len = 0; - - /* Copy the substitute (internal) target path */ - start = path_buf_len; - - wcsncpy((WCHAR*)&path_buf[path_buf_len], JUNCTION_PREFIX, - JUNCTION_PREFIX_LEN); - path_buf_len += JUNCTION_PREFIX_LEN; - - add_slash = 0; - for (i = is_long_path ? LONG_PATH_PREFIX_LEN : 0; path[i] != L'\0'; i++) { - if (IS_SLASH(path[i])) { - add_slash = 1; - continue; - } - - if (add_slash) { - path_buf[path_buf_len++] = L'\\'; - add_slash = 0; - } - - path_buf[path_buf_len++] = path[i]; - } - path_buf[path_buf_len++] = L'\\'; - len = path_buf_len - start; - - /* Set the info about the substitute name */ - buffer->MountPointReparseBuffer.SubstituteNameOffset = start * sizeof(WCHAR); - buffer->MountPointReparseBuffer.SubstituteNameLength = len * sizeof(WCHAR); - - /* Insert null terminator */ - path_buf[path_buf_len++] = L'\0'; - - /* Copy the print name of the target path */ - start = path_buf_len; - add_slash = 0; - for (i = is_long_path ? LONG_PATH_PREFIX_LEN : 0; path[i] != L'\0'; i++) { - if (IS_SLASH(path[i])) { - add_slash = 1; - continue; - } - - if (add_slash) { - path_buf[path_buf_len++] = L'\\'; - add_slash = 0; - } - - path_buf[path_buf_len++] = path[i]; - } - len = path_buf_len - start; - if (len == 2) { - path_buf[path_buf_len++] = L'\\'; - len++; - } - - /* Set the info about the print name */ - buffer->MountPointReparseBuffer.PrintNameOffset = start * sizeof(WCHAR); - buffer->MountPointReparseBuffer.PrintNameLength = len * sizeof(WCHAR); - - /* Insert another null terminator */ - path_buf[path_buf_len++] = L'\0'; - - /* Calculate how much buffer space was actually used */ - used_buf_size = FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) + - path_buf_len * sizeof(WCHAR); - used_data_size = used_buf_size - - FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer); - - /* Put general info in the data buffer */ - buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; - buffer->ReparseDataLength = used_data_size; - buffer->Reserved = 0; - - /* Create a new directory */ - if (!CreateDirectoryW(new_path, NULL)) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - goto error; - } - created = 1; - - /* Open the directory */ - handle = CreateFileW(new_path, - GENERIC_WRITE, - 0, - NULL, - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS | - FILE_FLAG_OPEN_REPARSE_POINT, - NULL); - if (handle == INVALID_HANDLE_VALUE) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - goto error; - } - - /* Create the actual reparse point */ - if (!DeviceIoControl(handle, - FSCTL_SET_REPARSE_POINT, - buffer, - used_buf_size, - NULL, - 0, - &bytes, - NULL)) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - goto error; - } - - /* Clean up */ - CloseHandle(handle); - free(buffer); - - SET_REQ_RESULT(req, 0); - return; - -error: - free(buffer); - - if (handle != INVALID_HANDLE_VALUE) { - CloseHandle(handle); - } - - if (created) { - RemoveDirectoryW(new_path); - } -} - - -static void fs__symlink(uv_fs_t* req) { - WCHAR* pathw = req->pathw; - WCHAR* new_pathw = req->new_pathw; - int flags = req->file_flags; - int result; - - - if (flags & UV_FS_SYMLINK_JUNCTION) { - fs__create_junction(req, pathw, new_pathw); - } else if (pCreateSymbolicLinkW) { - result = pCreateSymbolicLinkW(new_pathw, - pathw, - flags & UV_FS_SYMLINK_DIR ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0) ? 0 : -1; - if (result == -1) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - } else { - SET_REQ_RESULT(req, result); - } - } else { - SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED); - } -} - - -static void fs__readlink(uv_fs_t* req) { - HANDLE handle; - - handle = CreateFileW(req->pathw, - 0, - 0, - NULL, - OPEN_EXISTING, - FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, - NULL); - - if (handle == INVALID_HANDLE_VALUE) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - return; - } - - if (fs__readlink_handle(handle, (char**) &req->ptr, NULL) != 0) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - CloseHandle(handle); - return; - } - - req->flags |= UV_FS_FREE_PTR; - SET_REQ_RESULT(req, 0); - - CloseHandle(handle); -} - - - -static void fs__chown(uv_fs_t* req) { - req->result = 0; -} - - -static void fs__fchown(uv_fs_t* req) { - req->result = 0; -} - - -static void uv__fs_work(struct uv__work* w) { - uv_fs_t* req; - - req = container_of(w, uv_fs_t, work_req); - assert(req->type == UV_FS); - -#define XX(uc, lc) case UV_FS_##uc: fs__##lc(req); break; - switch (req->fs_type) { - XX(OPEN, open) - XX(CLOSE, close) - XX(READ, read) - XX(WRITE, write) - XX(SENDFILE, sendfile) - XX(STAT, stat) - XX(LSTAT, lstat) - XX(FSTAT, fstat) - XX(FTRUNCATE, ftruncate) - XX(UTIME, utime) - XX(FUTIME, futime) - XX(ACCESS, access) - XX(CHMOD, chmod) - XX(FCHMOD, fchmod) - XX(FSYNC, fsync) - XX(FDATASYNC, fdatasync) - XX(UNLINK, unlink) - XX(RMDIR, rmdir) - XX(MKDIR, mkdir) - XX(MKDTEMP, mkdtemp) - XX(RENAME, rename) - XX(SCANDIR, scandir) - XX(LINK, link) - XX(SYMLINK, symlink) - XX(READLINK, readlink) - XX(CHOWN, chown) - XX(FCHOWN, fchown); - default: - assert(!"bad uv_fs_type"); - } -} - - -static void uv__fs_done(struct uv__work* w, int status) { - uv_fs_t* req; - - req = container_of(w, uv_fs_t, work_req); - uv__req_unregister(req->loop, req); - - if (status == UV_ECANCELED) { - assert(req->result == 0); - req->result = UV_ECANCELED; - } - - if (req->cb != NULL) - req->cb(req); -} - - -void uv_fs_req_cleanup(uv_fs_t* req) { - if (req->flags & UV_FS_CLEANEDUP) - return; - - if (req->flags & UV_FS_FREE_PATHS) - free(req->pathw); - - if (req->flags & UV_FS_FREE_PTR) - free(req->ptr); - - req->path = NULL; - req->pathw = NULL; - req->new_pathw = NULL; - req->ptr = NULL; - - req->flags |= UV_FS_CLEANEDUP; -} - - -int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, - int mode, uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_OPEN, cb); - - err = fs__capture_path(loop, req, path, NULL, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - req->file_flags = flags; - req->mode = mode; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__open(req); - return req->result; - } -} - - -int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_CLOSE, cb); - req->fd = fd; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__close(req); - return req->result; - } -} - - -int uv_fs_read(uv_loop_t* loop, - uv_fs_t* req, - uv_file fd, - const uv_buf_t bufs[], - unsigned int nbufs, - int64_t offset, - uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_READ, cb); - - req->fd = fd; - - req->nbufs = nbufs; - req->bufs = req->bufsml; - if (nbufs > ARRAY_SIZE(req->bufsml)) - req->bufs = malloc(nbufs * sizeof(*bufs)); - - if (req->bufs == NULL) - return UV_ENOMEM; - - memcpy(req->bufs, bufs, nbufs * sizeof(*bufs)); - - req->offset = offset; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__read(req); - return req->result; - } -} - - -int uv_fs_write(uv_loop_t* loop, - uv_fs_t* req, - uv_file fd, - const uv_buf_t bufs[], - unsigned int nbufs, - int64_t offset, - uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_WRITE, cb); - - req->fd = fd; - - req->nbufs = nbufs; - req->bufs = req->bufsml; - if (nbufs > ARRAY_SIZE(req->bufsml)) - req->bufs = malloc(nbufs * sizeof(*bufs)); - - if (req->bufs == NULL) - return UV_ENOMEM; - - memcpy(req->bufs, bufs, nbufs * sizeof(*bufs)); - - req->offset = offset; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__write(req); - return req->result; - } -} - - -int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, - uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_UNLINK, cb); - - err = fs__capture_path(loop, req, path, NULL, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__unlink(req); - return req->result; - } -} - - -int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, - uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_MKDIR, cb); - - err = fs__capture_path(loop, req, path, NULL, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - req->mode = mode; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__mkdir(req); - return req->result; - } -} - - -int uv_fs_mkdtemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl, - uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_MKDTEMP, cb); - - err = fs__capture_path(loop, req, tpl, NULL, TRUE); - if (err) - return uv_translate_sys_error(err); - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__mkdtemp(req); - return req->result; - } -} - - -int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_RMDIR, cb); - - err = fs__capture_path(loop, req, path, NULL, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__rmdir(req); - return req->result; - } -} - - -int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, - uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_SCANDIR, cb); - - err = fs__capture_path(loop, req, path, NULL, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - req->file_flags = flags; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__scandir(req); - return req->result; - } -} - - -int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, - const char* new_path, uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_LINK, cb); - - err = fs__capture_path(loop, req, path, new_path, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__link(req); - return req->result; - } -} - - -int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path, - const char* new_path, int flags, uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_SYMLINK, cb); - - err = fs__capture_path(loop, req, path, new_path, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - req->file_flags = flags; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__symlink(req); - return req->result; - } -} - - -int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path, - uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_READLINK, cb); - - err = fs__capture_path(loop, req, path, NULL, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__readlink(req); - return req->result; - } -} - - -int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, - uv_gid_t gid, uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_CHOWN, cb); - - err = fs__capture_path(loop, req, path, NULL, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__chown(req); - return req->result; - } -} - - -int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_uid_t uid, - uv_gid_t gid, uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_FCHOWN, cb); - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__fchown(req); - return req->result; - } -} - - -int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_STAT, cb); - - err = fs__capture_path(loop, req, path, NULL, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__stat(req); - return req->result; - } -} - - -int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_LSTAT, cb); - - err = fs__capture_path(loop, req, path, NULL, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__lstat(req); - return req->result; - } -} - - -int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_FSTAT, cb); - req->fd = fd; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__fstat(req); - return req->result; - } -} - - -int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path, - const char* new_path, uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_RENAME, cb); - - err = fs__capture_path(loop, req, path, new_path, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__rename(req); - return req->result; - } -} - - -int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_FSYNC, cb); - req->fd = fd; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__fsync(req); - return req->result; - } -} - - -int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_FDATASYNC, cb); - req->fd = fd; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__fdatasync(req); - return req->result; - } -} - - -int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file fd, - int64_t offset, uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_FTRUNCATE, cb); - - req->fd = fd; - req->offset = offset; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__ftruncate(req); - return req->result; - } -} - - - -int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file fd_out, - uv_file fd_in, int64_t in_offset, size_t length, uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_SENDFILE, cb); - - req->fd = fd_in; - req->fd_out = fd_out; - req->offset = in_offset; - req->bufsml[0].len = length; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__sendfile(req); - return req->result; - } -} - - -int uv_fs_access(uv_loop_t* loop, - uv_fs_t* req, - const char* path, - int flags, - uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_ACCESS, cb); - - err = fs__capture_path(loop, req, path, NULL, cb != NULL); - if (err) - return uv_translate_sys_error(err); - - req->flags = flags; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } - - fs__access(req); - return req->result; -} - - -int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, - uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_CHMOD, cb); - - err = fs__capture_path(loop, req, path, NULL, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - req->mode = mode; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__chmod(req); - return req->result; - } -} - - -int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file fd, int mode, - uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_FCHMOD, cb); - - req->fd = fd; - req->mode = mode; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__fchmod(req); - return req->result; - } -} - - -int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, - double mtime, uv_fs_cb cb) { - int err; - - uv_fs_req_init(loop, req, UV_FS_UTIME, cb); - - err = fs__capture_path(loop, req, path, NULL, cb != NULL); - if (err) { - return uv_translate_sys_error(err); - } - - req->atime = atime; - req->mtime = mtime; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__utime(req); - return req->result; - } -} - - -int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file fd, double atime, - double mtime, uv_fs_cb cb) { - uv_fs_req_init(loop, req, UV_FS_FUTIME, cb); - - req->fd = fd; - req->atime = atime; - req->mtime = mtime; - - if (cb) { - QUEUE_FS_TP_JOB(loop, req); - return 0; - } else { - fs__futime(req); - return req->result; - } -} diff --git a/libuv/src/win/getaddrinfo.c b/libuv/src/win/getaddrinfo.c deleted file mode 100644 index f103f5f..0000000 --- a/libuv/src/win/getaddrinfo.c +++ /dev/null @@ -1,362 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include - -#include "uv.h" -#include "internal.h" -#include "req-inl.h" - -/* EAI_* constants. */ -#include - - -int uv__getaddrinfo_translate_error(int sys_err) { - switch (sys_err) { - case 0: return 0; - case WSATRY_AGAIN: return UV_EAI_AGAIN; - case WSAEINVAL: return UV_EAI_BADFLAGS; - case WSANO_RECOVERY: return UV_EAI_FAIL; - case WSAEAFNOSUPPORT: return UV_EAI_FAMILY; - case WSA_NOT_ENOUGH_MEMORY: return UV_EAI_MEMORY; - case WSAHOST_NOT_FOUND: return UV_EAI_NONAME; - case WSATYPE_NOT_FOUND: return UV_EAI_SERVICE; - case WSAESOCKTNOSUPPORT: return UV_EAI_SOCKTYPE; - default: return uv_translate_sys_error(sys_err); - } -} - - -/* - * MinGW is missing this - */ -#if !defined(_MSC_VER) && !defined(__MINGW64_VERSION_MAJOR) - typedef struct addrinfoW { - int ai_flags; - int ai_family; - int ai_socktype; - int ai_protocol; - size_t ai_addrlen; - WCHAR* ai_canonname; - struct sockaddr* ai_addr; - struct addrinfoW* ai_next; - } ADDRINFOW, *PADDRINFOW; - - DECLSPEC_IMPORT int WSAAPI GetAddrInfoW(const WCHAR* node, - const WCHAR* service, - const ADDRINFOW* hints, - PADDRINFOW* result); - - DECLSPEC_IMPORT void WSAAPI FreeAddrInfoW(PADDRINFOW pAddrInfo); -#endif - - -/* adjust size value to be multiple of 4. Use to keep pointer aligned */ -/* Do we need different versions of this for different architectures? */ -#define ALIGNED_SIZE(X) ((((X) + 3) >> 2) << 2) - - -static void uv__getaddrinfo_work(struct uv__work* w) { - uv_getaddrinfo_t* req; - struct addrinfoW* hints; - int err; - - req = container_of(w, uv_getaddrinfo_t, work_req); - hints = req->addrinfow; - req->addrinfow = NULL; - err = GetAddrInfoW(req->node, req->service, hints, &req->addrinfow); - req->retcode = uv__getaddrinfo_translate_error(err); -} - - -/* - * Called from uv_run when complete. Call user specified callback - * then free returned addrinfo - * Returned addrinfo strings are converted from UTF-16 to UTF-8. - * - * To minimize allocation we calculate total size required, - * and copy all structs and referenced strings into the one block. - * Each size calculation is adjusted to avoid unaligned pointers. - */ -static void uv__getaddrinfo_done(struct uv__work* w, int status) { - uv_getaddrinfo_t* req; - int addrinfo_len = 0; - int name_len = 0; - size_t addrinfo_struct_len = ALIGNED_SIZE(sizeof(struct addrinfo)); - struct addrinfoW* addrinfow_ptr; - struct addrinfo* addrinfo_ptr; - char* alloc_ptr = NULL; - char* cur_ptr = NULL; - - req = container_of(w, uv_getaddrinfo_t, work_req); - - /* release input parameter memory */ - if (req->alloc != NULL) { - free(req->alloc); - req->alloc = NULL; - } - - if (status == UV_ECANCELED) { - assert(req->retcode == 0); - req->retcode = UV_EAI_CANCELED; - goto complete; - } - - if (req->retcode == 0) { - /* convert addrinfoW to addrinfo */ - /* first calculate required length */ - addrinfow_ptr = req->addrinfow; - while (addrinfow_ptr != NULL) { - addrinfo_len += addrinfo_struct_len + - ALIGNED_SIZE(addrinfow_ptr->ai_addrlen); - if (addrinfow_ptr->ai_canonname != NULL) { - name_len = uv_utf16_to_utf8(addrinfow_ptr->ai_canonname, -1, NULL, 0); - if (name_len == 0) { - req->retcode = uv_translate_sys_error(GetLastError()); - goto complete; - } - addrinfo_len += ALIGNED_SIZE(name_len); - } - addrinfow_ptr = addrinfow_ptr->ai_next; - } - - /* allocate memory for addrinfo results */ - alloc_ptr = (char*)malloc(addrinfo_len); - - /* do conversions */ - if (alloc_ptr != NULL) { - cur_ptr = alloc_ptr; - addrinfow_ptr = req->addrinfow; - - while (addrinfow_ptr != NULL) { - /* copy addrinfo struct data */ - assert(cur_ptr + addrinfo_struct_len <= alloc_ptr + addrinfo_len); - addrinfo_ptr = (struct addrinfo*)cur_ptr; - addrinfo_ptr->ai_family = addrinfow_ptr->ai_family; - addrinfo_ptr->ai_socktype = addrinfow_ptr->ai_socktype; - addrinfo_ptr->ai_protocol = addrinfow_ptr->ai_protocol; - addrinfo_ptr->ai_flags = addrinfow_ptr->ai_flags; - addrinfo_ptr->ai_addrlen = addrinfow_ptr->ai_addrlen; - addrinfo_ptr->ai_canonname = NULL; - addrinfo_ptr->ai_addr = NULL; - addrinfo_ptr->ai_next = NULL; - - cur_ptr += addrinfo_struct_len; - - /* copy sockaddr */ - if (addrinfo_ptr->ai_addrlen > 0) { - assert(cur_ptr + addrinfo_ptr->ai_addrlen <= - alloc_ptr + addrinfo_len); - memcpy(cur_ptr, addrinfow_ptr->ai_addr, addrinfo_ptr->ai_addrlen); - addrinfo_ptr->ai_addr = (struct sockaddr*)cur_ptr; - cur_ptr += ALIGNED_SIZE(addrinfo_ptr->ai_addrlen); - } - - /* convert canonical name to UTF-8 */ - if (addrinfow_ptr->ai_canonname != NULL) { - name_len = uv_utf16_to_utf8(addrinfow_ptr->ai_canonname, - -1, - NULL, - 0); - assert(name_len > 0); - assert(cur_ptr + name_len <= alloc_ptr + addrinfo_len); - name_len = uv_utf16_to_utf8(addrinfow_ptr->ai_canonname, - -1, - cur_ptr, - name_len); - assert(name_len > 0); - addrinfo_ptr->ai_canonname = cur_ptr; - cur_ptr += ALIGNED_SIZE(name_len); - } - assert(cur_ptr <= alloc_ptr + addrinfo_len); - - /* set next ptr */ - addrinfow_ptr = addrinfow_ptr->ai_next; - if (addrinfow_ptr != NULL) { - addrinfo_ptr->ai_next = (struct addrinfo*)cur_ptr; - } - } - req->addrinfo = (struct addrinfo*)alloc_ptr; - } else { - req->retcode = UV_EAI_MEMORY; - } - } - - /* return memory to system */ - if (req->addrinfow != NULL) { - FreeAddrInfoW(req->addrinfow); - req->addrinfow = NULL; - } - -complete: - uv__req_unregister(req->loop, req); - - /* finally do callback with converted result */ - if (req->getaddrinfo_cb) - req->getaddrinfo_cb(req, req->retcode, req->addrinfo); -} - - -void uv_freeaddrinfo(struct addrinfo* ai) { - char* alloc_ptr = (char*)ai; - - /* release copied result memory */ - if (alloc_ptr != NULL) { - free(alloc_ptr); - } -} - - -/* - * Entry point for getaddrinfo - * we convert the UTF-8 strings to UNICODE - * and save the UNICODE string pointers in the req - * We also copy hints so that caller does not need to keep memory until the - * callback. - * return 0 if a callback will be made - * return error code if validation fails - * - * To minimize allocation we calculate total size required, - * and copy all structs and referenced strings into the one block. - * Each size calculation is adjusted to avoid unaligned pointers. - */ -int uv_getaddrinfo(uv_loop_t* loop, - uv_getaddrinfo_t* req, - uv_getaddrinfo_cb getaddrinfo_cb, - const char* node, - const char* service, - const struct addrinfo* hints) { - int nodesize = 0; - int servicesize = 0; - int hintssize = 0; - char* alloc_ptr = NULL; - int err; - - if (req == NULL || (node == NULL && service == NULL)) { - err = WSAEINVAL; - goto error; - } - - uv_req_init(loop, (uv_req_t*)req); - - req->getaddrinfo_cb = getaddrinfo_cb; - req->addrinfo = NULL; - req->type = UV_GETADDRINFO; - req->loop = loop; - req->retcode = 0; - - /* calculate required memory size for all input values */ - if (node != NULL) { - nodesize = ALIGNED_SIZE(uv_utf8_to_utf16(node, NULL, 0) * sizeof(WCHAR)); - if (nodesize == 0) { - err = GetLastError(); - goto error; - } - } - - if (service != NULL) { - servicesize = ALIGNED_SIZE(uv_utf8_to_utf16(service, NULL, 0) * - sizeof(WCHAR)); - if (servicesize == 0) { - err = GetLastError(); - goto error; - } - } - if (hints != NULL) { - hintssize = ALIGNED_SIZE(sizeof(struct addrinfoW)); - } - - /* allocate memory for inputs, and partition it as needed */ - alloc_ptr = (char*)malloc(nodesize + servicesize + hintssize); - if (!alloc_ptr) { - err = WSAENOBUFS; - goto error; - } - - /* save alloc_ptr now so we can free if error */ - req->alloc = (void*)alloc_ptr; - - /* convert node string to UTF16 into allocated memory and save pointer in */ - /* the request. */ - if (node != NULL) { - req->node = (WCHAR*)alloc_ptr; - if (uv_utf8_to_utf16(node, - (WCHAR*) alloc_ptr, - nodesize / sizeof(WCHAR)) == 0) { - err = GetLastError(); - goto error; - } - alloc_ptr += nodesize; - } else { - req->node = NULL; - } - - /* convert service string to UTF16 into allocated memory and save pointer */ - /* in the req. */ - if (service != NULL) { - req->service = (WCHAR*)alloc_ptr; - if (uv_utf8_to_utf16(service, - (WCHAR*) alloc_ptr, - servicesize / sizeof(WCHAR)) == 0) { - err = GetLastError(); - goto error; - } - alloc_ptr += servicesize; - } else { - req->service = NULL; - } - - /* copy hints to allocated memory and save pointer in req */ - if (hints != NULL) { - req->addrinfow = (struct addrinfoW*)alloc_ptr; - req->addrinfow->ai_family = hints->ai_family; - req->addrinfow->ai_socktype = hints->ai_socktype; - req->addrinfow->ai_protocol = hints->ai_protocol; - req->addrinfow->ai_flags = hints->ai_flags; - req->addrinfow->ai_addrlen = 0; - req->addrinfow->ai_canonname = NULL; - req->addrinfow->ai_addr = NULL; - req->addrinfow->ai_next = NULL; - } else { - req->addrinfow = NULL; - } - - uv__req_register(loop, req); - - if (getaddrinfo_cb) { - uv__work_submit(loop, - &req->work_req, - uv__getaddrinfo_work, - uv__getaddrinfo_done); - return 0; - } else { - uv__getaddrinfo_work(&req->work_req); - uv__getaddrinfo_done(&req->work_req, 0); - return req->retcode; - } - -error: - if (req != NULL && req->alloc != NULL) { - free(req->alloc); - } - return uv_translate_sys_error(err); -} diff --git a/libuv/src/win/getnameinfo.c b/libuv/src/win/getnameinfo.c deleted file mode 100644 index b1d045c..0000000 --- a/libuv/src/win/getnameinfo.c +++ /dev/null @@ -1,151 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to -* deal in the Software without restriction, including without limitation the -* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -* sell copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -* IN THE SOFTWARE. -*/ - -#include -#include -#include - -#include "uv.h" -#include "internal.h" -#include "req-inl.h" - -#ifndef GetNameInfo -int WSAAPI GetNameInfoW( - const SOCKADDR *pSockaddr, - socklen_t SockaddrLength, - PWCHAR pNodeBuffer, - DWORD NodeBufferSize, - PWCHAR pServiceBuffer, - DWORD ServiceBufferSize, - INT Flags -); -#endif - -static void uv__getnameinfo_work(struct uv__work* w) { - uv_getnameinfo_t* req; - WCHAR host[NI_MAXHOST]; - WCHAR service[NI_MAXSERV]; - int ret = 0; - - req = container_of(w, uv_getnameinfo_t, work_req); - if (GetNameInfoW((struct sockaddr*)&req->storage, - sizeof(req->storage), - host, - ARRAY_SIZE(host), - service, - ARRAY_SIZE(service), - req->flags)) { - ret = WSAGetLastError(); - } - req->retcode = uv__getaddrinfo_translate_error(ret); - - /* convert results to UTF-8 */ - WideCharToMultiByte(CP_UTF8, - 0, - host, - -1, - req->host, - sizeof(req->host), - NULL, - NULL); - - WideCharToMultiByte(CP_UTF8, - 0, - service, - -1, - req->service, - sizeof(req->service), - NULL, - NULL); -} - - -/* -* Called from uv_run when complete. -*/ -static void uv__getnameinfo_done(struct uv__work* w, int status) { - uv_getnameinfo_t* req; - char* host; - char* service; - - req = container_of(w, uv_getnameinfo_t, work_req); - uv__req_unregister(req->loop, req); - host = service = NULL; - - if (status == UV_ECANCELED) { - assert(req->retcode == 0); - req->retcode = UV_EAI_CANCELED; - } else if (req->retcode == 0) { - host = req->host; - service = req->service; - } - - if (req->getnameinfo_cb) - req->getnameinfo_cb(req, req->retcode, host, service); -} - - -/* -* Entry point for getnameinfo -* return 0 if a callback will be made -* return error code if validation fails -*/ -int uv_getnameinfo(uv_loop_t* loop, - uv_getnameinfo_t* req, - uv_getnameinfo_cb getnameinfo_cb, - const struct sockaddr* addr, - int flags) { - if (req == NULL || addr == NULL) - return UV_EINVAL; - - if (addr->sa_family == AF_INET) { - memcpy(&req->storage, - addr, - sizeof(struct sockaddr_in)); - } else if (addr->sa_family == AF_INET6) { - memcpy(&req->storage, - addr, - sizeof(struct sockaddr_in6)); - } else { - return UV_EINVAL; - } - - uv_req_init(loop, (uv_req_t*)req); - uv__req_register(loop, req); - - req->getnameinfo_cb = getnameinfo_cb; - req->flags = flags; - req->type = UV_GETNAMEINFO; - req->loop = loop; - req->retcode = 0; - - if (getnameinfo_cb) { - uv__work_submit(loop, - &req->work_req, - uv__getnameinfo_work, - uv__getnameinfo_done); - return 0; - } else { - uv__getnameinfo_work(&req->work_req); - uv__getnameinfo_done(&req->work_req, 0); - return req->retcode; - } -} diff --git a/libuv/src/win/handle-inl.h b/libuv/src/win/handle-inl.h deleted file mode 100644 index 8d0334c..0000000 --- a/libuv/src/win/handle-inl.h +++ /dev/null @@ -1,179 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_WIN_HANDLE_INL_H_ -#define UV_WIN_HANDLE_INL_H_ - -#include -#include - -#include "uv.h" -#include "internal.h" - - -#define DECREASE_ACTIVE_COUNT(loop, handle) \ - do { \ - if (--(handle)->activecnt == 0 && \ - !((handle)->flags & UV__HANDLE_CLOSING)) { \ - uv__handle_stop((handle)); \ - } \ - assert((handle)->activecnt >= 0); \ - } while (0) - - -#define INCREASE_ACTIVE_COUNT(loop, handle) \ - do { \ - if ((handle)->activecnt++ == 0) { \ - uv__handle_start((handle)); \ - } \ - assert((handle)->activecnt > 0); \ - } while (0) - - -#define DECREASE_PENDING_REQ_COUNT(handle) \ - do { \ - assert(handle->reqs_pending > 0); \ - handle->reqs_pending--; \ - \ - if (handle->flags & UV__HANDLE_CLOSING && \ - handle->reqs_pending == 0) { \ - uv_want_endgame(loop, (uv_handle_t*)handle); \ - } \ - } while (0) - - -#define uv__handle_closing(handle) \ - do { \ - assert(!((handle)->flags & UV__HANDLE_CLOSING)); \ - \ - if (!(((handle)->flags & UV__HANDLE_ACTIVE) && \ - ((handle)->flags & UV__HANDLE_REF))) \ - uv__active_handle_add((uv_handle_t*) (handle)); \ - \ - (handle)->flags |= UV__HANDLE_CLOSING; \ - (handle)->flags &= ~UV__HANDLE_ACTIVE; \ - } while (0) - - -#define uv__handle_close(handle) \ - do { \ - QUEUE_REMOVE(&(handle)->handle_queue); \ - uv__active_handle_rm((uv_handle_t*) (handle)); \ - \ - (handle)->flags |= UV_HANDLE_CLOSED; \ - \ - if ((handle)->close_cb) \ - (handle)->close_cb((uv_handle_t*) (handle)); \ - } while (0) - - -INLINE static void uv_want_endgame(uv_loop_t* loop, uv_handle_t* handle) { - if (!(handle->flags & UV_HANDLE_ENDGAME_QUEUED)) { - handle->flags |= UV_HANDLE_ENDGAME_QUEUED; - - handle->endgame_next = loop->endgame_handles; - loop->endgame_handles = handle; - } -} - - -INLINE static void uv_process_endgames(uv_loop_t* loop) { - uv_handle_t* handle; - - while (loop->endgame_handles) { - handle = loop->endgame_handles; - loop->endgame_handles = handle->endgame_next; - - handle->flags &= ~UV_HANDLE_ENDGAME_QUEUED; - - switch (handle->type) { - case UV_TCP: - uv_tcp_endgame(loop, (uv_tcp_t*) handle); - break; - - case UV_NAMED_PIPE: - uv_pipe_endgame(loop, (uv_pipe_t*) handle); - break; - - case UV_TTY: - uv_tty_endgame(loop, (uv_tty_t*) handle); - break; - - case UV_UDP: - uv_udp_endgame(loop, (uv_udp_t*) handle); - break; - - case UV_POLL: - uv_poll_endgame(loop, (uv_poll_t*) handle); - break; - - case UV_TIMER: - uv_timer_endgame(loop, (uv_timer_t*) handle); - break; - - case UV_PREPARE: - case UV_CHECK: - case UV_IDLE: - uv_loop_watcher_endgame(loop, handle); - break; - - case UV_ASYNC: - uv_async_endgame(loop, (uv_async_t*) handle); - break; - - case UV_SIGNAL: - uv_signal_endgame(loop, (uv_signal_t*) handle); - break; - - case UV_PROCESS: - uv_process_endgame(loop, (uv_process_t*) handle); - break; - - case UV_FS_EVENT: - uv_fs_event_endgame(loop, (uv_fs_event_t*) handle); - break; - - case UV_FS_POLL: - uv__fs_poll_endgame(loop, (uv_fs_poll_t*) handle); - break; - - default: - assert(0); - break; - } - } -} - -INLINE static HANDLE uv__get_osfhandle(int fd) -{ - /* _get_osfhandle() raises an assert in debug builds if the FD is invalid. */ - /* But it also correctly checks the FD and returns INVALID_HANDLE_VALUE */ - /* for invalid FDs in release builds (or if you let the assert continue). */ - /* So this wrapper function disables asserts when calling _get_osfhandle. */ - - HANDLE handle; - UV_BEGIN_DISABLE_CRT_ASSERT(); - handle = (HANDLE) _get_osfhandle(fd); - UV_END_DISABLE_CRT_ASSERT(); - return handle; -} - -#endif /* UV_WIN_HANDLE_INL_H_ */ diff --git a/libuv/src/win/handle.c b/libuv/src/win/handle.c deleted file mode 100644 index 72b49d9..0000000 --- a/libuv/src/win/handle.c +++ /dev/null @@ -1,154 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include - -#include "uv.h" -#include "internal.h" -#include "handle-inl.h" - - -uv_handle_type uv_guess_handle(uv_file file) { - HANDLE handle; - DWORD mode; - - if (file < 0) { - return UV_UNKNOWN_HANDLE; - } - - handle = uv__get_osfhandle(file); - - switch (GetFileType(handle)) { - case FILE_TYPE_CHAR: - if (GetConsoleMode(handle, &mode)) { - return UV_TTY; - } else { - return UV_FILE; - } - - case FILE_TYPE_PIPE: - return UV_NAMED_PIPE; - - case FILE_TYPE_DISK: - return UV_FILE; - - default: - return UV_UNKNOWN_HANDLE; - } -} - - -int uv_is_active(const uv_handle_t* handle) { - return (handle->flags & UV__HANDLE_ACTIVE) && - !(handle->flags & UV__HANDLE_CLOSING); -} - - -void uv_close(uv_handle_t* handle, uv_close_cb cb) { - uv_loop_t* loop = handle->loop; - - if (handle->flags & UV__HANDLE_CLOSING) { - assert(0); - return; - } - - handle->close_cb = cb; - - /* Handle-specific close actions */ - switch (handle->type) { - case UV_TCP: - uv_tcp_close(loop, (uv_tcp_t*)handle); - return; - - case UV_NAMED_PIPE: - uv_pipe_close(loop, (uv_pipe_t*) handle); - return; - - case UV_TTY: - uv_tty_close((uv_tty_t*) handle); - return; - - case UV_UDP: - uv_udp_close(loop, (uv_udp_t*) handle); - return; - - case UV_POLL: - uv_poll_close(loop, (uv_poll_t*) handle); - return; - - case UV_TIMER: - uv_timer_stop((uv_timer_t*)handle); - uv__handle_closing(handle); - uv_want_endgame(loop, handle); - return; - - case UV_PREPARE: - uv_prepare_stop((uv_prepare_t*)handle); - uv__handle_closing(handle); - uv_want_endgame(loop, handle); - return; - - case UV_CHECK: - uv_check_stop((uv_check_t*)handle); - uv__handle_closing(handle); - uv_want_endgame(loop, handle); - return; - - case UV_IDLE: - uv_idle_stop((uv_idle_t*)handle); - uv__handle_closing(handle); - uv_want_endgame(loop, handle); - return; - - case UV_ASYNC: - uv_async_close(loop, (uv_async_t*) handle); - return; - - case UV_SIGNAL: - uv_signal_close(loop, (uv_signal_t*) handle); - return; - - case UV_PROCESS: - uv_process_close(loop, (uv_process_t*) handle); - return; - - case UV_FS_EVENT: - uv_fs_event_close(loop, (uv_fs_event_t*) handle); - return; - - case UV_FS_POLL: - uv__fs_poll_close((uv_fs_poll_t*) handle); - uv__handle_closing(handle); - uv_want_endgame(loop, handle); - return; - - default: - /* Not supported */ - abort(); - } -} - - -int uv_is_closing(const uv_handle_t* handle) { - return !!(handle->flags & (UV__HANDLE_CLOSING | UV_HANDLE_CLOSED)); -} diff --git a/libuv/src/win/internal.h b/libuv/src/win/internal.h deleted file mode 100644 index 04b2a54..0000000 --- a/libuv/src/win/internal.h +++ /dev/null @@ -1,382 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_WIN_INTERNAL_H_ -#define UV_WIN_INTERNAL_H_ - -#include "uv.h" -#include "../uv-common.h" - -#include "tree.h" -#include "winapi.h" -#include "winsock.h" - -#ifdef _MSC_VER -# define INLINE __inline -# define UV_THREAD_LOCAL __declspec( thread ) -#else -# define INLINE inline -# define UV_THREAD_LOCAL __thread -#endif - - -#ifdef _DEBUG - -extern UV_THREAD_LOCAL int uv__crt_assert_enabled; - -#define UV_BEGIN_DISABLE_CRT_ASSERT() \ - { \ - int uv__saved_crt_assert_enabled = uv__crt_assert_enabled; \ - uv__crt_assert_enabled = FALSE; - - -#define UV_END_DISABLE_CRT_ASSERT() \ - uv__crt_assert_enabled = uv__saved_crt_assert_enabled; \ - } - -#else -#define UV_BEGIN_DISABLE_CRT_ASSERT() -#define UV_END_DISABLE_CRT_ASSERT() -#endif - -/* - * Handles - * (also see handle-inl.h) - */ - -/* Used by all handles. */ -#define UV_HANDLE_CLOSED 0x00000002 -#define UV_HANDLE_ENDGAME_QUEUED 0x00000004 - -/* uv-common.h: #define UV__HANDLE_CLOSING 0x00000001 */ -/* uv-common.h: #define UV__HANDLE_ACTIVE 0x00000040 */ -/* uv-common.h: #define UV__HANDLE_REF 0x00000020 */ -/* uv-common.h: #define UV_HANDLE_INTERNAL 0x00000080 */ - -/* Used by streams and UDP handles. */ -#define UV_HANDLE_READING 0x00000100 -#define UV_HANDLE_BOUND 0x00000200 -#define UV_HANDLE_LISTENING 0x00000800 -#define UV_HANDLE_CONNECTION 0x00001000 -#define UV_HANDLE_CONNECTED 0x00002000 -#define UV_HANDLE_READABLE 0x00008000 -#define UV_HANDLE_WRITABLE 0x00010000 -#define UV_HANDLE_READ_PENDING 0x00020000 -#define UV_HANDLE_SYNC_BYPASS_IOCP 0x00040000 -#define UV_HANDLE_ZERO_READ 0x00080000 -#define UV_HANDLE_EMULATE_IOCP 0x00100000 -#define UV_HANDLE_BLOCKING_WRITES 0x00200000 - -/* Used by uv_tcp_t and uv_udp_t handles */ -#define UV_HANDLE_IPV6 0x01000000 - -/* Only used by uv_tcp_t handles. */ -#define UV_HANDLE_TCP_NODELAY 0x02000000 -#define UV_HANDLE_TCP_KEEPALIVE 0x04000000 -#define UV_HANDLE_TCP_SINGLE_ACCEPT 0x08000000 -#define UV_HANDLE_TCP_ACCEPT_STATE_CHANGING 0x10000000 -#define UV_HANDLE_TCP_SOCKET_CLOSED 0x20000000 -#define UV_HANDLE_SHARED_TCP_SOCKET 0x40000000 - -/* Only used by uv_pipe_t handles. */ -#define UV_HANDLE_NON_OVERLAPPED_PIPE 0x01000000 -#define UV_HANDLE_PIPESERVER 0x02000000 -#define UV_HANDLE_PIPE_READ_CANCELABLE 0x04000000 - -/* Only used by uv_tty_t handles. */ -#define UV_HANDLE_TTY_READABLE 0x01000000 -#define UV_HANDLE_TTY_RAW 0x02000000 -#define UV_HANDLE_TTY_SAVED_POSITION 0x04000000 -#define UV_HANDLE_TTY_SAVED_ATTRIBUTES 0x08000000 - -/* Only used by uv_poll_t handles. */ -#define UV_HANDLE_POLL_SLOW 0x02000000 - - -/* - * Requests: see req-inl.h - */ - - -/* - * Streams: see stream-inl.h - */ - - -/* - * TCP - */ - -typedef struct { - WSAPROTOCOL_INFOW socket_info; - int delayed_error; -} uv__ipc_socket_info_ex; - -int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb); -int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client); -int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb, - uv_read_cb read_cb); -int uv_tcp_write(uv_loop_t* loop, uv_write_t* req, uv_tcp_t* handle, - const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb); -int uv__tcp_try_write(uv_tcp_t* handle, const uv_buf_t bufs[], - unsigned int nbufs); - -void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, uv_req_t* req); -void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle, - uv_write_t* req); -void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle, - uv_req_t* req); -void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle, - uv_connect_t* req); - -void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp); -void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle); - -int uv_tcp_import(uv_tcp_t* tcp, uv__ipc_socket_info_ex* socket_info_ex, - int tcp_connection); - -int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid, - LPWSAPROTOCOL_INFOW protocol_info); - - -/* - * UDP - */ -void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle, uv_req_t* req); -void uv_process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle, - uv_udp_send_t* req); - -void uv_udp_close(uv_loop_t* loop, uv_udp_t* handle); -void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle); - - -/* - * Pipes - */ -int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access, - char* name, size_t nameSize); - -int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb); -int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client); -int uv_pipe_read_start(uv_pipe_t* handle, uv_alloc_cb alloc_cb, - uv_read_cb read_cb); -int uv_pipe_write(uv_loop_t* loop, uv_write_t* req, uv_pipe_t* handle, - const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb); -int uv_pipe_write2(uv_loop_t* loop, uv_write_t* req, uv_pipe_t* handle, - const uv_buf_t bufs[], unsigned int nbufs, uv_stream_t* send_handle, - uv_write_cb cb); -void uv__pipe_pause_read(uv_pipe_t* handle); -void uv__pipe_unpause_read(uv_pipe_t* handle); -void uv__pipe_stop_read(uv_pipe_t* handle); - -void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle, - uv_req_t* req); -void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle, - uv_write_t* req); -void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle, - uv_req_t* raw_req); -void uv_process_pipe_connect_req(uv_loop_t* loop, uv_pipe_t* handle, - uv_connect_t* req); -void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle, - uv_shutdown_t* req); - -void uv_pipe_close(uv_loop_t* loop, uv_pipe_t* handle); -void uv_pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle); -void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle); - - -/* - * TTY - */ -void uv_console_init(); - -int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb, - uv_read_cb read_cb); -int uv_tty_read_stop(uv_tty_t* handle); -int uv_tty_write(uv_loop_t* loop, uv_write_t* req, uv_tty_t* handle, - const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb); -int uv__tty_try_write(uv_tty_t* handle, const uv_buf_t bufs[], - unsigned int nbufs); -void uv_tty_close(uv_tty_t* handle); - -void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle, - uv_req_t* req); -void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle, - uv_write_t* req); -/* TODO: remove me */ -void uv_process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle, - uv_req_t* raw_req); -/* TODO: remove me */ -void uv_process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle, - uv_connect_t* req); - -void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle); - - -/* - * Poll watchers - */ -void uv_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, - uv_req_t* req); - -int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle); -void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle); - - -/* - * Timers - */ -void uv_timer_endgame(uv_loop_t* loop, uv_timer_t* handle); - -DWORD uv__next_timeout(const uv_loop_t* loop); -void uv__time_forward(uv_loop_t* loop, uint64_t msecs); -void uv_process_timers(uv_loop_t* loop); - - -/* - * Loop watchers - */ -void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle); - -void uv_prepare_invoke(uv_loop_t* loop); -void uv_check_invoke(uv_loop_t* loop); -void uv_idle_invoke(uv_loop_t* loop); - -void uv__once_init(); - - -/* - * Async watcher - */ -void uv_async_close(uv_loop_t* loop, uv_async_t* handle); -void uv_async_endgame(uv_loop_t* loop, uv_async_t* handle); - -void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle, - uv_req_t* req); - - -/* - * Signal watcher - */ -void uv_signals_init(); -int uv__signal_dispatch(int signum); - -void uv_signal_close(uv_loop_t* loop, uv_signal_t* handle); -void uv_signal_endgame(uv_loop_t* loop, uv_signal_t* handle); - -void uv_process_signal_req(uv_loop_t* loop, uv_signal_t* handle, - uv_req_t* req); - - -/* - * Spawn - */ -void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle); -void uv_process_close(uv_loop_t* loop, uv_process_t* handle); -void uv_process_endgame(uv_loop_t* loop, uv_process_t* handle); - - -/* - * Error - */ -int uv_translate_sys_error(int sys_errno); - - -/* - * FS - */ -void uv_fs_init(); - - -/* - * FS Event - */ -void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, - uv_fs_event_t* handle); -void uv_fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle); -void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle); - - -/* - * Stat poller. - */ -void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle); - - -/* - * Utilities. - */ -void uv__util_init(); - -uint64_t uv__hrtime(double scale); -int uv_parent_pid(); -__declspec(noreturn) void uv_fatal_error(const int errorno, const char* syscall); - - -/* - * Process stdio handles. - */ -int uv__stdio_create(uv_loop_t* loop, - const uv_process_options_t* options, - BYTE** buffer_ptr); -void uv__stdio_destroy(BYTE* buffer); -void uv__stdio_noinherit(BYTE* buffer); -int uv__stdio_verify(BYTE* buffer, WORD size); -WORD uv__stdio_size(BYTE* buffer); -HANDLE uv__stdio_handle(BYTE* buffer, int fd); - - -/* - * Winapi and ntapi utility functions - */ -void uv_winapi_init(); - - -/* - * Winsock utility functions - */ -void uv_winsock_init(); - -int uv_ntstatus_to_winsock_error(NTSTATUS status); - -BOOL uv_get_acceptex_function(SOCKET socket, LPFN_ACCEPTEX* target); -BOOL uv_get_connectex_function(SOCKET socket, LPFN_CONNECTEX* target); - -int WSAAPI uv_wsarecv_workaround(SOCKET socket, WSABUF* buffers, - DWORD buffer_count, DWORD* bytes, DWORD* flags, WSAOVERLAPPED *overlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine); -int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers, - DWORD buffer_count, DWORD* bytes, DWORD* flags, struct sockaddr* addr, - int* addr_len, WSAOVERLAPPED *overlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine); - -int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in, - AFD_POLL_INFO* info_out, OVERLAPPED* overlapped); - -/* Whether there are any non-IFS LSPs stacked on TCP */ -extern int uv_tcp_non_ifs_lsp_ipv4; -extern int uv_tcp_non_ifs_lsp_ipv6; - -/* Ip address used to bind to any port at any interface */ -extern struct sockaddr_in uv_addr_ip4_any_; -extern struct sockaddr_in6 uv_addr_ip6_any_; - -#endif /* UV_WIN_INTERNAL_H_ */ diff --git a/libuv/src/win/loop-watcher.c b/libuv/src/win/loop-watcher.c deleted file mode 100644 index 20e4509..0000000 --- a/libuv/src/win/loop-watcher.c +++ /dev/null @@ -1,122 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include - -#include "uv.h" -#include "internal.h" -#include "handle-inl.h" - - -void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle) { - if (handle->flags & UV__HANDLE_CLOSING) { - assert(!(handle->flags & UV_HANDLE_CLOSED)); - handle->flags |= UV_HANDLE_CLOSED; - uv__handle_close(handle); - } -} - - -#define UV_LOOP_WATCHER_DEFINE(name, NAME) \ - int uv_##name##_init(uv_loop_t* loop, uv_##name##_t* handle) { \ - uv__handle_init(loop, (uv_handle_t*) handle, UV_##NAME); \ - \ - return 0; \ - } \ - \ - \ - int uv_##name##_start(uv_##name##_t* handle, uv_##name##_cb cb) { \ - uv_loop_t* loop = handle->loop; \ - uv_##name##_t* old_head; \ - \ - assert(handle->type == UV_##NAME); \ - \ - if (uv__is_active(handle)) \ - return 0; \ - \ - if (cb == NULL) \ - return UV_EINVAL; \ - \ - old_head = loop->name##_handles; \ - \ - handle->name##_next = old_head; \ - handle->name##_prev = NULL; \ - \ - if (old_head) { \ - old_head->name##_prev = handle; \ - } \ - \ - loop->name##_handles = handle; \ - \ - handle->name##_cb = cb; \ - uv__handle_start(handle); \ - \ - return 0; \ - } \ - \ - \ - int uv_##name##_stop(uv_##name##_t* handle) { \ - uv_loop_t* loop = handle->loop; \ - \ - assert(handle->type == UV_##NAME); \ - \ - if (!uv__is_active(handle)) \ - return 0; \ - \ - /* Update loop head if needed */ \ - if (loop->name##_handles == handle) { \ - loop->name##_handles = handle->name##_next; \ - } \ - \ - /* Update the iterator-next pointer of needed */ \ - if (loop->next_##name##_handle == handle) { \ - loop->next_##name##_handle = handle->name##_next; \ - } \ - \ - if (handle->name##_prev) { \ - handle->name##_prev->name##_next = handle->name##_next; \ - } \ - if (handle->name##_next) { \ - handle->name##_next->name##_prev = handle->name##_prev; \ - } \ - \ - uv__handle_stop(handle); \ - \ - return 0; \ - } \ - \ - \ - void uv_##name##_invoke(uv_loop_t* loop) { \ - uv_##name##_t* handle; \ - \ - (loop)->next_##name##_handle = (loop)->name##_handles; \ - \ - while ((loop)->next_##name##_handle != NULL) { \ - handle = (loop)->next_##name##_handle; \ - (loop)->next_##name##_handle = handle->name##_next; \ - \ - handle->name##_cb(handle); \ - } \ - } - -UV_LOOP_WATCHER_DEFINE(prepare, PREPARE) -UV_LOOP_WATCHER_DEFINE(check, CHECK) -UV_LOOP_WATCHER_DEFINE(idle, IDLE) diff --git a/libuv/src/win/pipe.c b/libuv/src/win/pipe.c deleted file mode 100644 index 57fab06..0000000 --- a/libuv/src/win/pipe.c +++ /dev/null @@ -1,2067 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include - -#include "uv.h" -#include "internal.h" -#include "handle-inl.h" -#include "stream-inl.h" -#include "req-inl.h" - -typedef struct uv__ipc_queue_item_s uv__ipc_queue_item_t; - -struct uv__ipc_queue_item_s { - /* - * NOTE: It is important for socket_info_ex to be the first field, - * because we will we assigning it to the pending_ipc_info.socket_info - */ - uv__ipc_socket_info_ex socket_info_ex; - QUEUE member; - int tcp_connection; -}; - -/* A zero-size buffer for use by uv_pipe_read */ -static char uv_zero_[] = ""; - -/* Null uv_buf_t */ -static const uv_buf_t uv_null_buf_ = { 0, NULL }; - -/* The timeout that the pipe will wait for the remote end to write data */ -/* when the local ends wants to shut it down. */ -static const int64_t eof_timeout = 50; /* ms */ - -static const int default_pending_pipe_instances = 4; - -/* Pipe prefix */ -static char pipe_prefix[] = "\\\\?\\pipe"; -static const int pipe_prefix_len = sizeof(pipe_prefix) - 1; - -/* IPC protocol flags. */ -#define UV_IPC_RAW_DATA 0x0001 -#define UV_IPC_TCP_SERVER 0x0002 -#define UV_IPC_TCP_CONNECTION 0x0004 - -/* IPC frame header. */ -typedef struct { - int flags; - uint64_t raw_data_length; -} uv_ipc_frame_header_t; - -/* IPC frame, which contains an imported TCP socket stream. */ -typedef struct { - uv_ipc_frame_header_t header; - uv__ipc_socket_info_ex socket_info_ex; -} uv_ipc_frame_uv_stream; - -static void eof_timer_init(uv_pipe_t* pipe); -static void eof_timer_start(uv_pipe_t* pipe); -static void eof_timer_stop(uv_pipe_t* pipe); -static void eof_timer_cb(uv_timer_t* timer); -static void eof_timer_destroy(uv_pipe_t* pipe); -static void eof_timer_close_cb(uv_handle_t* handle); - - -static void uv_unique_pipe_name(char* ptr, char* name, size_t size) { - _snprintf(name, size, "\\\\?\\pipe\\uv\\%p-%u", ptr, GetCurrentProcessId()); -} - - -int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) { - uv_stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE); - - handle->reqs_pending = 0; - handle->handle = INVALID_HANDLE_VALUE; - handle->name = NULL; - handle->ipc_pid = 0; - handle->remaining_ipc_rawdata_bytes = 0; - QUEUE_INIT(&handle->pending_ipc_info.queue); - handle->pending_ipc_info.queue_len = 0; - handle->ipc = ipc; - handle->non_overlapped_writes_tail = NULL; - handle->readfile_thread = NULL; - - uv_req_init(loop, (uv_req_t*) &handle->ipc_header_write_req); - - return 0; -} - - -static void uv_pipe_connection_init(uv_pipe_t* handle) { - uv_connection_init((uv_stream_t*) handle); - handle->read_req.data = handle; - handle->eof_timer = NULL; - assert(!(handle->flags & UV_HANDLE_PIPESERVER)); - if (pCancelSynchronousIo && - handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) { - uv_mutex_init(&handle->readfile_mutex); - handle->flags |= UV_HANDLE_PIPE_READ_CANCELABLE; - } -} - - -static HANDLE open_named_pipe(const WCHAR* name, DWORD* duplex_flags) { - HANDLE pipeHandle; - - /* - * Assume that we have a duplex pipe first, so attempt to - * connect with GENERIC_READ | GENERIC_WRITE. - */ - pipeHandle = CreateFileW(name, - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, - NULL); - if (pipeHandle != INVALID_HANDLE_VALUE) { - *duplex_flags = UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; - return pipeHandle; - } - - /* - * If the pipe is not duplex CreateFileW fails with - * ERROR_ACCESS_DENIED. In that case try to connect - * as a read-only or write-only. - */ - if (GetLastError() == ERROR_ACCESS_DENIED) { - pipeHandle = CreateFileW(name, - GENERIC_READ | FILE_WRITE_ATTRIBUTES, - 0, - NULL, - OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, - NULL); - - if (pipeHandle != INVALID_HANDLE_VALUE) { - *duplex_flags = UV_HANDLE_READABLE; - return pipeHandle; - } - } - - if (GetLastError() == ERROR_ACCESS_DENIED) { - pipeHandle = CreateFileW(name, - GENERIC_WRITE | FILE_READ_ATTRIBUTES, - 0, - NULL, - OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, - NULL); - - if (pipeHandle != INVALID_HANDLE_VALUE) { - *duplex_flags = UV_HANDLE_WRITABLE; - return pipeHandle; - } - } - - return INVALID_HANDLE_VALUE; -} - - -int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access, - char* name, size_t nameSize) { - HANDLE pipeHandle; - int err; - char* ptr = (char*)handle; - - for (;;) { - uv_unique_pipe_name(ptr, name, nameSize); - - pipeHandle = CreateNamedPipeA(name, - access | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE, - PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 65536, 65536, 0, - NULL); - - if (pipeHandle != INVALID_HANDLE_VALUE) { - /* No name collisions. We're done. */ - break; - } - - err = GetLastError(); - if (err != ERROR_PIPE_BUSY && err != ERROR_ACCESS_DENIED) { - goto error; - } - - /* Pipe name collision. Increment the pointer and try again. */ - ptr++; - } - - if (CreateIoCompletionPort(pipeHandle, - loop->iocp, - (ULONG_PTR)handle, - 0) == NULL) { - err = GetLastError(); - goto error; - } - - uv_pipe_connection_init(handle); - handle->handle = pipeHandle; - - return 0; - - error: - if (pipeHandle != INVALID_HANDLE_VALUE) { - CloseHandle(pipeHandle); - } - - return err; -} - - -static int uv_set_pipe_handle(uv_loop_t* loop, - uv_pipe_t* handle, - HANDLE pipeHandle, - DWORD duplex_flags) { - NTSTATUS nt_status; - IO_STATUS_BLOCK io_status; - FILE_MODE_INFORMATION mode_info; - DWORD mode = PIPE_READMODE_BYTE | PIPE_WAIT; - DWORD current_mode = 0; - DWORD err = 0; - - if (!SetNamedPipeHandleState(pipeHandle, &mode, NULL, NULL)) { - err = GetLastError(); - if (err == ERROR_ACCESS_DENIED) { - /* - * SetNamedPipeHandleState can fail if the handle doesn't have either - * GENERIC_WRITE or FILE_WRITE_ATTRIBUTES. - * But if the handle already has the desired wait and blocking modes - * we can continue. - */ - if (!GetNamedPipeHandleState(pipeHandle, ¤t_mode, NULL, NULL, - NULL, NULL, 0)) { - return -1; - } else if (current_mode & PIPE_NOWAIT) { - SetLastError(ERROR_ACCESS_DENIED); - return -1; - } - } else { - /* If this returns ERROR_INVALID_PARAMETER we probably opened - * something that is not a pipe. */ - if (err == ERROR_INVALID_PARAMETER) { - SetLastError(WSAENOTSOCK); - } - return -1; - } - } - - /* Check if the pipe was created with FILE_FLAG_OVERLAPPED. */ - nt_status = pNtQueryInformationFile(pipeHandle, - &io_status, - &mode_info, - sizeof(mode_info), - FileModeInformation); - if (nt_status != STATUS_SUCCESS) { - return -1; - } - - if (mode_info.Mode & FILE_SYNCHRONOUS_IO_ALERT || - mode_info.Mode & FILE_SYNCHRONOUS_IO_NONALERT) { - /* Non-overlapped pipe. */ - handle->flags |= UV_HANDLE_NON_OVERLAPPED_PIPE; - } else { - /* Overlapped pipe. Try to associate with IOCP. */ - if (CreateIoCompletionPort(pipeHandle, - loop->iocp, - (ULONG_PTR)handle, - 0) == NULL) { - handle->flags |= UV_HANDLE_EMULATE_IOCP; - } - } - - handle->handle = pipeHandle; - handle->flags |= duplex_flags; - - return 0; -} - - -static DWORD WINAPI pipe_shutdown_thread_proc(void* parameter) { - uv_loop_t* loop; - uv_pipe_t* handle; - uv_shutdown_t* req; - - req = (uv_shutdown_t*) parameter; - assert(req); - handle = (uv_pipe_t*) req->handle; - assert(handle); - loop = handle->loop; - assert(loop); - - FlushFileBuffers(handle->handle); - - /* Post completed */ - POST_COMPLETION_FOR_REQ(loop, req); - - return 0; -} - - -void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) { - int err; - DWORD result; - uv_shutdown_t* req; - NTSTATUS nt_status; - IO_STATUS_BLOCK io_status; - FILE_PIPE_LOCAL_INFORMATION pipe_info; - uv__ipc_queue_item_t* item; - - if (handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) { - handle->flags &= ~UV_HANDLE_PIPE_READ_CANCELABLE; - uv_mutex_destroy(&handle->readfile_mutex); - } - - if ((handle->flags & UV_HANDLE_CONNECTION) && - handle->shutdown_req != NULL && - handle->write_reqs_pending == 0) { - req = handle->shutdown_req; - - /* Clear the shutdown_req field so we don't go here again. */ - handle->shutdown_req = NULL; - - if (handle->flags & UV__HANDLE_CLOSING) { - UNREGISTER_HANDLE_REQ(loop, handle, req); - - /* Already closing. Cancel the shutdown. */ - if (req->cb) { - req->cb(req, UV_ECANCELED); - } - - DECREASE_PENDING_REQ_COUNT(handle); - return; - } - - /* Try to avoid flushing the pipe buffer in the thread pool. */ - nt_status = pNtQueryInformationFile(handle->handle, - &io_status, - &pipe_info, - sizeof pipe_info, - FilePipeLocalInformation); - - if (nt_status != STATUS_SUCCESS) { - /* Failure */ - UNREGISTER_HANDLE_REQ(loop, handle, req); - - handle->flags |= UV_HANDLE_WRITABLE; /* Questionable */ - if (req->cb) { - err = pRtlNtStatusToDosError(nt_status); - req->cb(req, uv_translate_sys_error(err)); - } - - DECREASE_PENDING_REQ_COUNT(handle); - return; - } - - if (pipe_info.OutboundQuota == pipe_info.WriteQuotaAvailable) { - /* Short-circuit, no need to call FlushFileBuffers. */ - uv_insert_pending_req(loop, (uv_req_t*) req); - return; - } - - /* Run FlushFileBuffers in the thread pool. */ - result = QueueUserWorkItem(pipe_shutdown_thread_proc, - req, - WT_EXECUTELONGFUNCTION); - if (result) { - return; - - } else { - /* Failure. */ - UNREGISTER_HANDLE_REQ(loop, handle, req); - - handle->flags |= UV_HANDLE_WRITABLE; /* Questionable */ - if (req->cb) { - err = GetLastError(); - req->cb(req, uv_translate_sys_error(err)); - } - - DECREASE_PENDING_REQ_COUNT(handle); - return; - } - } - - if (handle->flags & UV__HANDLE_CLOSING && - handle->reqs_pending == 0) { - assert(!(handle->flags & UV_HANDLE_CLOSED)); - - if (handle->flags & UV_HANDLE_CONNECTION) { - /* Free pending sockets */ - while (!QUEUE_EMPTY(&handle->pending_ipc_info.queue)) { - QUEUE* q; - SOCKET socket; - - q = QUEUE_HEAD(&handle->pending_ipc_info.queue); - QUEUE_REMOVE(q); - item = QUEUE_DATA(q, uv__ipc_queue_item_t, member); - - /* Materialize socket and close it */ - socket = WSASocketW(FROM_PROTOCOL_INFO, - FROM_PROTOCOL_INFO, - FROM_PROTOCOL_INFO, - &item->socket_info_ex.socket_info, - 0, - WSA_FLAG_OVERLAPPED); - free(item); - - if (socket != INVALID_SOCKET) - closesocket(socket); - } - handle->pending_ipc_info.queue_len = 0; - - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) { - UnregisterWait(handle->read_req.wait_handle); - handle->read_req.wait_handle = INVALID_HANDLE_VALUE; - } - if (handle->read_req.event_handle) { - CloseHandle(handle->read_req.event_handle); - handle->read_req.event_handle = NULL; - } - } - } - - if (handle->flags & UV_HANDLE_PIPESERVER) { - assert(handle->accept_reqs); - free(handle->accept_reqs); - handle->accept_reqs = NULL; - } - - uv__handle_close(handle); - } -} - - -void uv_pipe_pending_instances(uv_pipe_t* handle, int count) { - handle->pending_instances = count; - handle->flags |= UV_HANDLE_PIPESERVER; -} - - -/* Creates a pipe server. */ -int uv_pipe_bind(uv_pipe_t* handle, const char* name) { - uv_loop_t* loop = handle->loop; - int i, err, nameSize; - uv_pipe_accept_t* req; - - if (handle->flags & UV_HANDLE_BOUND) { - return UV_EINVAL; - } - - if (!name) { - return UV_EINVAL; - } - - if (!(handle->flags & UV_HANDLE_PIPESERVER)) { - handle->pending_instances = default_pending_pipe_instances; - } - - handle->accept_reqs = (uv_pipe_accept_t*) - malloc(sizeof(uv_pipe_accept_t) * handle->pending_instances); - if (!handle->accept_reqs) { - uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); - } - - for (i = 0; i < handle->pending_instances; i++) { - req = &handle->accept_reqs[i]; - uv_req_init(loop, (uv_req_t*) req); - req->type = UV_ACCEPT; - req->data = handle; - req->pipeHandle = INVALID_HANDLE_VALUE; - req->next_pending = NULL; - } - - /* Convert name to UTF16. */ - nameSize = uv_utf8_to_utf16(name, NULL, 0) * sizeof(WCHAR); - handle->name = (WCHAR*)malloc(nameSize); - if (!handle->name) { - uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); - } - - if (!uv_utf8_to_utf16(name, handle->name, nameSize / sizeof(WCHAR))) { - err = GetLastError(); - goto error; - } - - /* - * Attempt to create the first pipe with FILE_FLAG_FIRST_PIPE_INSTANCE. - * If this fails then there's already a pipe server for the given pipe name. - */ - handle->accept_reqs[0].pipeHandle = CreateNamedPipeW(handle->name, - PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | - FILE_FLAG_FIRST_PIPE_INSTANCE, - PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, - PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL); - - if (handle->accept_reqs[0].pipeHandle == INVALID_HANDLE_VALUE) { - err = GetLastError(); - if (err == ERROR_ACCESS_DENIED) { - err = WSAEADDRINUSE; /* Translates to UV_EADDRINUSE. */ - } else if (err == ERROR_PATH_NOT_FOUND || err == ERROR_INVALID_NAME) { - err = WSAEACCES; /* Translates to UV_EACCES. */ - } - goto error; - } - - if (uv_set_pipe_handle(loop, handle, handle->accept_reqs[0].pipeHandle, 0)) { - err = GetLastError(); - goto error; - } - - handle->pending_accepts = NULL; - handle->flags |= UV_HANDLE_PIPESERVER; - handle->flags |= UV_HANDLE_BOUND; - - return 0; - -error: - if (handle->name) { - free(handle->name); - handle->name = NULL; - } - - if (handle->accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE) { - CloseHandle(handle->accept_reqs[0].pipeHandle); - handle->accept_reqs[0].pipeHandle = INVALID_HANDLE_VALUE; - } - - return uv_translate_sys_error(err); -} - - -static DWORD WINAPI pipe_connect_thread_proc(void* parameter) { - uv_loop_t* loop; - uv_pipe_t* handle; - uv_connect_t* req; - HANDLE pipeHandle = INVALID_HANDLE_VALUE; - DWORD duplex_flags; - - req = (uv_connect_t*) parameter; - assert(req); - handle = (uv_pipe_t*) req->handle; - assert(handle); - loop = handle->loop; - assert(loop); - - /* We're here because CreateFile on a pipe returned ERROR_PIPE_BUSY. */ - /* We wait for the pipe to become available with WaitNamedPipe. */ - while (WaitNamedPipeW(handle->name, 30000)) { - /* The pipe is now available, try to connect. */ - pipeHandle = open_named_pipe(handle->name, &duplex_flags); - if (pipeHandle != INVALID_HANDLE_VALUE) { - break; - } - - SwitchToThread(); - } - - if (pipeHandle != INVALID_HANDLE_VALUE && - !uv_set_pipe_handle(loop, handle, pipeHandle, duplex_flags)) { - SET_REQ_SUCCESS(req); - } else { - SET_REQ_ERROR(req, GetLastError()); - } - - /* Post completed */ - POST_COMPLETION_FOR_REQ(loop, req); - - return 0; -} - - -void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, - const char* name, uv_connect_cb cb) { - uv_loop_t* loop = handle->loop; - int err, nameSize; - HANDLE pipeHandle = INVALID_HANDLE_VALUE; - DWORD duplex_flags; - - uv_req_init(loop, (uv_req_t*) req); - req->type = UV_CONNECT; - req->handle = (uv_stream_t*) handle; - req->cb = cb; - - /* Convert name to UTF16. */ - nameSize = uv_utf8_to_utf16(name, NULL, 0) * sizeof(WCHAR); - handle->name = (WCHAR*)malloc(nameSize); - if (!handle->name) { - uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); - } - - if (!uv_utf8_to_utf16(name, handle->name, nameSize / sizeof(WCHAR))) { - err = GetLastError(); - goto error; - } - - pipeHandle = open_named_pipe(handle->name, &duplex_flags); - if (pipeHandle == INVALID_HANDLE_VALUE) { - if (GetLastError() == ERROR_PIPE_BUSY) { - /* Wait for the server to make a pipe instance available. */ - if (!QueueUserWorkItem(&pipe_connect_thread_proc, - req, - WT_EXECUTELONGFUNCTION)) { - err = GetLastError(); - goto error; - } - - REGISTER_HANDLE_REQ(loop, handle, req); - handle->reqs_pending++; - - return; - } - - err = GetLastError(); - goto error; - } - - assert(pipeHandle != INVALID_HANDLE_VALUE); - - if (uv_set_pipe_handle(loop, - (uv_pipe_t*) req->handle, - pipeHandle, - duplex_flags)) { - err = GetLastError(); - goto error; - } - - SET_REQ_SUCCESS(req); - uv_insert_pending_req(loop, (uv_req_t*) req); - handle->reqs_pending++; - REGISTER_HANDLE_REQ(loop, handle, req); - return; - -error: - if (handle->name) { - free(handle->name); - handle->name = NULL; - } - - if (pipeHandle != INVALID_HANDLE_VALUE) { - CloseHandle(pipeHandle); - } - - /* Make this req pending reporting an error. */ - SET_REQ_ERROR(req, err); - uv_insert_pending_req(loop, (uv_req_t*) req); - handle->reqs_pending++; - REGISTER_HANDLE_REQ(loop, handle, req); - return; -} - - -void uv__pipe_pause_read(uv_pipe_t* handle) { - if (handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) { - /* Pause the ReadFile task briefly, to work - around the Windows kernel bug that causes - any access to a NamedPipe to deadlock if - any process has called ReadFile */ - HANDLE h; - uv_mutex_lock(&handle->readfile_mutex); - h = handle->readfile_thread; - while (h) { - /* spinlock: we expect this to finish quickly, - or we are probably about to deadlock anyways - (in the kernel), so it doesn't matter */ - pCancelSynchronousIo(h); - SwitchToThread(); /* yield thread control briefly */ - h = handle->readfile_thread; - } - } -} - - -void uv__pipe_unpause_read(uv_pipe_t* handle) { - if (handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) { - uv_mutex_unlock(&handle->readfile_mutex); - } -} - - -void uv__pipe_stop_read(uv_pipe_t* handle) { - handle->flags &= ~UV_HANDLE_READING; - uv__pipe_pause_read((uv_pipe_t*)handle); - uv__pipe_unpause_read((uv_pipe_t*)handle); -} - - -/* Cleans up uv_pipe_t (server or connection) and all resources associated */ -/* with it. */ -void uv_pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle) { - int i; - HANDLE pipeHandle; - - uv__pipe_stop_read(handle); - - if (handle->name) { - free(handle->name); - handle->name = NULL; - } - - if (handle->flags & UV_HANDLE_PIPESERVER) { - for (i = 0; i < handle->pending_instances; i++) { - pipeHandle = handle->accept_reqs[i].pipeHandle; - if (pipeHandle != INVALID_HANDLE_VALUE) { - CloseHandle(pipeHandle); - handle->accept_reqs[i].pipeHandle = INVALID_HANDLE_VALUE; - } - } - } - - if (handle->flags & UV_HANDLE_CONNECTION) { - handle->flags &= ~UV_HANDLE_WRITABLE; - eof_timer_destroy(handle); - } - - if ((handle->flags & UV_HANDLE_CONNECTION) - && handle->handle != INVALID_HANDLE_VALUE) { - CloseHandle(handle->handle); - handle->handle = INVALID_HANDLE_VALUE; - } - -} - - -void uv_pipe_close(uv_loop_t* loop, uv_pipe_t* handle) { - if (handle->flags & UV_HANDLE_READING) { - handle->flags &= ~UV_HANDLE_READING; - DECREASE_ACTIVE_COUNT(loop, handle); - } - - if (handle->flags & UV_HANDLE_LISTENING) { - handle->flags &= ~UV_HANDLE_LISTENING; - DECREASE_ACTIVE_COUNT(loop, handle); - } - - uv_pipe_cleanup(loop, handle); - - if (handle->reqs_pending == 0) { - uv_want_endgame(loop, (uv_handle_t*) handle); - } - - handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); - uv__handle_closing(handle); -} - - -static void uv_pipe_queue_accept(uv_loop_t* loop, uv_pipe_t* handle, - uv_pipe_accept_t* req, BOOL firstInstance) { - assert(handle->flags & UV_HANDLE_LISTENING); - - if (!firstInstance) { - assert(req->pipeHandle == INVALID_HANDLE_VALUE); - - req->pipeHandle = CreateNamedPipeW(handle->name, - PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, - PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, - PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL); - - if (req->pipeHandle == INVALID_HANDLE_VALUE) { - SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*) req); - handle->reqs_pending++; - return; - } - - if (uv_set_pipe_handle(loop, handle, req->pipeHandle, 0)) { - CloseHandle(req->pipeHandle); - req->pipeHandle = INVALID_HANDLE_VALUE; - SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*) req); - handle->reqs_pending++; - return; - } - } - - assert(req->pipeHandle != INVALID_HANDLE_VALUE); - - /* Prepare the overlapped structure. */ - memset(&(req->overlapped), 0, sizeof(req->overlapped)); - - if (!ConnectNamedPipe(req->pipeHandle, &req->overlapped) && - GetLastError() != ERROR_IO_PENDING) { - if (GetLastError() == ERROR_PIPE_CONNECTED) { - SET_REQ_SUCCESS(req); - } else { - CloseHandle(req->pipeHandle); - req->pipeHandle = INVALID_HANDLE_VALUE; - /* Make this req pending reporting an error. */ - SET_REQ_ERROR(req, GetLastError()); - } - uv_insert_pending_req(loop, (uv_req_t*) req); - handle->reqs_pending++; - return; - } - - handle->reqs_pending++; -} - - -int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) { - uv_loop_t* loop = server->loop; - uv_pipe_t* pipe_client; - uv_pipe_accept_t* req; - QUEUE* q; - uv__ipc_queue_item_t* item; - int err; - - if (server->ipc) { - if (QUEUE_EMPTY(&server->pending_ipc_info.queue)) { - /* No valid pending sockets. */ - return WSAEWOULDBLOCK; - } - - q = QUEUE_HEAD(&server->pending_ipc_info.queue); - QUEUE_REMOVE(q); - server->pending_ipc_info.queue_len--; - item = QUEUE_DATA(q, uv__ipc_queue_item_t, member); - - err = uv_tcp_import((uv_tcp_t*)client, - &item->socket_info_ex, - item->tcp_connection); - if (err != 0) - return err; - - free(item); - - } else { - pipe_client = (uv_pipe_t*)client; - - /* Find a connection instance that has been connected, but not yet */ - /* accepted. */ - req = server->pending_accepts; - - if (!req) { - /* No valid connections found, so we error out. */ - return WSAEWOULDBLOCK; - } - - /* Initialize the client handle and copy the pipeHandle to the client */ - uv_pipe_connection_init(pipe_client); - pipe_client->handle = req->pipeHandle; - pipe_client->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; - - /* Prepare the req to pick up a new connection */ - server->pending_accepts = req->next_pending; - req->next_pending = NULL; - req->pipeHandle = INVALID_HANDLE_VALUE; - - if (!(server->flags & UV__HANDLE_CLOSING)) { - uv_pipe_queue_accept(loop, server, req, FALSE); - } - } - - return 0; -} - - -/* Starts listening for connections for the given pipe. */ -int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { - uv_loop_t* loop = handle->loop; - int i; - - if (handle->flags & UV_HANDLE_LISTENING) { - handle->connection_cb = cb; - } - - if (!(handle->flags & UV_HANDLE_BOUND)) { - return WSAEINVAL; - } - - if (handle->flags & UV_HANDLE_READING) { - return WSAEISCONN; - } - - if (!(handle->flags & UV_HANDLE_PIPESERVER)) { - return ERROR_NOT_SUPPORTED; - } - - handle->flags |= UV_HANDLE_LISTENING; - INCREASE_ACTIVE_COUNT(loop, handle); - handle->connection_cb = cb; - - /* First pipe handle should have already been created in uv_pipe_bind */ - assert(handle->accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE); - - for (i = 0; i < handle->pending_instances; i++) { - uv_pipe_queue_accept(loop, handle, &handle->accept_reqs[i], i == 0); - } - - return 0; -} - - -static DWORD WINAPI uv_pipe_zero_readfile_thread_proc(void* parameter) { - int result; - DWORD bytes; - uv_read_t* req = (uv_read_t*) parameter; - uv_pipe_t* handle = (uv_pipe_t*) req->data; - uv_loop_t* loop = handle->loop; - HANDLE hThread = NULL; - DWORD err; - uv_mutex_t *m = &handle->readfile_mutex; - - assert(req != NULL); - assert(req->type == UV_READ); - assert(handle->type == UV_NAMED_PIPE); - - if (handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) { - uv_mutex_lock(m); /* mutex controls *setting* of readfile_thread */ - if (DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), - GetCurrentProcess(), &hThread, - 0, TRUE, DUPLICATE_SAME_ACCESS)) { - handle->readfile_thread = hThread; - } else { - hThread = NULL; - } - uv_mutex_unlock(m); - } -restart_readfile: - result = ReadFile(handle->handle, - &uv_zero_, - 0, - &bytes, - NULL); - if (!result) { - err = GetLastError(); - if (err == ERROR_OPERATION_ABORTED && - handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) { - if (handle->flags & UV_HANDLE_READING) { - /* just a brief break to do something else */ - handle->readfile_thread = NULL; - /* resume after it is finished */ - uv_mutex_lock(m); - handle->readfile_thread = hThread; - uv_mutex_unlock(m); - goto restart_readfile; - } else { - result = 1; /* successfully stopped reading */ - } - } - } - if (hThread) { - assert(hThread == handle->readfile_thread); - /* mutex does not control clearing readfile_thread */ - handle->readfile_thread = NULL; - uv_mutex_lock(m); - /* only when we hold the mutex lock is it safe to - open or close the handle */ - CloseHandle(hThread); - uv_mutex_unlock(m); - } - - if (!result) { - SET_REQ_ERROR(req, err); - } - - POST_COMPLETION_FOR_REQ(loop, req); - return 0; -} - - -static DWORD WINAPI uv_pipe_writefile_thread_proc(void* parameter) { - int result; - DWORD bytes; - uv_write_t* req = (uv_write_t*) parameter; - uv_pipe_t* handle = (uv_pipe_t*) req->handle; - uv_loop_t* loop = handle->loop; - - assert(req != NULL); - assert(req->type == UV_WRITE); - assert(handle->type == UV_NAMED_PIPE); - assert(req->write_buffer.base); - - result = WriteFile(handle->handle, - req->write_buffer.base, - req->write_buffer.len, - &bytes, - NULL); - - if (!result) { - SET_REQ_ERROR(req, GetLastError()); - } - - POST_COMPLETION_FOR_REQ(loop, req); - return 0; -} - - -static void CALLBACK post_completion_read_wait(void* context, BOOLEAN timed_out) { - uv_read_t* req; - uv_tcp_t* handle; - - req = (uv_read_t*) context; - assert(req != NULL); - handle = (uv_tcp_t*)req->data; - assert(handle != NULL); - assert(!timed_out); - - if (!PostQueuedCompletionStatus(handle->loop->iocp, - req->overlapped.InternalHigh, - 0, - &req->overlapped)) { - uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus"); - } -} - - -static void CALLBACK post_completion_write_wait(void* context, BOOLEAN timed_out) { - uv_write_t* req; - uv_tcp_t* handle; - - req = (uv_write_t*) context; - assert(req != NULL); - handle = (uv_tcp_t*)req->handle; - assert(handle != NULL); - assert(!timed_out); - - if (!PostQueuedCompletionStatus(handle->loop->iocp, - req->overlapped.InternalHigh, - 0, - &req->overlapped)) { - uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus"); - } -} - - -static void uv_pipe_queue_read(uv_loop_t* loop, uv_pipe_t* handle) { - uv_read_t* req; - int result; - - assert(handle->flags & UV_HANDLE_READING); - assert(!(handle->flags & UV_HANDLE_READ_PENDING)); - - assert(handle->handle != INVALID_HANDLE_VALUE); - - req = &handle->read_req; - - if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) { - if (!QueueUserWorkItem(&uv_pipe_zero_readfile_thread_proc, - req, - WT_EXECUTELONGFUNCTION)) { - /* Make this req pending reporting an error. */ - SET_REQ_ERROR(req, GetLastError()); - goto error; - } - } else { - memset(&req->overlapped, 0, sizeof(req->overlapped)); - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - req->overlapped.hEvent = (HANDLE) ((uintptr_t) req->event_handle | 1); - } - - /* Do 0-read */ - result = ReadFile(handle->handle, - &uv_zero_, - 0, - NULL, - &req->overlapped); - - if (!result && GetLastError() != ERROR_IO_PENDING) { - /* Make this req pending reporting an error. */ - SET_REQ_ERROR(req, GetLastError()); - goto error; - } - - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - if (!req->event_handle) { - req->event_handle = CreateEvent(NULL, 0, 0, NULL); - if (!req->event_handle) { - uv_fatal_error(GetLastError(), "CreateEvent"); - } - } - if (req->wait_handle == INVALID_HANDLE_VALUE) { - if (!RegisterWaitForSingleObject(&req->wait_handle, - req->overlapped.hEvent, post_completion_read_wait, (void*) req, - INFINITE, WT_EXECUTEINWAITTHREAD)) { - SET_REQ_ERROR(req, GetLastError()); - goto error; - } - } - } - } - - /* Start the eof timer if there is one */ - eof_timer_start(handle); - handle->flags |= UV_HANDLE_READ_PENDING; - handle->reqs_pending++; - return; - -error: - uv_insert_pending_req(loop, (uv_req_t*)req); - handle->flags |= UV_HANDLE_READ_PENDING; - handle->reqs_pending++; -} - - -int uv_pipe_read_start(uv_pipe_t* handle, - uv_alloc_cb alloc_cb, - uv_read_cb read_cb) { - uv_loop_t* loop = handle->loop; - - handle->flags |= UV_HANDLE_READING; - INCREASE_ACTIVE_COUNT(loop, handle); - handle->read_cb = read_cb; - handle->alloc_cb = alloc_cb; - - /* If reading was stopped and then started again, there could still be a */ - /* read request pending. */ - if (!(handle->flags & UV_HANDLE_READ_PENDING)) - uv_pipe_queue_read(loop, handle); - - return 0; -} - - -static void uv_insert_non_overlapped_write_req(uv_pipe_t* handle, - uv_write_t* req) { - req->next_req = NULL; - if (handle->non_overlapped_writes_tail) { - req->next_req = - handle->non_overlapped_writes_tail->next_req; - handle->non_overlapped_writes_tail->next_req = (uv_req_t*)req; - handle->non_overlapped_writes_tail = req; - } else { - req->next_req = (uv_req_t*)req; - handle->non_overlapped_writes_tail = req; - } -} - - -static uv_write_t* uv_remove_non_overlapped_write_req(uv_pipe_t* handle) { - uv_write_t* req; - - if (handle->non_overlapped_writes_tail) { - req = (uv_write_t*)handle->non_overlapped_writes_tail->next_req; - - if (req == handle->non_overlapped_writes_tail) { - handle->non_overlapped_writes_tail = NULL; - } else { - handle->non_overlapped_writes_tail->next_req = - req->next_req; - } - - return req; - } else { - /* queue empty */ - return NULL; - } -} - - -static void uv_queue_non_overlapped_write(uv_pipe_t* handle) { - uv_write_t* req = uv_remove_non_overlapped_write_req(handle); - if (req) { - if (!QueueUserWorkItem(&uv_pipe_writefile_thread_proc, - req, - WT_EXECUTELONGFUNCTION)) { - uv_fatal_error(GetLastError(), "QueueUserWorkItem"); - } - } -} - - -static int uv_pipe_write_impl(uv_loop_t* loop, - uv_write_t* req, - uv_pipe_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - uv_stream_t* send_handle, - uv_write_cb cb) { - int err; - int result; - uv_tcp_t* tcp_send_handle; - uv_write_t* ipc_header_req = NULL; - uv_ipc_frame_uv_stream ipc_frame; - - if (nbufs != 1 && (nbufs != 0 || !send_handle)) { - return ERROR_NOT_SUPPORTED; - } - - /* Only TCP handles are supported for sharing. */ - if (send_handle && ((send_handle->type != UV_TCP) || - (!(send_handle->flags & UV_HANDLE_BOUND) && - !(send_handle->flags & UV_HANDLE_CONNECTION)))) { - return ERROR_NOT_SUPPORTED; - } - - assert(handle->handle != INVALID_HANDLE_VALUE); - - uv_req_init(loop, (uv_req_t*) req); - req->type = UV_WRITE; - req->handle = (uv_stream_t*) handle; - req->cb = cb; - req->ipc_header = 0; - req->event_handle = NULL; - req->wait_handle = INVALID_HANDLE_VALUE; - memset(&req->overlapped, 0, sizeof(req->overlapped)); - - if (handle->ipc) { - assert(!(handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)); - ipc_frame.header.flags = 0; - - /* Use the IPC framing protocol. */ - if (send_handle) { - tcp_send_handle = (uv_tcp_t*)send_handle; - - err = uv_tcp_duplicate_socket(tcp_send_handle, handle->ipc_pid, - &ipc_frame.socket_info_ex.socket_info); - if (err) { - return err; - } - - ipc_frame.socket_info_ex.delayed_error = tcp_send_handle->delayed_error; - - ipc_frame.header.flags |= UV_IPC_TCP_SERVER; - - if (tcp_send_handle->flags & UV_HANDLE_CONNECTION) { - ipc_frame.header.flags |= UV_IPC_TCP_CONNECTION; - } - } - - if (nbufs == 1) { - ipc_frame.header.flags |= UV_IPC_RAW_DATA; - ipc_frame.header.raw_data_length = bufs[0].len; - } - - /* - * Use the provided req if we're only doing a single write. - * If we're doing multiple writes, use ipc_header_write_req to do - * the first write, and then use the provided req for the second write. - */ - if (!(ipc_frame.header.flags & UV_IPC_RAW_DATA)) { - ipc_header_req = req; - } else { - /* - * Try to use the preallocated write req if it's available. - * Otherwise allocate a new one. - */ - if (handle->ipc_header_write_req.type != UV_WRITE) { - ipc_header_req = (uv_write_t*)&handle->ipc_header_write_req; - } else { - ipc_header_req = (uv_write_t*)malloc(sizeof(uv_write_t)); - if (!ipc_header_req) { - uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); - } - } - - uv_req_init(loop, (uv_req_t*) ipc_header_req); - ipc_header_req->type = UV_WRITE; - ipc_header_req->handle = (uv_stream_t*) handle; - ipc_header_req->cb = NULL; - ipc_header_req->ipc_header = 1; - } - - /* Write the header or the whole frame. */ - memset(&ipc_header_req->overlapped, 0, sizeof(ipc_header_req->overlapped)); - - /* Using overlapped IO, but wait for completion before returning. - This write is blocking because ipc_frame is on stack. */ - ipc_header_req->overlapped.hEvent = CreateEvent(NULL, 1, 0, NULL); - if (!ipc_header_req->overlapped.hEvent) { - uv_fatal_error(GetLastError(), "CreateEvent"); - } - - result = WriteFile(handle->handle, - &ipc_frame, - ipc_frame.header.flags & UV_IPC_TCP_SERVER ? - sizeof(ipc_frame) : sizeof(ipc_frame.header), - NULL, - &ipc_header_req->overlapped); - if (!result && GetLastError() != ERROR_IO_PENDING) { - err = GetLastError(); - CloseHandle(ipc_header_req->overlapped.hEvent); - return err; - } - - if (!result) { - /* Request not completed immediately. Wait for it.*/ - if (WaitForSingleObject(ipc_header_req->overlapped.hEvent, INFINITE) != - WAIT_OBJECT_0) { - err = GetLastError(); - CloseHandle(ipc_header_req->overlapped.hEvent); - return err; - } - } - ipc_header_req->queued_bytes = 0; - CloseHandle(ipc_header_req->overlapped.hEvent); - ipc_header_req->overlapped.hEvent = NULL; - - REGISTER_HANDLE_REQ(loop, handle, ipc_header_req); - handle->reqs_pending++; - handle->write_reqs_pending++; - - /* If we don't have any raw data to write - we're done. */ - if (!(ipc_frame.header.flags & UV_IPC_RAW_DATA)) { - return 0; - } - } - - if ((handle->flags & - (UV_HANDLE_BLOCKING_WRITES | UV_HANDLE_NON_OVERLAPPED_PIPE)) == - (UV_HANDLE_BLOCKING_WRITES | UV_HANDLE_NON_OVERLAPPED_PIPE)) { - DWORD bytes; - result = WriteFile(handle->handle, - bufs[0].base, - bufs[0].len, - &bytes, - NULL); - - if (!result) { - err = GetLastError(); - return err; - } else { - /* Request completed immediately. */ - req->queued_bytes = 0; - } - - REGISTER_HANDLE_REQ(loop, handle, req); - handle->reqs_pending++; - handle->write_reqs_pending++; - POST_COMPLETION_FOR_REQ(loop, req); - return 0; - } else if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) { - req->write_buffer = bufs[0]; - uv_insert_non_overlapped_write_req(handle, req); - if (handle->write_reqs_pending == 0) { - uv_queue_non_overlapped_write(handle); - } - - /* Request queued by the kernel. */ - req->queued_bytes = uv__count_bufs(bufs, nbufs); - handle->write_queue_size += req->queued_bytes; - } else if (handle->flags & UV_HANDLE_BLOCKING_WRITES) { - /* Using overlapped IO, but wait for completion before returning */ - req->overlapped.hEvent = CreateEvent(NULL, 1, 0, NULL); - if (!req->overlapped.hEvent) { - uv_fatal_error(GetLastError(), "CreateEvent"); - } - - result = WriteFile(handle->handle, - bufs[0].base, - bufs[0].len, - NULL, - &req->overlapped); - - if (!result && GetLastError() != ERROR_IO_PENDING) { - err = GetLastError(); - CloseHandle(req->overlapped.hEvent); - return err; - } - - if (result) { - /* Request completed immediately. */ - req->queued_bytes = 0; - } else { - assert(ipc_header_req != NULL); - /* Request queued by the kernel. */ - if (WaitForSingleObject(ipc_header_req->overlapped.hEvent, INFINITE) != - WAIT_OBJECT_0) { - err = GetLastError(); - CloseHandle(ipc_header_req->overlapped.hEvent); - return uv_translate_sys_error(err); - } - } - CloseHandle(req->overlapped.hEvent); - - REGISTER_HANDLE_REQ(loop, handle, req); - handle->reqs_pending++; - handle->write_reqs_pending++; - POST_COMPLETION_FOR_REQ(loop, req); - return 0; - } else { - result = WriteFile(handle->handle, - bufs[0].base, - bufs[0].len, - NULL, - &req->overlapped); - - if (!result && GetLastError() != ERROR_IO_PENDING) { - return GetLastError(); - } - - if (result) { - /* Request completed immediately. */ - req->queued_bytes = 0; - } else { - /* Request queued by the kernel. */ - req->queued_bytes = uv__count_bufs(bufs, nbufs); - handle->write_queue_size += req->queued_bytes; - } - - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - req->event_handle = CreateEvent(NULL, 0, 0, NULL); - if (!req->event_handle) { - uv_fatal_error(GetLastError(), "CreateEvent"); - } - if (!RegisterWaitForSingleObject(&req->wait_handle, - req->overlapped.hEvent, post_completion_write_wait, (void*) req, - INFINITE, WT_EXECUTEINWAITTHREAD)) { - return GetLastError(); - } - } - } - - REGISTER_HANDLE_REQ(loop, handle, req); - handle->reqs_pending++; - handle->write_reqs_pending++; - - return 0; -} - - -int uv_pipe_write(uv_loop_t* loop, - uv_write_t* req, - uv_pipe_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - uv_write_cb cb) { - return uv_pipe_write_impl(loop, req, handle, bufs, nbufs, NULL, cb); -} - - -int uv_pipe_write2(uv_loop_t* loop, - uv_write_t* req, - uv_pipe_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - uv_stream_t* send_handle, - uv_write_cb cb) { - if (!handle->ipc) { - return WSAEINVAL; - } - - return uv_pipe_write_impl(loop, req, handle, bufs, nbufs, send_handle, cb); -} - - -static void uv_pipe_read_eof(uv_loop_t* loop, uv_pipe_t* handle, - uv_buf_t buf) { - /* If there is an eof timer running, we don't need it any more, */ - /* so discard it. */ - eof_timer_destroy(handle); - - handle->flags &= ~UV_HANDLE_READABLE; - uv_read_stop((uv_stream_t*) handle); - - handle->read_cb((uv_stream_t*) handle, UV_EOF, &buf); -} - - -static void uv_pipe_read_error(uv_loop_t* loop, uv_pipe_t* handle, int error, - uv_buf_t buf) { - /* If there is an eof timer running, we don't need it any more, */ - /* so discard it. */ - eof_timer_destroy(handle); - - uv_read_stop((uv_stream_t*) handle); - - handle->read_cb((uv_stream_t*)handle, uv_translate_sys_error(error), &buf); -} - - -static void uv_pipe_read_error_or_eof(uv_loop_t* loop, uv_pipe_t* handle, - int error, uv_buf_t buf) { - if (error == ERROR_BROKEN_PIPE) { - uv_pipe_read_eof(loop, handle, buf); - } else { - uv_pipe_read_error(loop, handle, error, buf); - } -} - - -void uv__pipe_insert_pending_socket(uv_pipe_t* handle, - uv__ipc_socket_info_ex* info, - int tcp_connection) { - uv__ipc_queue_item_t* item; - - item = (uv__ipc_queue_item_t*) malloc(sizeof(*item)); - if (item == NULL) - uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); - - memcpy(&item->socket_info_ex, info, sizeof(item->socket_info_ex)); - item->tcp_connection = tcp_connection; - QUEUE_INSERT_TAIL(&handle->pending_ipc_info.queue, &item->member); - handle->pending_ipc_info.queue_len++; -} - - -void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle, - uv_req_t* req) { - DWORD bytes, avail; - uv_buf_t buf; - uv_ipc_frame_uv_stream ipc_frame; - - assert(handle->type == UV_NAMED_PIPE); - - handle->flags &= ~UV_HANDLE_READ_PENDING; - eof_timer_stop(handle); - - if (!REQ_SUCCESS(req)) { - /* An error occurred doing the 0-read. */ - if (handle->flags & UV_HANDLE_READING) { - uv_pipe_read_error_or_eof(loop, - handle, - GET_REQ_ERROR(req), - uv_null_buf_); - } - } else { - /* Do non-blocking reads until the buffer is empty */ - while (handle->flags & UV_HANDLE_READING) { - if (!PeekNamedPipe(handle->handle, - NULL, - 0, - NULL, - &avail, - NULL)) { - uv_pipe_read_error_or_eof(loop, handle, GetLastError(), uv_null_buf_); - break; - } - - if (avail == 0) { - /* There is nothing to read after all. */ - break; - } - - if (handle->ipc) { - /* Use the IPC framing protocol to read the incoming data. */ - if (handle->remaining_ipc_rawdata_bytes == 0) { - /* We're reading a new frame. First, read the header. */ - assert(avail >= sizeof(ipc_frame.header)); - - if (!ReadFile(handle->handle, - &ipc_frame.header, - sizeof(ipc_frame.header), - &bytes, - NULL)) { - uv_pipe_read_error_or_eof(loop, handle, GetLastError(), - uv_null_buf_); - break; - } - - assert(bytes == sizeof(ipc_frame.header)); - assert(ipc_frame.header.flags <= (UV_IPC_TCP_SERVER | UV_IPC_RAW_DATA | - UV_IPC_TCP_CONNECTION)); - - if (ipc_frame.header.flags & UV_IPC_TCP_SERVER) { - assert(avail - sizeof(ipc_frame.header) >= - sizeof(ipc_frame.socket_info_ex)); - - /* Read the TCP socket info. */ - if (!ReadFile(handle->handle, - &ipc_frame.socket_info_ex, - sizeof(ipc_frame) - sizeof(ipc_frame.header), - &bytes, - NULL)) { - uv_pipe_read_error_or_eof(loop, handle, GetLastError(), - uv_null_buf_); - break; - } - - assert(bytes == sizeof(ipc_frame) - sizeof(ipc_frame.header)); - - /* Store the pending socket info. */ - uv__pipe_insert_pending_socket( - handle, - &ipc_frame.socket_info_ex, - ipc_frame.header.flags & UV_IPC_TCP_CONNECTION); - } - - if (ipc_frame.header.flags & UV_IPC_RAW_DATA) { - handle->remaining_ipc_rawdata_bytes = - ipc_frame.header.raw_data_length; - continue; - } - } else { - avail = min(avail, (DWORD)handle->remaining_ipc_rawdata_bytes); - } - } - - handle->alloc_cb((uv_handle_t*) handle, avail, &buf); - if (buf.len == 0) { - handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &buf); - break; - } - assert(buf.base != NULL); - - if (ReadFile(handle->handle, - buf.base, - buf.len, - &bytes, - NULL)) { - /* Successful read */ - if (handle->ipc) { - assert(handle->remaining_ipc_rawdata_bytes >= bytes); - handle->remaining_ipc_rawdata_bytes = - handle->remaining_ipc_rawdata_bytes - bytes; - } - handle->read_cb((uv_stream_t*)handle, bytes, &buf); - - /* Read again only if bytes == buf.len */ - if (bytes <= buf.len) { - break; - } - } else { - uv_pipe_read_error_or_eof(loop, handle, GetLastError(), buf); - break; - } - } - - /* Post another 0-read if still reading and not closing. */ - if ((handle->flags & UV_HANDLE_READING) && - !(handle->flags & UV_HANDLE_READ_PENDING)) { - uv_pipe_queue_read(loop, handle); - } - } - - DECREASE_PENDING_REQ_COUNT(handle); -} - - -void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle, - uv_write_t* req) { - int err; - - assert(handle->type == UV_NAMED_PIPE); - - assert(handle->write_queue_size >= req->queued_bytes); - handle->write_queue_size -= req->queued_bytes; - - UNREGISTER_HANDLE_REQ(loop, handle, req); - - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - if (req->wait_handle != INVALID_HANDLE_VALUE) { - UnregisterWait(req->wait_handle); - req->wait_handle = INVALID_HANDLE_VALUE; - } - if (req->event_handle) { - CloseHandle(req->event_handle); - req->event_handle = NULL; - } - } - - if (req->ipc_header) { - if (req == &handle->ipc_header_write_req) { - req->type = UV_UNKNOWN_REQ; - } else { - free(req); - } - } else { - if (req->cb) { - err = GET_REQ_ERROR(req); - req->cb(req, uv_translate_sys_error(err)); - } - } - - handle->write_reqs_pending--; - - if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE && - handle->non_overlapped_writes_tail) { - assert(handle->write_reqs_pending > 0); - uv_queue_non_overlapped_write(handle); - } - - if (handle->shutdown_req != NULL && - handle->write_reqs_pending == 0) { - uv_want_endgame(loop, (uv_handle_t*)handle); - } - - DECREASE_PENDING_REQ_COUNT(handle); -} - - -void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle, - uv_req_t* raw_req) { - uv_pipe_accept_t* req = (uv_pipe_accept_t*) raw_req; - - assert(handle->type == UV_NAMED_PIPE); - - if (handle->flags & UV__HANDLE_CLOSING) { - /* The req->pipeHandle should be freed already in uv_pipe_cleanup(). */ - assert(req->pipeHandle == INVALID_HANDLE_VALUE); - DECREASE_PENDING_REQ_COUNT(handle); - return; - } - - if (REQ_SUCCESS(req)) { - assert(req->pipeHandle != INVALID_HANDLE_VALUE); - req->next_pending = handle->pending_accepts; - handle->pending_accepts = req; - - if (handle->connection_cb) { - handle->connection_cb((uv_stream_t*)handle, 0); - } - } else { - if (req->pipeHandle != INVALID_HANDLE_VALUE) { - CloseHandle(req->pipeHandle); - req->pipeHandle = INVALID_HANDLE_VALUE; - } - if (!(handle->flags & UV__HANDLE_CLOSING)) { - uv_pipe_queue_accept(loop, handle, req, FALSE); - } - } - - DECREASE_PENDING_REQ_COUNT(handle); -} - - -void uv_process_pipe_connect_req(uv_loop_t* loop, uv_pipe_t* handle, - uv_connect_t* req) { - int err; - - assert(handle->type == UV_NAMED_PIPE); - - UNREGISTER_HANDLE_REQ(loop, handle, req); - - if (req->cb) { - err = 0; - if (REQ_SUCCESS(req)) { - uv_pipe_connection_init(handle); - } else { - err = GET_REQ_ERROR(req); - } - req->cb(req, uv_translate_sys_error(err)); - } - - DECREASE_PENDING_REQ_COUNT(handle); -} - - -void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle, - uv_shutdown_t* req) { - assert(handle->type == UV_NAMED_PIPE); - - UNREGISTER_HANDLE_REQ(loop, handle, req); - - if (handle->flags & UV_HANDLE_READABLE) { - /* Initialize and optionally start the eof timer. Only do this if the */ - /* pipe is readable and we haven't seen EOF come in ourselves. */ - eof_timer_init(handle); - - /* If reading start the timer right now. */ - /* Otherwise uv_pipe_queue_read will start it. */ - if (handle->flags & UV_HANDLE_READ_PENDING) { - eof_timer_start(handle); - } - - } else { - /* This pipe is not readable. We can just close it to let the other end */ - /* know that we're done writing. */ - CloseHandle(handle->handle); - handle->handle = INVALID_HANDLE_VALUE; - } - - if (req->cb) { - req->cb(req, 0); - } - - DECREASE_PENDING_REQ_COUNT(handle); -} - - -static void eof_timer_init(uv_pipe_t* pipe) { - int r; - - assert(pipe->eof_timer == NULL); - assert(pipe->flags & UV_HANDLE_CONNECTION); - - pipe->eof_timer = (uv_timer_t*) malloc(sizeof *pipe->eof_timer); - - r = uv_timer_init(pipe->loop, pipe->eof_timer); - assert(r == 0); /* timers can't fail */ - pipe->eof_timer->data = pipe; - uv_unref((uv_handle_t*) pipe->eof_timer); -} - - -static void eof_timer_start(uv_pipe_t* pipe) { - assert(pipe->flags & UV_HANDLE_CONNECTION); - - if (pipe->eof_timer != NULL) { - uv_timer_start(pipe->eof_timer, eof_timer_cb, eof_timeout, 0); - } -} - - -static void eof_timer_stop(uv_pipe_t* pipe) { - assert(pipe->flags & UV_HANDLE_CONNECTION); - - if (pipe->eof_timer != NULL) { - uv_timer_stop(pipe->eof_timer); - } -} - - -static void eof_timer_cb(uv_timer_t* timer) { - uv_pipe_t* pipe = (uv_pipe_t*) timer->data; - uv_loop_t* loop = timer->loop; - - assert(pipe->type == UV_NAMED_PIPE); - - /* This should always be true, since we start the timer only */ - /* in uv_pipe_queue_read after successfully calling ReadFile, */ - /* or in uv_process_pipe_shutdown_req if a read is pending, */ - /* and we always immediately stop the timer in */ - /* uv_process_pipe_read_req. */ - assert(pipe->flags & UV_HANDLE_READ_PENDING); - - /* If there are many packets coming off the iocp then the timer callback */ - /* may be called before the read request is coming off the queue. */ - /* Therefore we check here if the read request has completed but will */ - /* be processed later. */ - if ((pipe->flags & UV_HANDLE_READ_PENDING) && - HasOverlappedIoCompleted(&pipe->read_req.overlapped)) { - return; - } - - /* Force both ends off the pipe. */ - CloseHandle(pipe->handle); - pipe->handle = INVALID_HANDLE_VALUE; - - /* Stop reading, so the pending read that is going to fail will */ - /* not be reported to the user. */ - uv_read_stop((uv_stream_t*) pipe); - - /* Report the eof and update flags. This will get reported even if the */ - /* user stopped reading in the meantime. TODO: is that okay? */ - uv_pipe_read_eof(loop, pipe, uv_null_buf_); -} - - -static void eof_timer_destroy(uv_pipe_t* pipe) { - assert(pipe->flags & UV_HANDLE_CONNECTION); - - if (pipe->eof_timer) { - uv_close((uv_handle_t*) pipe->eof_timer, eof_timer_close_cb); - pipe->eof_timer = NULL; - } -} - - -static void eof_timer_close_cb(uv_handle_t* handle) { - assert(handle->type == UV_TIMER); - free(handle); -} - - -int uv_pipe_open(uv_pipe_t* pipe, uv_file file) { - HANDLE os_handle = uv__get_osfhandle(file); - NTSTATUS nt_status; - IO_STATUS_BLOCK io_status; - FILE_ACCESS_INFORMATION access; - DWORD duplex_flags = 0; - - /* Determine what kind of permissions we have on this handle. - * Cygwin opens the pipe in message mode, but we can support it, - * just query the access flags and set the stream flags accordingly. - */ - nt_status = pNtQueryInformationFile(os_handle, - &io_status, - &access, - sizeof(access), - FileAccessInformation); - if (nt_status != STATUS_SUCCESS) - return UV_EINVAL; - - if (pipe->ipc) { - if (!(access.AccessFlags & FILE_WRITE_DATA) || - !(access.AccessFlags & FILE_READ_DATA)) { - return UV_EINVAL; - } - } - - if (access.AccessFlags & FILE_WRITE_DATA) - duplex_flags |= UV_HANDLE_WRITABLE; - if (access.AccessFlags & FILE_READ_DATA) - duplex_flags |= UV_HANDLE_READABLE; - - if (os_handle == INVALID_HANDLE_VALUE || - uv_set_pipe_handle(pipe->loop, pipe, os_handle, duplex_flags) == -1) { - return UV_EINVAL; - } - - uv_pipe_connection_init(pipe); - - if (pipe->ipc) { - assert(!(pipe->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)); - pipe->ipc_pid = uv_parent_pid(); - assert(pipe->ipc_pid != -1); - } - return 0; -} - - -static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size) { - NTSTATUS nt_status; - IO_STATUS_BLOCK io_status; - FILE_NAME_INFORMATION tmp_name_info; - FILE_NAME_INFORMATION* name_info; - WCHAR* name_buf; - unsigned int addrlen; - unsigned int name_size; - unsigned int name_len; - int err; - - name_info = NULL; - - if (handle->handle == INVALID_HANDLE_VALUE) { - *size = 0; - return UV_EINVAL; - } - - uv__pipe_pause_read((uv_pipe_t*)handle); /* cast away const warning */ - - nt_status = pNtQueryInformationFile(handle->handle, - &io_status, - &tmp_name_info, - sizeof tmp_name_info, - FileNameInformation); - if (nt_status == STATUS_BUFFER_OVERFLOW) { - name_size = sizeof(*name_info) + tmp_name_info.FileNameLength; - name_info = malloc(name_size); - if (!name_info) { - *size = 0; - err = UV_ENOMEM; - goto cleanup; - } - - nt_status = pNtQueryInformationFile(handle->handle, - &io_status, - name_info, - name_size, - FileNameInformation); - } - - if (nt_status != STATUS_SUCCESS) { - *size = 0; - err = uv_translate_sys_error(pRtlNtStatusToDosError(nt_status)); - goto error; - } - - if (!name_info) { - /* the struct on stack was used */ - name_buf = tmp_name_info.FileName; - name_len = tmp_name_info.FileNameLength; - } else { - name_buf = name_info->FileName; - name_len = name_info->FileNameLength; - } - - if (name_len == 0) { - *size = 0; - err = 0; - goto error; - } - - name_len /= sizeof(WCHAR); - - /* check how much space we need */ - addrlen = WideCharToMultiByte(CP_UTF8, - 0, - name_buf, - name_len, - NULL, - 0, - NULL, - NULL); - if (!addrlen) { - *size = 0; - err = uv_translate_sys_error(GetLastError()); - goto error; - } else if (pipe_prefix_len + addrlen > *size) { - /* "\\\\.\\pipe" + name */ - *size = pipe_prefix_len + addrlen; - err = UV_ENOBUFS; - goto error; - } - - memcpy(buffer, pipe_prefix, pipe_prefix_len); - addrlen = WideCharToMultiByte(CP_UTF8, - 0, - name_buf, - name_len, - buffer+pipe_prefix_len, - *size-pipe_prefix_len, - NULL, - NULL); - if (!addrlen) { - *size = 0; - err = uv_translate_sys_error(GetLastError()); - goto error; - } - - addrlen += pipe_prefix_len; - *size = addrlen; - - err = 0; - goto cleanup; - -error: - free(name_info); - -cleanup: - uv__pipe_unpause_read((uv_pipe_t*)handle); /* cast away const warning */ - return err; -} - - -int uv_pipe_pending_count(uv_pipe_t* handle) { - if (!handle->ipc) - return 0; - return handle->pending_ipc_info.queue_len; -} - - -int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) { - if (handle->flags & UV_HANDLE_BOUND) - return uv__pipe_getname(handle, buffer, size); - - if (handle->flags & UV_HANDLE_CONNECTION || - handle->handle != INVALID_HANDLE_VALUE) { - *size = 0; - return 0; - } - - return UV_EBADF; -} - - -int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) { - /* emulate unix behaviour */ - if (handle->flags & UV_HANDLE_BOUND) - return UV_ENOTCONN; - - if (handle->handle != INVALID_HANDLE_VALUE) - return uv__pipe_getname(handle, buffer, size); - - return UV_EBADF; -} - - -uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) { - if (!handle->ipc) - return UV_UNKNOWN_HANDLE; - if (handle->pending_ipc_info.queue_len == 0) - return UV_UNKNOWN_HANDLE; - else - return UV_TCP; -} diff --git a/libuv/src/win/poll.c b/libuv/src/win/poll.c deleted file mode 100644 index 4d8e1f9..0000000 --- a/libuv/src/win/poll.c +++ /dev/null @@ -1,635 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include - -#include "uv.h" -#include "internal.h" -#include "handle-inl.h" -#include "req-inl.h" - - -static const GUID uv_msafd_provider_ids[UV_MSAFD_PROVIDER_COUNT] = { - {0xe70f1aa0, 0xab8b, 0x11cf, - {0x8c, 0xa3, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}}, - {0xf9eab0c0, 0x26d4, 0x11d0, - {0xbb, 0xbf, 0x00, 0xaa, 0x00, 0x6c, 0x34, 0xe4}}, - {0x9fc48064, 0x7298, 0x43e4, - {0xb7, 0xbd, 0x18, 0x1f, 0x20, 0x89, 0x79, 0x2a}} -}; - -typedef struct uv_single_fd_set_s { - unsigned int fd_count; - SOCKET fd_array[1]; -} uv_single_fd_set_t; - - -static OVERLAPPED overlapped_dummy_; -static uv_once_t overlapped_dummy_init_guard_ = UV_ONCE_INIT; - -static AFD_POLL_INFO afd_poll_info_dummy_; - - -static void uv__init_overlapped_dummy(void) { - HANDLE event; - - event = CreateEvent(NULL, TRUE, TRUE, NULL); - if (event == NULL) - uv_fatal_error(GetLastError(), "CreateEvent"); - - memset(&overlapped_dummy_, 0, sizeof overlapped_dummy_); - overlapped_dummy_.hEvent = (HANDLE) ((uintptr_t) event | 1); -} - - -static OVERLAPPED* uv__get_overlapped_dummy() { - uv_once(&overlapped_dummy_init_guard_, uv__init_overlapped_dummy); - return &overlapped_dummy_; -} - - -static AFD_POLL_INFO* uv__get_afd_poll_info_dummy() { - return &afd_poll_info_dummy_; -} - - -static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) { - uv_req_t* req; - AFD_POLL_INFO* afd_poll_info; - DWORD result; - - /* Find a yet unsubmitted req to submit. */ - if (handle->submitted_events_1 == 0) { - req = &handle->poll_req_1; - afd_poll_info = &handle->afd_poll_info_1; - handle->submitted_events_1 = handle->events; - handle->mask_events_1 = 0; - handle->mask_events_2 = handle->events; - } else if (handle->submitted_events_2 == 0) { - req = &handle->poll_req_2; - afd_poll_info = &handle->afd_poll_info_2; - handle->submitted_events_2 = handle->events; - handle->mask_events_1 = handle->events; - handle->mask_events_2 = 0; - } else { - assert(0); - return; - } - - /* Setting Exclusive to TRUE makes the other poll request return if there */ - /* is any. */ - afd_poll_info->Exclusive = TRUE; - afd_poll_info->NumberOfHandles = 1; - afd_poll_info->Timeout.QuadPart = INT64_MAX; - afd_poll_info->Handles[0].Handle = (HANDLE) handle->socket; - afd_poll_info->Handles[0].Status = 0; - afd_poll_info->Handles[0].Events = 0; - - if (handle->events & UV_READABLE) { - afd_poll_info->Handles[0].Events |= AFD_POLL_RECEIVE | - AFD_POLL_DISCONNECT | AFD_POLL_ACCEPT | AFD_POLL_ABORT; - } - if (handle->events & UV_WRITABLE) { - afd_poll_info->Handles[0].Events |= AFD_POLL_SEND | AFD_POLL_CONNECT_FAIL; - } - - memset(&req->overlapped, 0, sizeof req->overlapped); - - result = uv_msafd_poll((SOCKET) handle->peer_socket, - afd_poll_info, - afd_poll_info, - &req->overlapped); - if (result != 0 && WSAGetLastError() != WSA_IO_PENDING) { - /* Queue this req, reporting an error. */ - SET_REQ_ERROR(req, WSAGetLastError()); - uv_insert_pending_req(loop, req); - } -} - - -static int uv__fast_poll_cancel_poll_req(uv_loop_t* loop, uv_poll_t* handle) { - AFD_POLL_INFO afd_poll_info; - DWORD result; - - afd_poll_info.Exclusive = TRUE; - afd_poll_info.NumberOfHandles = 1; - afd_poll_info.Timeout.QuadPart = INT64_MAX; - afd_poll_info.Handles[0].Handle = (HANDLE) handle->socket; - afd_poll_info.Handles[0].Status = 0; - afd_poll_info.Handles[0].Events = AFD_POLL_ALL; - - result = uv_msafd_poll(handle->socket, - &afd_poll_info, - uv__get_afd_poll_info_dummy(), - uv__get_overlapped_dummy()); - - if (result == SOCKET_ERROR) { - DWORD error = WSAGetLastError(); - if (error != WSA_IO_PENDING) - return error; - } - - return 0; -} - - -static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, - uv_req_t* req) { - unsigned char mask_events; - AFD_POLL_INFO* afd_poll_info; - - if (req == &handle->poll_req_1) { - afd_poll_info = &handle->afd_poll_info_1; - handle->submitted_events_1 = 0; - mask_events = handle->mask_events_1; - } else if (req == &handle->poll_req_2) { - afd_poll_info = &handle->afd_poll_info_2; - handle->submitted_events_2 = 0; - mask_events = handle->mask_events_2; - } else { - assert(0); - return; - } - - /* Report an error unless the select was just interrupted. */ - if (!REQ_SUCCESS(req)) { - DWORD error = GET_REQ_SOCK_ERROR(req); - if (error != WSAEINTR && handle->events != 0) { - handle->events = 0; /* Stop the watcher */ - handle->poll_cb(handle, uv_translate_sys_error(error), 0); - } - - } else if (afd_poll_info->NumberOfHandles >= 1) { - unsigned char events = 0; - - if ((afd_poll_info->Handles[0].Events & (AFD_POLL_RECEIVE | - AFD_POLL_DISCONNECT | AFD_POLL_ACCEPT | AFD_POLL_ABORT)) != 0) { - events |= UV_READABLE; - } - if ((afd_poll_info->Handles[0].Events & (AFD_POLL_SEND | - AFD_POLL_CONNECT_FAIL)) != 0) { - events |= UV_WRITABLE; - } - - events &= handle->events & ~mask_events; - - if (afd_poll_info->Handles[0].Events & AFD_POLL_LOCAL_CLOSE) { - /* Stop polling. */ - handle->events = 0; - if (uv__is_active(handle)) - uv__handle_stop(handle); - } - - if (events != 0) { - handle->poll_cb(handle, 0, events); - } - } - - if ((handle->events & ~(handle->submitted_events_1 | - handle->submitted_events_2)) != 0) { - uv__fast_poll_submit_poll_req(loop, handle); - } else if ((handle->flags & UV__HANDLE_CLOSING) && - handle->submitted_events_1 == 0 && - handle->submitted_events_2 == 0) { - uv_want_endgame(loop, (uv_handle_t*) handle); - } -} - - -static int uv__fast_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) { - assert(handle->type == UV_POLL); - assert(!(handle->flags & UV__HANDLE_CLOSING)); - assert((events & ~(UV_READABLE | UV_WRITABLE)) == 0); - - handle->events = events; - - if (handle->events != 0) { - uv__handle_start(handle); - } else { - uv__handle_stop(handle); - } - - if ((handle->events & ~(handle->submitted_events_1 | - handle->submitted_events_2)) != 0) { - uv__fast_poll_submit_poll_req(handle->loop, handle); - } - - return 0; -} - - -static int uv__fast_poll_close(uv_loop_t* loop, uv_poll_t* handle) { - handle->events = 0; - uv__handle_closing(handle); - - if (handle->submitted_events_1 == 0 && - handle->submitted_events_2 == 0) { - uv_want_endgame(loop, (uv_handle_t*) handle); - return 0; - } else { - /* Cancel outstanding poll requests by executing another, unique poll */ - /* request that forces the outstanding ones to return. */ - return uv__fast_poll_cancel_poll_req(loop, handle); - } -} - - -static SOCKET uv__fast_poll_create_peer_socket(HANDLE iocp, - WSAPROTOCOL_INFOW* protocol_info) { - SOCKET sock = 0; - - sock = WSASocketW(protocol_info->iAddressFamily, - protocol_info->iSocketType, - protocol_info->iProtocol, - protocol_info, - 0, - WSA_FLAG_OVERLAPPED); - if (sock == INVALID_SOCKET) { - return INVALID_SOCKET; - } - - if (!SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0)) { - goto error; - }; - - if (CreateIoCompletionPort((HANDLE) sock, - iocp, - (ULONG_PTR) sock, - 0) == NULL) { - goto error; - } - - return sock; - - error: - closesocket(sock); - return INVALID_SOCKET; -} - - -static SOCKET uv__fast_poll_get_peer_socket(uv_loop_t* loop, - WSAPROTOCOL_INFOW* protocol_info) { - int index, i; - SOCKET peer_socket; - - index = -1; - for (i = 0; (size_t) i < ARRAY_SIZE(uv_msafd_provider_ids); i++) { - if (memcmp((void*) &protocol_info->ProviderId, - (void*) &uv_msafd_provider_ids[i], - sizeof protocol_info->ProviderId) == 0) { - index = i; - } - } - - /* Check if the protocol uses an msafd socket. */ - if (index < 0) { - return INVALID_SOCKET; - } - - /* If we didn't (try) to create a peer socket yet, try to make one. Don't */ - /* try again if the peer socket creation failed earlier for the same */ - /* protocol. */ - peer_socket = loop->poll_peer_sockets[index]; - if (peer_socket == 0) { - peer_socket = uv__fast_poll_create_peer_socket(loop->iocp, protocol_info); - loop->poll_peer_sockets[index] = peer_socket; - } - - return peer_socket; -} - - -static DWORD WINAPI uv__slow_poll_thread_proc(void* arg) { - uv_req_t* req = (uv_req_t*) arg; - uv_poll_t* handle = (uv_poll_t*) req->data; - unsigned char reported_events; - int r; - uv_single_fd_set_t rfds, wfds, efds; - struct timeval timeout; - - assert(handle->type == UV_POLL); - assert(req->type == UV_POLL_REQ); - - if (handle->events & UV_READABLE) { - rfds.fd_count = 1; - rfds.fd_array[0] = handle->socket; - } else { - rfds.fd_count = 0; - } - - if (handle->events & UV_WRITABLE) { - wfds.fd_count = 1; - wfds.fd_array[0] = handle->socket; - efds.fd_count = 1; - efds.fd_array[0] = handle->socket; - } else { - wfds.fd_count = 0; - efds.fd_count = 0; - } - - /* Make the select() time out after 3 minutes. If select() hangs because */ - /* the user closed the socket, we will at least not hang indefinitely. */ - timeout.tv_sec = 3 * 60; - timeout.tv_usec = 0; - - r = select(1, (fd_set*) &rfds, (fd_set*) &wfds, (fd_set*) &efds, &timeout); - if (r == SOCKET_ERROR) { - /* Queue this req, reporting an error. */ - SET_REQ_ERROR(&handle->poll_req_1, WSAGetLastError()); - POST_COMPLETION_FOR_REQ(handle->loop, req); - return 0; - } - - reported_events = 0; - - if (r > 0) { - if (rfds.fd_count > 0) { - assert(rfds.fd_count == 1); - assert(rfds.fd_array[0] == handle->socket); - reported_events |= UV_READABLE; - } - - if (wfds.fd_count > 0) { - assert(wfds.fd_count == 1); - assert(wfds.fd_array[0] == handle->socket); - reported_events |= UV_WRITABLE; - } else if (efds.fd_count > 0) { - assert(efds.fd_count == 1); - assert(efds.fd_array[0] == handle->socket); - reported_events |= UV_WRITABLE; - } - } - - SET_REQ_SUCCESS(req); - req->overlapped.InternalHigh = (DWORD) reported_events; - POST_COMPLETION_FOR_REQ(handle->loop, req); - - return 0; -} - - -static void uv__slow_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) { - uv_req_t* req; - - /* Find a yet unsubmitted req to submit. */ - if (handle->submitted_events_1 == 0) { - req = &handle->poll_req_1; - handle->submitted_events_1 = handle->events; - handle->mask_events_1 = 0; - handle->mask_events_2 = handle->events; - } else if (handle->submitted_events_2 == 0) { - req = &handle->poll_req_2; - handle->submitted_events_2 = handle->events; - handle->mask_events_1 = handle->events; - handle->mask_events_2 = 0; - } else { - assert(0); - return; - } - - if (!QueueUserWorkItem(uv__slow_poll_thread_proc, - (void*) req, - WT_EXECUTELONGFUNCTION)) { - /* Make this req pending, reporting an error. */ - SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, req); - } -} - - - -static void uv__slow_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, - uv_req_t* req) { - unsigned char mask_events; - int err; - - if (req == &handle->poll_req_1) { - handle->submitted_events_1 = 0; - mask_events = handle->mask_events_1; - } else if (req == &handle->poll_req_2) { - handle->submitted_events_2 = 0; - mask_events = handle->mask_events_2; - } else { - assert(0); - return; - } - - if (!REQ_SUCCESS(req)) { - /* Error. */ - if (handle->events != 0) { - err = GET_REQ_ERROR(req); - handle->events = 0; /* Stop the watcher */ - handle->poll_cb(handle, uv_translate_sys_error(err), 0); - } - } else { - /* Got some events. */ - int events = req->overlapped.InternalHigh & handle->events & ~mask_events; - if (events != 0) { - handle->poll_cb(handle, 0, events); - } - } - - if ((handle->events & ~(handle->submitted_events_1 | - handle->submitted_events_2)) != 0) { - uv__slow_poll_submit_poll_req(loop, handle); - } else if ((handle->flags & UV__HANDLE_CLOSING) && - handle->submitted_events_1 == 0 && - handle->submitted_events_2 == 0) { - uv_want_endgame(loop, (uv_handle_t*) handle); - } -} - - -static int uv__slow_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) { - assert(handle->type == UV_POLL); - assert(!(handle->flags & UV__HANDLE_CLOSING)); - assert((events & ~(UV_READABLE | UV_WRITABLE)) == 0); - - handle->events = events; - - if (handle->events != 0) { - uv__handle_start(handle); - } else { - uv__handle_stop(handle); - } - - if ((handle->events & - ~(handle->submitted_events_1 | handle->submitted_events_2)) != 0) { - uv__slow_poll_submit_poll_req(handle->loop, handle); - } - - return 0; -} - - -static int uv__slow_poll_close(uv_loop_t* loop, uv_poll_t* handle) { - handle->events = 0; - uv__handle_closing(handle); - - if (handle->submitted_events_1 == 0 && - handle->submitted_events_2 == 0) { - uv_want_endgame(loop, (uv_handle_t*) handle); - } - - return 0; -} - - -int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) { - return uv_poll_init_socket(loop, handle, (SOCKET) uv__get_osfhandle(fd)); -} - - -int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle, - uv_os_sock_t socket) { - WSAPROTOCOL_INFOW protocol_info; - int len; - SOCKET peer_socket, base_socket; - DWORD bytes; - DWORD yes = 1; - - /* Set the socket to nonblocking mode */ - if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) - return uv_translate_sys_error(WSAGetLastError()); - - /* Try to obtain a base handle for the socket. This increases this chances */ - /* that we find an AFD handle and are able to use the fast poll mechanism. */ - /* This will always fail on windows XP/2k3, since they don't support the */ - /* SIO_BASE_HANDLE ioctl. */ -#ifndef NDEBUG - base_socket = INVALID_SOCKET; -#endif - - if (WSAIoctl(socket, - SIO_BASE_HANDLE, - NULL, - 0, - &base_socket, - sizeof base_socket, - &bytes, - NULL, - NULL) == 0) { - assert(base_socket != 0 && base_socket != INVALID_SOCKET); - socket = base_socket; - } - - uv__handle_init(loop, (uv_handle_t*) handle, UV_POLL); - handle->socket = socket; - handle->events = 0; - - /* Obtain protocol information about the socket. */ - len = sizeof protocol_info; - if (getsockopt(socket, - SOL_SOCKET, - SO_PROTOCOL_INFOW, - (char*) &protocol_info, - &len) != 0) { - return uv_translate_sys_error(WSAGetLastError()); - } - - /* Get the peer socket that is needed to enable fast poll. If the returned */ - /* value is NULL, the protocol is not implemented by MSAFD and we'll have */ - /* to use slow mode. */ - peer_socket = uv__fast_poll_get_peer_socket(loop, &protocol_info); - - if (peer_socket != INVALID_SOCKET) { - /* Initialize fast poll specific fields. */ - handle->peer_socket = peer_socket; - } else { - /* Initialize slow poll specific fields. */ - handle->flags |= UV_HANDLE_POLL_SLOW; - } - - /* Initialize 2 poll reqs. */ - handle->submitted_events_1 = 0; - uv_req_init(loop, (uv_req_t*) &(handle->poll_req_1)); - handle->poll_req_1.type = UV_POLL_REQ; - handle->poll_req_1.data = handle; - - handle->submitted_events_2 = 0; - uv_req_init(loop, (uv_req_t*) &(handle->poll_req_2)); - handle->poll_req_2.type = UV_POLL_REQ; - handle->poll_req_2.data = handle; - - return 0; -} - - -int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb cb) { - int err; - - if (!(handle->flags & UV_HANDLE_POLL_SLOW)) { - err = uv__fast_poll_set(handle->loop, handle, events); - } else { - err = uv__slow_poll_set(handle->loop, handle, events); - } - - if (err) { - return uv_translate_sys_error(err); - } - - handle->poll_cb = cb; - - return 0; -} - - -int uv_poll_stop(uv_poll_t* handle) { - int err; - - if (!(handle->flags & UV_HANDLE_POLL_SLOW)) { - err = uv__fast_poll_set(handle->loop, handle, 0); - } else { - err = uv__slow_poll_set(handle->loop, handle, 0); - } - - return uv_translate_sys_error(err); -} - - -void uv_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, uv_req_t* req) { - if (!(handle->flags & UV_HANDLE_POLL_SLOW)) { - uv__fast_poll_process_poll_req(loop, handle, req); - } else { - uv__slow_poll_process_poll_req(loop, handle, req); - } -} - - -int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle) { - if (!(handle->flags & UV_HANDLE_POLL_SLOW)) { - return uv__fast_poll_close(loop, handle); - } else { - return uv__slow_poll_close(loop, handle); - } -} - - -void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle) { - assert(handle->flags & UV__HANDLE_CLOSING); - assert(!(handle->flags & UV_HANDLE_CLOSED)); - - assert(handle->submitted_events_1 == 0); - assert(handle->submitted_events_2 == 0); - - uv__handle_close(handle); -} diff --git a/libuv/src/win/process-stdio.c b/libuv/src/win/process-stdio.c deleted file mode 100644 index 98566da..0000000 --- a/libuv/src/win/process-stdio.c +++ /dev/null @@ -1,510 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include - -#include "uv.h" -#include "internal.h" -#include "handle-inl.h" - - -/* - * The `child_stdio_buffer` buffer has the following layout: - * int number_of_fds - * unsigned char crt_flags[number_of_fds] - * HANDLE os_handle[number_of_fds] - */ -#define CHILD_STDIO_SIZE(count) \ - (sizeof(int) + \ - sizeof(unsigned char) * (count) + \ - sizeof(uintptr_t) * (count)) - -#define CHILD_STDIO_COUNT(buffer) \ - *((unsigned int*) (buffer)) - -#define CHILD_STDIO_CRT_FLAGS(buffer, fd) \ - *((unsigned char*) (buffer) + sizeof(int) + fd) - -#define CHILD_STDIO_HANDLE(buffer, fd) \ - *((HANDLE*) ((unsigned char*) (buffer) + \ - sizeof(int) + \ - sizeof(unsigned char) * \ - CHILD_STDIO_COUNT((buffer)) + \ - sizeof(HANDLE) * (fd))) - - -/* CRT file descriptor mode flags */ -#define FOPEN 0x01 -#define FEOFLAG 0x02 -#define FCRLF 0x04 -#define FPIPE 0x08 -#define FNOINHERIT 0x10 -#define FAPPEND 0x20 -#define FDEV 0x40 -#define FTEXT 0x80 - - -/* - * Clear the HANDLE_FLAG_INHERIT flag from all HANDLEs that were inherited - * the parent process. Don't check for errors - the stdio handles may not be - * valid, or may be closed already. There is no guarantee that this function - * does a perfect job. - */ -void uv_disable_stdio_inheritance(void) { - HANDLE handle; - STARTUPINFOW si; - - /* Make the windows stdio handles non-inheritable. */ - handle = GetStdHandle(STD_INPUT_HANDLE); - if (handle != NULL && handle != INVALID_HANDLE_VALUE) - SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0); - - handle = GetStdHandle(STD_OUTPUT_HANDLE); - if (handle != NULL && handle != INVALID_HANDLE_VALUE) - SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0); - - handle = GetStdHandle(STD_ERROR_HANDLE); - if (handle != NULL && handle != INVALID_HANDLE_VALUE) - SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0); - - /* Make inherited CRT FDs non-inheritable. */ - GetStartupInfoW(&si); - if (uv__stdio_verify(si.lpReserved2, si.cbReserved2)) - uv__stdio_noinherit(si.lpReserved2); -} - - -static int uv__create_stdio_pipe_pair(uv_loop_t* loop, - uv_pipe_t* server_pipe, HANDLE* child_pipe_ptr, unsigned int flags) { - char pipe_name[64]; - SECURITY_ATTRIBUTES sa; - DWORD server_access = 0; - DWORD client_access = 0; - HANDLE child_pipe = INVALID_HANDLE_VALUE; - int err; - - if (flags & UV_READABLE_PIPE) { - /* The server needs inbound access too, otherwise CreateNamedPipe() */ - /* won't give us the FILE_READ_ATTRIBUTES permission. We need that to */ - /* probe the state of the write buffer when we're trying to shutdown */ - /* the pipe. */ - server_access |= PIPE_ACCESS_OUTBOUND | PIPE_ACCESS_INBOUND; - client_access |= GENERIC_READ | FILE_WRITE_ATTRIBUTES; - } - if (flags & UV_WRITABLE_PIPE) { - server_access |= PIPE_ACCESS_INBOUND; - client_access |= GENERIC_WRITE | FILE_READ_ATTRIBUTES; - } - - /* Create server pipe handle. */ - err = uv_stdio_pipe_server(loop, - server_pipe, - server_access, - pipe_name, - sizeof(pipe_name)); - if (err) - goto error; - - /* Create child pipe handle. */ - sa.nLength = sizeof sa; - sa.lpSecurityDescriptor = NULL; - sa.bInheritHandle = TRUE; - - child_pipe = CreateFileA(pipe_name, - client_access, - 0, - &sa, - OPEN_EXISTING, - server_pipe->ipc ? FILE_FLAG_OVERLAPPED : 0, - NULL); - if (child_pipe == INVALID_HANDLE_VALUE) { - err = GetLastError(); - goto error; - } - -#ifndef NDEBUG - /* Validate that the pipe was opened in the right mode. */ - { - DWORD mode; - BOOL r = GetNamedPipeHandleState(child_pipe, - &mode, - NULL, - NULL, - NULL, - NULL, - 0); - assert(r == TRUE); - assert(mode == (PIPE_READMODE_BYTE | PIPE_WAIT)); - } -#endif - - /* Do a blocking ConnectNamedPipe. This should not block because we have */ - /* both ends of the pipe created. */ - if (!ConnectNamedPipe(server_pipe->handle, NULL)) { - if (GetLastError() != ERROR_PIPE_CONNECTED) { - err = GetLastError(); - goto error; - } - } - - /* The server end is now readable and/or writable. */ - if (flags & UV_READABLE_PIPE) - server_pipe->flags |= UV_HANDLE_WRITABLE; - if (flags & UV_WRITABLE_PIPE) - server_pipe->flags |= UV_HANDLE_READABLE; - - *child_pipe_ptr = child_pipe; - return 0; - - error: - if (server_pipe->handle != INVALID_HANDLE_VALUE) { - uv_pipe_cleanup(loop, server_pipe); - } - - if (child_pipe != INVALID_HANDLE_VALUE) { - CloseHandle(child_pipe); - } - - return err; -} - - -static int uv__duplicate_handle(uv_loop_t* loop, HANDLE handle, HANDLE* dup) { - HANDLE current_process; - - - /* _get_osfhandle will sometimes return -2 in case of an error. This seems */ - /* to happen when fd <= 2 and the process' corresponding stdio handle is */ - /* set to NULL. Unfortunately DuplicateHandle will happily duplicate */ - /* (HANDLE) -2, so this situation goes unnoticed until someone tries to */ - /* use the duplicate. Therefore we filter out known-invalid handles here. */ - if (handle == INVALID_HANDLE_VALUE || - handle == NULL || - handle == (HANDLE) -2) { - *dup = INVALID_HANDLE_VALUE; - return ERROR_INVALID_HANDLE; - } - - current_process = GetCurrentProcess(); - - if (!DuplicateHandle(current_process, - handle, - current_process, - dup, - 0, - TRUE, - DUPLICATE_SAME_ACCESS)) { - *dup = INVALID_HANDLE_VALUE; - return GetLastError(); - } - - return 0; -} - - -static int uv__duplicate_fd(uv_loop_t* loop, int fd, HANDLE* dup) { - HANDLE handle; - - if (fd == -1) { - *dup = INVALID_HANDLE_VALUE; - return ERROR_INVALID_HANDLE; - } - - handle = uv__get_osfhandle(fd); - return uv__duplicate_handle(loop, handle, dup); -} - - -int uv__create_nul_handle(HANDLE* handle_ptr, - DWORD access) { - HANDLE handle; - SECURITY_ATTRIBUTES sa; - - sa.nLength = sizeof sa; - sa.lpSecurityDescriptor = NULL; - sa.bInheritHandle = TRUE; - - handle = CreateFileW(L"NUL", - access, - FILE_SHARE_READ | FILE_SHARE_WRITE, - &sa, - OPEN_EXISTING, - 0, - NULL); - if (handle == INVALID_HANDLE_VALUE) { - return GetLastError(); - } - - *handle_ptr = handle; - return 0; -} - - -int uv__stdio_create(uv_loop_t* loop, - const uv_process_options_t* options, - BYTE** buffer_ptr) { - BYTE* buffer; - int count, i; - int err; - - count = options->stdio_count; - - if (count < 0 || count > 255) { - /* Only support FDs 0-255 */ - return ERROR_NOT_SUPPORTED; - } else if (count < 3) { - /* There should always be at least 3 stdio handles. */ - count = 3; - } - - /* Allocate the child stdio buffer */ - buffer = (BYTE*) malloc(CHILD_STDIO_SIZE(count)); - if (buffer == NULL) { - return ERROR_OUTOFMEMORY; - } - - /* Prepopulate the buffer with INVALID_HANDLE_VALUE handles so we can */ - /* clean up on failure. */ - CHILD_STDIO_COUNT(buffer) = count; - for (i = 0; i < count; i++) { - CHILD_STDIO_CRT_FLAGS(buffer, i) = 0; - CHILD_STDIO_HANDLE(buffer, i) = INVALID_HANDLE_VALUE; - } - - for (i = 0; i < count; i++) { - uv_stdio_container_t fdopt; - if (i < options->stdio_count) { - fdopt = options->stdio[i]; - } else { - fdopt.flags = UV_IGNORE; - } - - switch (fdopt.flags & (UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD | - UV_INHERIT_STREAM)) { - case UV_IGNORE: - /* Starting a process with no stdin/stout/stderr can confuse it. */ - /* So no matter what the user specified, we make sure the first */ - /* three FDs are always open in their typical modes, e.g. stdin */ - /* be readable and stdout/err should be writable. For FDs > 2, don't */ - /* do anything - all handles in the stdio buffer are initialized with */ - /* INVALID_HANDLE_VALUE, which should be okay. */ - if (i <= 2) { - DWORD access = (i == 0) ? FILE_GENERIC_READ : - FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES; - - err = uv__create_nul_handle(&CHILD_STDIO_HANDLE(buffer, i), - access); - if (err) - goto error; - - CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV; - } - break; - - case UV_CREATE_PIPE: { - /* Create a pair of two connected pipe ends; one end is turned into */ - /* an uv_pipe_t for use by the parent. The other one is given to */ - /* the child. */ - uv_pipe_t* parent_pipe = (uv_pipe_t*) fdopt.data.stream; - HANDLE child_pipe = INVALID_HANDLE_VALUE; - - /* Create a new, connected pipe pair. stdio[i].stream should point */ - /* to an uninitialized, but not connected pipe handle. */ - assert(fdopt.data.stream->type == UV_NAMED_PIPE); - assert(!(fdopt.data.stream->flags & UV_HANDLE_CONNECTION)); - assert(!(fdopt.data.stream->flags & UV_HANDLE_PIPESERVER)); - - err = uv__create_stdio_pipe_pair(loop, - parent_pipe, - &child_pipe, - fdopt.flags); - if (err) - goto error; - - CHILD_STDIO_HANDLE(buffer, i) = child_pipe; - CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FPIPE; - break; - } - - case UV_INHERIT_FD: { - /* Inherit a raw FD. */ - HANDLE child_handle; - - /* Make an inheritable duplicate of the handle. */ - err = uv__duplicate_fd(loop, fdopt.data.fd, &child_handle); - if (err) { - /* If fdopt.data.fd is not valid and fd fd <= 2, then ignore the */ - /* error. */ - if (fdopt.data.fd <= 2 && err == ERROR_INVALID_HANDLE) { - CHILD_STDIO_CRT_FLAGS(buffer, i) = 0; - CHILD_STDIO_HANDLE(buffer, i) = INVALID_HANDLE_VALUE; - break; - } - goto error; - } - - /* Figure out what the type is. */ - switch (GetFileType(child_handle)) { - case FILE_TYPE_DISK: - CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN; - break; - - case FILE_TYPE_PIPE: - CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FPIPE; - - case FILE_TYPE_CHAR: - case FILE_TYPE_REMOTE: - CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV; - break; - - case FILE_TYPE_UNKNOWN: - if (GetLastError() != 0) { - err = GetLastError(); - CloseHandle(child_handle); - goto error; - } - CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV; - break; - - default: - assert(0); - return -1; - } - - CHILD_STDIO_HANDLE(buffer, i) = child_handle; - break; - } - - case UV_INHERIT_STREAM: { - /* Use an existing stream as the stdio handle for the child. */ - HANDLE stream_handle, child_handle; - unsigned char crt_flags; - uv_stream_t* stream = fdopt.data.stream; - - /* Leech the handle out of the stream. */ - if (stream->type == UV_TTY) { - stream_handle = ((uv_tty_t*) stream)->handle; - crt_flags = FOPEN | FDEV; - } else if (stream->type == UV_NAMED_PIPE && - stream->flags & UV_HANDLE_CONNECTED) { - stream_handle = ((uv_pipe_t*) stream)->handle; - crt_flags = FOPEN | FPIPE; - } else { - stream_handle = INVALID_HANDLE_VALUE; - crt_flags = 0; - } - - if (stream_handle == NULL || - stream_handle == INVALID_HANDLE_VALUE) { - /* The handle is already closed, or not yet created, or the */ - /* stream type is not supported. */ - err = ERROR_NOT_SUPPORTED; - goto error; - } - - /* Make an inheritable copy of the handle. */ - err = uv__duplicate_handle(loop, stream_handle, &child_handle); - if (err) - goto error; - - CHILD_STDIO_HANDLE(buffer, i) = child_handle; - CHILD_STDIO_CRT_FLAGS(buffer, i) = crt_flags; - break; - } - - default: - assert(0); - return -1; - } - } - - *buffer_ptr = buffer; - return 0; - - error: - uv__stdio_destroy(buffer); - return err; -} - - -void uv__stdio_destroy(BYTE* buffer) { - int i, count; - - count = CHILD_STDIO_COUNT(buffer); - for (i = 0; i < count; i++) { - HANDLE handle = CHILD_STDIO_HANDLE(buffer, i); - if (handle != INVALID_HANDLE_VALUE) { - CloseHandle(handle); - } - } - - free(buffer); -} - - -void uv__stdio_noinherit(BYTE* buffer) { - int i, count; - - count = CHILD_STDIO_COUNT(buffer); - for (i = 0; i < count; i++) { - HANDLE handle = CHILD_STDIO_HANDLE(buffer, i); - if (handle != INVALID_HANDLE_VALUE) { - SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0); - } - } -} - - -int uv__stdio_verify(BYTE* buffer, WORD size) { - unsigned int count; - - /* Check the buffer pointer. */ - if (buffer == NULL) - return 0; - - /* Verify that the buffer is at least big enough to hold the count. */ - if (size < CHILD_STDIO_SIZE(0)) - return 0; - - /* Verify if the count is within range. */ - count = CHILD_STDIO_COUNT(buffer); - if (count > 256) - return 0; - - /* Verify that the buffer size is big enough to hold info for N FDs. */ - if (size < CHILD_STDIO_SIZE(count)) - return 0; - - return 1; -} - - -WORD uv__stdio_size(BYTE* buffer) { - return (WORD) CHILD_STDIO_SIZE(CHILD_STDIO_COUNT((buffer))); -} - - -HANDLE uv__stdio_handle(BYTE* buffer, int fd) { - return CHILD_STDIO_HANDLE(buffer, fd); -} diff --git a/libuv/src/win/process.c b/libuv/src/win/process.c deleted file mode 100644 index 3a0106f..0000000 --- a/libuv/src/win/process.c +++ /dev/null @@ -1,1247 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "uv.h" -#include "internal.h" -#include "handle-inl.h" -#include "req-inl.h" - - -#define SIGKILL 9 - - -typedef struct env_var { - const WCHAR* const wide; - const WCHAR* const wide_eq; - const size_t len; /* including null or '=' */ -} env_var_t; - -#define E_V(str) { L##str, L##str L"=", sizeof(str) } - -static const env_var_t required_vars[] = { /* keep me sorted */ - E_V("HOMEDRIVE"), - E_V("HOMEPATH"), - E_V("LOGONSERVER"), - E_V("PATH"), - E_V("SYSTEMDRIVE"), - E_V("SYSTEMROOT"), - E_V("TEMP"), - E_V("USERDOMAIN"), - E_V("USERNAME"), - E_V("USERPROFILE"), - E_V("WINDIR"), -}; -static size_t n_required_vars = ARRAY_SIZE(required_vars); - - -static HANDLE uv_global_job_handle_; -static uv_once_t uv_global_job_handle_init_guard_ = UV_ONCE_INIT; - - -static void uv__init_global_job_handle(void) { - /* Create a job object and set it up to kill all contained processes when - * it's closed. Since this handle is made non-inheritable and we're not - * giving it to anyone, we're the only process holding a reference to it. - * That means that if this process exits it is closed and all the processes - * it contains are killed. All processes created with uv_spawn that are not - * spawned with the UV_PROCESS_DETACHED flag are assigned to this job. - * - * We're setting the JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK flag so only the - * processes that we explicitly add are affected, and *their* subprocesses - * are not. This ensures that our child processes are not limited in their - * ability to use job control on Windows versions that don't deal with - * nested jobs (prior to Windows 8 / Server 2012). It also lets our child - * processes created detached processes without explicitly breaking away - * from job control (which uv_spawn doesn't, either). - */ - SECURITY_ATTRIBUTES attr; - JOBOBJECT_EXTENDED_LIMIT_INFORMATION info; - - memset(&attr, 0, sizeof attr); - attr.bInheritHandle = FALSE; - - memset(&info, 0, sizeof info); - info.BasicLimitInformation.LimitFlags = - JOB_OBJECT_LIMIT_BREAKAWAY_OK | - JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK | - JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION | - JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; - - uv_global_job_handle_ = CreateJobObjectW(&attr, NULL); - if (uv_global_job_handle_ == NULL) - uv_fatal_error(GetLastError(), "CreateJobObjectW"); - - if (!SetInformationJobObject(uv_global_job_handle_, - JobObjectExtendedLimitInformation, - &info, - sizeof info)) - uv_fatal_error(GetLastError(), "SetInformationJobObject"); -} - - -static int uv_utf8_to_utf16_alloc(const char* s, WCHAR** ws_ptr) { - int ws_len, r; - WCHAR* ws; - - ws_len = MultiByteToWideChar(CP_UTF8, - 0, - s, - -1, - NULL, - 0); - if (ws_len <= 0) { - return GetLastError(); - } - - ws = (WCHAR*) malloc(ws_len * sizeof(WCHAR)); - if (ws == NULL) { - return ERROR_OUTOFMEMORY; - } - - r = MultiByteToWideChar(CP_UTF8, - 0, - s, - -1, - ws, - ws_len); - assert(r == ws_len); - - *ws_ptr = ws; - return 0; -} - - -static void uv_process_init(uv_loop_t* loop, uv_process_t* handle) { - uv__handle_init(loop, (uv_handle_t*) handle, UV_PROCESS); - handle->exit_cb = NULL; - handle->pid = 0; - handle->exit_signal = 0; - handle->wait_handle = INVALID_HANDLE_VALUE; - handle->process_handle = INVALID_HANDLE_VALUE; - handle->child_stdio_buffer = NULL; - handle->exit_cb_pending = 0; - - uv_req_init(loop, (uv_req_t*)&handle->exit_req); - handle->exit_req.type = UV_PROCESS_EXIT; - handle->exit_req.data = handle; -} - - -/* - * Path search functions - */ - -/* - * Helper function for search_path - */ -static WCHAR* search_path_join_test(const WCHAR* dir, - size_t dir_len, - const WCHAR* name, - size_t name_len, - const WCHAR* ext, - size_t ext_len, - const WCHAR* cwd, - size_t cwd_len) { - WCHAR *result, *result_pos; - DWORD attrs; - if (dir_len > 2 && dir[0] == L'\\' && dir[1] == L'\\') { - /* It's a UNC path so ignore cwd */ - cwd_len = 0; - } else if (dir_len >= 1 && (dir[0] == L'/' || dir[0] == L'\\')) { - /* It's a full path without drive letter, use cwd's drive letter only */ - cwd_len = 2; - } else if (dir_len >= 2 && dir[1] == L':' && - (dir_len < 3 || (dir[2] != L'/' && dir[2] != L'\\'))) { - /* It's a relative path with drive letter (ext.g. D:../some/file) - * Replace drive letter in dir by full cwd if it points to the same drive, - * otherwise use the dir only. - */ - if (cwd_len < 2 || _wcsnicmp(cwd, dir, 2) != 0) { - cwd_len = 0; - } else { - dir += 2; - dir_len -= 2; - } - } else if (dir_len > 2 && dir[1] == L':') { - /* It's an absolute path with drive letter - * Don't use the cwd at all - */ - cwd_len = 0; - } - - /* Allocate buffer for output */ - result = result_pos = (WCHAR*)malloc(sizeof(WCHAR) * - (cwd_len + 1 + dir_len + 1 + name_len + 1 + ext_len + 1)); - - /* Copy cwd */ - wcsncpy(result_pos, cwd, cwd_len); - result_pos += cwd_len; - - /* Add a path separator if cwd didn't end with one */ - if (cwd_len && wcsrchr(L"\\/:", result_pos[-1]) == NULL) { - result_pos[0] = L'\\'; - result_pos++; - } - - /* Copy dir */ - wcsncpy(result_pos, dir, dir_len); - result_pos += dir_len; - - /* Add a separator if the dir didn't end with one */ - if (dir_len && wcsrchr(L"\\/:", result_pos[-1]) == NULL) { - result_pos[0] = L'\\'; - result_pos++; - } - - /* Copy filename */ - wcsncpy(result_pos, name, name_len); - result_pos += name_len; - - if (ext_len) { - /* Add a dot if the filename didn't end with one */ - if (name_len && result_pos[-1] != '.') { - result_pos[0] = L'.'; - result_pos++; - } - - /* Copy extension */ - wcsncpy(result_pos, ext, ext_len); - result_pos += ext_len; - } - - /* Null terminator */ - result_pos[0] = L'\0'; - - attrs = GetFileAttributesW(result); - - if (attrs != INVALID_FILE_ATTRIBUTES && - !(attrs & FILE_ATTRIBUTE_DIRECTORY)) { - return result; - } - - free(result); - return NULL; -} - - -/* - * Helper function for search_path - */ -static WCHAR* path_search_walk_ext(const WCHAR *dir, - size_t dir_len, - const WCHAR *name, - size_t name_len, - WCHAR *cwd, - size_t cwd_len, - int name_has_ext) { - WCHAR* result; - - /* If the name itself has a nonempty extension, try this extension first */ - if (name_has_ext) { - result = search_path_join_test(dir, dir_len, - name, name_len, - L"", 0, - cwd, cwd_len); - if (result != NULL) { - return result; - } - } - - /* Try .com extension */ - result = search_path_join_test(dir, dir_len, - name, name_len, - L"com", 3, - cwd, cwd_len); - if (result != NULL) { - return result; - } - - /* Try .exe extension */ - result = search_path_join_test(dir, dir_len, - name, name_len, - L"exe", 3, - cwd, cwd_len); - if (result != NULL) { - return result; - } - - return NULL; -} - - -/* - * search_path searches the system path for an executable filename - - * the windows API doesn't provide this as a standalone function nor as an - * option to CreateProcess. - * - * It tries to return an absolute filename. - * - * Furthermore, it tries to follow the semantics that cmd.exe, with this - * exception that PATHEXT environment variable isn't used. Since CreateProcess - * can start only .com and .exe files, only those extensions are tried. This - * behavior equals that of msvcrt's spawn functions. - * - * - Do not search the path if the filename already contains a path (either - * relative or absolute). - * - * - If there's really only a filename, check the current directory for file, - * then search all path directories. - * - * - If filename specified has *any* extension, search for the file with the - * specified extension first. - * - * - If the literal filename is not found in a directory, try *appending* - * (not replacing) .com first and then .exe. - * - * - The path variable may contain relative paths; relative paths are relative - * to the cwd. - * - * - Directories in path may or may not end with a trailing backslash. - * - * - CMD does not trim leading/trailing whitespace from path/pathex entries - * nor from the environment variables as a whole. - * - * - When cmd.exe cannot read a directory, it will just skip it and go on - * searching. However, unlike posix-y systems, it will happily try to run a - * file that is not readable/executable; if the spawn fails it will not - * continue searching. - * - * UNC path support: we are dealing with UNC paths in both the path and the - * filename. This is a deviation from what cmd.exe does (it does not let you - * start a program by specifying an UNC path on the command line) but this is - * really a pointless restriction. - * - */ -static WCHAR* search_path(const WCHAR *file, - WCHAR *cwd, - const WCHAR *path) { - int file_has_dir; - WCHAR* result = NULL; - WCHAR *file_name_start; - WCHAR *dot; - const WCHAR *dir_start, *dir_end, *dir_path; - size_t dir_len; - int name_has_ext; - - size_t file_len = wcslen(file); - size_t cwd_len = wcslen(cwd); - - /* If the caller supplies an empty filename, - * we're not gonna return c:\windows\.exe -- GFY! - */ - if (file_len == 0 - || (file_len == 1 && file[0] == L'.')) { - return NULL; - } - - /* Find the start of the filename so we can split the directory from the */ - /* name. */ - for (file_name_start = (WCHAR*)file + file_len; - file_name_start > file - && file_name_start[-1] != L'\\' - && file_name_start[-1] != L'/' - && file_name_start[-1] != L':'; - file_name_start--); - - file_has_dir = file_name_start != file; - - /* Check if the filename includes an extension */ - dot = wcschr(file_name_start, L'.'); - name_has_ext = (dot != NULL && dot[1] != L'\0'); - - if (file_has_dir) { - /* The file has a path inside, don't use path */ - result = path_search_walk_ext( - file, file_name_start - file, - file_name_start, file_len - (file_name_start - file), - cwd, cwd_len, - name_has_ext); - - } else { - dir_end = path; - - /* The file is really only a name; look in cwd first, then scan path */ - result = path_search_walk_ext(L"", 0, - file, file_len, - cwd, cwd_len, - name_has_ext); - - while (result == NULL) { - if (*dir_end == L'\0') { - break; - } - - /* Skip the separator that dir_end now points to */ - if (dir_end != path || *path == L';') { - dir_end++; - } - - /* Next slice starts just after where the previous one ended */ - dir_start = dir_end; - - /* Slice until the next ; or \0 is found */ - dir_end = wcschr(dir_start, L';'); - if (dir_end == NULL) { - dir_end = wcschr(dir_start, L'\0'); - } - - /* If the slice is zero-length, don't bother */ - if (dir_end - dir_start == 0) { - continue; - } - - dir_path = dir_start; - dir_len = dir_end - dir_start; - - /* Adjust if the path is quoted. */ - if (dir_path[0] == '"' || dir_path[0] == '\'') { - ++dir_path; - --dir_len; - } - - if (dir_path[dir_len - 1] == '"' || dir_path[dir_len - 1] == '\'') { - --dir_len; - } - - result = path_search_walk_ext(dir_path, dir_len, - file, file_len, - cwd, cwd_len, - name_has_ext); - } - } - - return result; -} - - -/* - * Quotes command line arguments - * Returns a pointer to the end (next char to be written) of the buffer - */ -WCHAR* quote_cmd_arg(const WCHAR *source, WCHAR *target) { - size_t len = wcslen(source); - size_t i; - int quote_hit; - WCHAR* start; - - if (len == 0) { - /* Need double quotation for empty argument */ - *(target++) = L'"'; - *(target++) = L'"'; - return target; - } - - if (NULL == wcspbrk(source, L" \t\"")) { - /* No quotation needed */ - wcsncpy(target, source, len); - target += len; - return target; - } - - if (NULL == wcspbrk(source, L"\"\\")) { - /* - * No embedded double quotes or backlashes, so I can just wrap - * quote marks around the whole thing. - */ - *(target++) = L'"'; - wcsncpy(target, source, len); - target += len; - *(target++) = L'"'; - return target; - } - - /* - * Expected input/output: - * input : hello"world - * output: "hello\"world" - * input : hello""world - * output: "hello\"\"world" - * input : hello\world - * output: hello\world - * input : hello\\world - * output: hello\\world - * input : hello\"world - * output: "hello\\\"world" - * input : hello\\"world - * output: "hello\\\\\"world" - * input : hello world\ - * output: "hello world\" - */ - - *(target++) = L'"'; - start = target; - quote_hit = 1; - - for (i = len; i > 0; --i) { - *(target++) = source[i - 1]; - - if (quote_hit && source[i - 1] == L'\\') { - *(target++) = L'\\'; - } else if(source[i - 1] == L'"') { - quote_hit = 1; - *(target++) = L'\\'; - } else { - quote_hit = 0; - } - } - target[0] = L'\0'; - wcsrev(start); - *(target++) = L'"'; - return target; -} - - -int make_program_args(char** args, int verbatim_arguments, WCHAR** dst_ptr) { - char** arg; - WCHAR* dst = NULL; - WCHAR* temp_buffer = NULL; - size_t dst_len = 0; - size_t temp_buffer_len = 0; - WCHAR* pos; - int arg_count = 0; - int err = 0; - - /* Count the required size. */ - for (arg = args; *arg; arg++) { - DWORD arg_len; - - arg_len = MultiByteToWideChar(CP_UTF8, - 0, - *arg, - -1, - NULL, - 0); - if (arg_len == 0) { - return GetLastError(); - } - - dst_len += arg_len; - - if (arg_len > temp_buffer_len) - temp_buffer_len = arg_len; - - arg_count++; - } - - /* Adjust for potential quotes. Also assume the worst-case scenario */ - /* that every character needs escaping, so we need twice as much space. */ - dst_len = dst_len * 2 + arg_count * 2; - - /* Allocate buffer for the final command line. */ - dst = (WCHAR*) malloc(dst_len * sizeof(WCHAR)); - if (dst == NULL) { - err = ERROR_OUTOFMEMORY; - goto error; - } - - /* Allocate temporary working buffer. */ - temp_buffer = (WCHAR*) malloc(temp_buffer_len * sizeof(WCHAR)); - if (temp_buffer == NULL) { - err = ERROR_OUTOFMEMORY; - goto error; - } - - pos = dst; - for (arg = args; *arg; arg++) { - DWORD arg_len; - - /* Convert argument to wide char. */ - arg_len = MultiByteToWideChar(CP_UTF8, - 0, - *arg, - -1, - temp_buffer, - (int) (dst + dst_len - pos)); - if (arg_len == 0) { - err = GetLastError(); - goto error; - } - - if (verbatim_arguments) { - /* Copy verbatim. */ - wcscpy(pos, temp_buffer); - pos += arg_len - 1; - } else { - /* Quote/escape, if needed. */ - pos = quote_cmd_arg(temp_buffer, pos); - } - - *pos++ = *(arg + 1) ? L' ' : L'\0'; - } - - free(temp_buffer); - - *dst_ptr = dst; - return 0; - -error: - free(dst); - free(temp_buffer); - return err; -} - - -int env_strncmp(const wchar_t* a, int na, const wchar_t* b) { - wchar_t* a_eq; - wchar_t* b_eq; - wchar_t* A; - wchar_t* B; - int nb; - int r; - - if (na < 0) { - a_eq = wcschr(a, L'='); - assert(a_eq); - na = (int)(long)(a_eq - a); - } else { - na--; - } - b_eq = wcschr(b, L'='); - assert(b_eq); - nb = b_eq - b; - - A = alloca((na+1) * sizeof(wchar_t)); - B = alloca((nb+1) * sizeof(wchar_t)); - - r = LCMapStringW(LOCALE_INVARIANT, LCMAP_UPPERCASE, a, na, A, na); - assert(r==na); - A[na] = L'\0'; - r = LCMapStringW(LOCALE_INVARIANT, LCMAP_UPPERCASE, b, nb, B, nb); - assert(r==nb); - B[nb] = L'\0'; - - while (1) { - wchar_t AA = *A++; - wchar_t BB = *B++; - if (AA < BB) { - return -1; - } else if (AA > BB) { - return 1; - } else if (!AA && !BB) { - return 0; - } - } -} - - -static int qsort_wcscmp(const void *a, const void *b) { - wchar_t* astr = *(wchar_t* const*)a; - wchar_t* bstr = *(wchar_t* const*)b; - return env_strncmp(astr, -1, bstr); -} - - -/* - * The way windows takes environment variables is different than what C does; - * Windows wants a contiguous block of null-terminated strings, terminated - * with an additional null. - * - * Windows has a few "essential" environment variables. winsock will fail - * to initialize if SYSTEMROOT is not defined; some APIs make reference to - * TEMP. SYSTEMDRIVE is probably also important. We therefore ensure that - * these get defined if the input environment block does not contain any - * values for them. - * - * Also add variables known to Cygwin to be required for correct - * subprocess operation in many cases: - * https://github.com/Alexpux/Cygwin/blob/b266b04fbbd3a595f02ea149e4306d3ab9b1fe3d/winsup/cygwin/environ.cc#L955 - * - */ -int make_program_env(char* env_block[], WCHAR** dst_ptr) { - WCHAR* dst; - WCHAR* ptr; - char** env; - size_t env_len = 0; - int len; - size_t i; - DWORD var_size; - size_t env_block_count = 1; /* 1 for null-terminator */ - WCHAR* dst_copy; - WCHAR** ptr_copy; - WCHAR** env_copy; - DWORD* required_vars_value_len = alloca(n_required_vars * sizeof(DWORD*)); - - /* first pass: determine size in UTF-16 */ - for (env = env_block; *env; env++) { - int len; - if (strchr(*env, '=')) { - len = MultiByteToWideChar(CP_UTF8, - 0, - *env, - -1, - NULL, - 0); - if (len <= 0) { - return GetLastError(); - } - env_len += len; - env_block_count++; - } - } - - /* second pass: copy to UTF-16 environment block */ - dst_copy = _malloca(env_len * sizeof(WCHAR)); - if (!dst_copy) { - return ERROR_OUTOFMEMORY; - } - env_copy = alloca(env_block_count * sizeof(WCHAR*)); - - ptr = dst_copy; - ptr_copy = env_copy; - for (env = env_block; *env; env++) { - if (strchr(*env, '=')) { - len = MultiByteToWideChar(CP_UTF8, - 0, - *env, - -1, - ptr, - (int) (env_len - (ptr - dst_copy))); - if (len <= 0) { - DWORD err = GetLastError(); - _freea(dst_copy); - return err; - } - *ptr_copy++ = ptr; - ptr += len; - } - } - *ptr_copy = NULL; - assert(env_len == ptr - dst_copy); - - /* sort our (UTF-16) copy */ - qsort(env_copy, env_block_count-1, sizeof(wchar_t*), qsort_wcscmp); - - /* third pass: check for required variables */ - for (ptr_copy = env_copy, i = 0; i < n_required_vars; ) { - int cmp; - if (!*ptr_copy) { - cmp = -1; - } else { - cmp = env_strncmp(required_vars[i].wide_eq, - required_vars[i].len, - *ptr_copy); - } - if (cmp < 0) { - /* missing required var */ - var_size = GetEnvironmentVariableW(required_vars[i].wide, NULL, 0); - required_vars_value_len[i] = var_size; - if (var_size != 0) { - env_len += required_vars[i].len; - env_len += var_size; - } - i++; - } else { - ptr_copy++; - if (cmp == 0) - i++; - } - } - - /* final pass: copy, in sort order, and inserting required variables */ - dst = malloc((1+env_len) * sizeof(WCHAR)); - if (!dst) { - _freea(dst_copy); - return ERROR_OUTOFMEMORY; - } - - for (ptr = dst, ptr_copy = env_copy, i = 0; - *ptr_copy || i < n_required_vars; - ptr += len) { - int cmp; - if (i >= n_required_vars) { - cmp = 1; - } else if (!*ptr_copy) { - cmp = -1; - } else { - cmp = env_strncmp(required_vars[i].wide_eq, - required_vars[i].len, - *ptr_copy); - } - if (cmp < 0) { - /* missing required var */ - len = required_vars_value_len[i]; - if (len) { - wcscpy(ptr, required_vars[i].wide_eq); - ptr += required_vars[i].len; - var_size = GetEnvironmentVariableW(required_vars[i].wide, - ptr, - (int) (env_len - (ptr - dst))); - if (var_size != len-1) { /* race condition? */ - uv_fatal_error(GetLastError(), "GetEnvironmentVariableW"); - } - } - i++; - } else { - /* copy var from env_block */ - len = wcslen(*ptr_copy) + 1; - wmemcpy(ptr, *ptr_copy, len); - ptr_copy++; - if (cmp == 0) - i++; - } - } - - /* Terminate with an extra NULL. */ - assert(env_len == (ptr - dst)); - *ptr = L'\0'; - - _freea(dst_copy); - *dst_ptr = dst; - return 0; -} - -/* - * Attempt to find the value of the PATH environment variable in the child's - * preprocessed environment. - * - * If found, a pointer into `env` is returned. If not found, NULL is returned. - */ -static WCHAR* find_path(WCHAR *env) { - for (; env != NULL && *env != 0; env += wcslen(env) + 1) { - if (wcsncmp(env, L"PATH=", 5) == 0) - return &env[5]; - } - - return NULL; -} - -/* - * Called on Windows thread-pool thread to indicate that - * a child process has exited. - */ -static void CALLBACK exit_wait_callback(void* data, BOOLEAN didTimeout) { - uv_process_t* process = (uv_process_t*) data; - uv_loop_t* loop = process->loop; - - assert(didTimeout == FALSE); - assert(process); - assert(!process->exit_cb_pending); - - process->exit_cb_pending = 1; - - /* Post completed */ - POST_COMPLETION_FOR_REQ(loop, &process->exit_req); -} - - -/* Called on main thread after a child process has exited. */ -void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) { - int64_t exit_code; - DWORD status; - - assert(handle->exit_cb_pending); - handle->exit_cb_pending = 0; - - /* If we're closing, don't call the exit callback. Just schedule a close */ - /* callback now. */ - if (handle->flags & UV__HANDLE_CLOSING) { - uv_want_endgame(loop, (uv_handle_t*) handle); - return; - } - - /* Unregister from process notification. */ - if (handle->wait_handle != INVALID_HANDLE_VALUE) { - UnregisterWait(handle->wait_handle); - handle->wait_handle = INVALID_HANDLE_VALUE; - } - - /* Set the handle to inactive: no callbacks will be made after the exit */ - /* callback.*/ - uv__handle_stop(handle); - - if (GetExitCodeProcess(handle->process_handle, &status)) { - exit_code = status; - } else { - /* Unable to to obtain the exit code. This should never happen. */ - exit_code = uv_translate_sys_error(GetLastError()); - } - - /* Fire the exit callback. */ - if (handle->exit_cb) { - handle->exit_cb(handle, exit_code, handle->exit_signal); - } -} - - -void uv_process_close(uv_loop_t* loop, uv_process_t* handle) { - uv__handle_closing(handle); - - if (handle->wait_handle != INVALID_HANDLE_VALUE) { - /* This blocks until either the wait was cancelled, or the callback has */ - /* completed. */ - BOOL r = UnregisterWaitEx(handle->wait_handle, INVALID_HANDLE_VALUE); - if (!r) { - /* This should never happen, and if it happens, we can't recover... */ - uv_fatal_error(GetLastError(), "UnregisterWaitEx"); - } - - handle->wait_handle = INVALID_HANDLE_VALUE; - } - - if (!handle->exit_cb_pending) { - uv_want_endgame(loop, (uv_handle_t*)handle); - } -} - - -void uv_process_endgame(uv_loop_t* loop, uv_process_t* handle) { - assert(!handle->exit_cb_pending); - assert(handle->flags & UV__HANDLE_CLOSING); - assert(!(handle->flags & UV_HANDLE_CLOSED)); - - /* Clean-up the process handle. */ - CloseHandle(handle->process_handle); - - uv__handle_close(handle); -} - - -int uv_spawn(uv_loop_t* loop, - uv_process_t* process, - const uv_process_options_t* options) { - int i; - int err = 0; - WCHAR* path = NULL, *alloc_path = NULL; - BOOL result; - WCHAR* application_path = NULL, *application = NULL, *arguments = NULL, - *env = NULL, *cwd = NULL; - STARTUPINFOW startup; - PROCESS_INFORMATION info; - DWORD process_flags; - - uv_process_init(loop, process); - process->exit_cb = options->exit_cb; - - if (options->flags & (UV_PROCESS_SETGID | UV_PROCESS_SETUID)) { - return UV_ENOTSUP; - } - - if (options->file == NULL || - options->args == NULL) { - return UV_EINVAL; - } - - assert(options->file != NULL); - assert(!(options->flags & ~(UV_PROCESS_DETACHED | - UV_PROCESS_SETGID | - UV_PROCESS_SETUID | - UV_PROCESS_WINDOWS_HIDE | - UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS))); - - err = uv_utf8_to_utf16_alloc(options->file, &application); - if (err) - goto done; - - err = make_program_args( - options->args, - options->flags & UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS, - &arguments); - if (err) - goto done; - - if (options->env) { - err = make_program_env(options->env, &env); - if (err) - goto done; - } - - if (options->cwd) { - /* Explicit cwd */ - err = uv_utf8_to_utf16_alloc(options->cwd, &cwd); - if (err) - goto done; - - } else { - /* Inherit cwd */ - DWORD cwd_len, r; - - cwd_len = GetCurrentDirectoryW(0, NULL); - if (!cwd_len) { - err = GetLastError(); - goto done; - } - - cwd = (WCHAR*) malloc(cwd_len * sizeof(WCHAR)); - if (cwd == NULL) { - err = ERROR_OUTOFMEMORY; - goto done; - } - - r = GetCurrentDirectoryW(cwd_len, cwd); - if (r == 0 || r >= cwd_len) { - err = GetLastError(); - goto done; - } - } - - /* Get PATH environment variable. */ - path = find_path(env); - if (path == NULL) { - DWORD path_len, r; - - path_len = GetEnvironmentVariableW(L"PATH", NULL, 0); - if (path_len == 0) { - err = GetLastError(); - goto done; - } - - alloc_path = (WCHAR*) malloc(path_len * sizeof(WCHAR)); - if (alloc_path == NULL) { - err = ERROR_OUTOFMEMORY; - goto done; - } - path = alloc_path; - - r = GetEnvironmentVariableW(L"PATH", path, path_len); - if (r == 0 || r >= path_len) { - err = GetLastError(); - goto done; - } - } - - err = uv__stdio_create(loop, options, &process->child_stdio_buffer); - if (err) - goto done; - - application_path = search_path(application, - cwd, - path); - if (application_path == NULL) { - /* Not found. */ - err = ERROR_FILE_NOT_FOUND; - goto done; - } - - startup.cb = sizeof(startup); - startup.lpReserved = NULL; - startup.lpDesktop = NULL; - startup.lpTitle = NULL; - startup.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; - - startup.cbReserved2 = uv__stdio_size(process->child_stdio_buffer); - startup.lpReserved2 = (BYTE*) process->child_stdio_buffer; - - startup.hStdInput = uv__stdio_handle(process->child_stdio_buffer, 0); - startup.hStdOutput = uv__stdio_handle(process->child_stdio_buffer, 1); - startup.hStdError = uv__stdio_handle(process->child_stdio_buffer, 2); - - if (options->flags & UV_PROCESS_WINDOWS_HIDE) { - /* Use SW_HIDE to avoid any potential process window. */ - startup.wShowWindow = SW_HIDE; - } else { - startup.wShowWindow = SW_SHOWDEFAULT; - } - - process_flags = CREATE_UNICODE_ENVIRONMENT; - - if (options->flags & UV_PROCESS_DETACHED) { - /* Note that we're not setting the CREATE_BREAKAWAY_FROM_JOB flag. That - * means that libuv might not let you create a fully daemonized process - * when run under job control. However the type of job control that libuv - * itself creates doesn't trickle down to subprocesses so they can still - * daemonize. - * - * A reason to not do this is that CREATE_BREAKAWAY_FROM_JOB makes the - * CreateProcess call fail if we're under job control that doesn't allow - * breakaway. - */ - process_flags |= DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP; - } - - if (!CreateProcessW(application_path, - arguments, - NULL, - NULL, - 1, - process_flags, - env, - cwd, - &startup, - &info)) { - /* CreateProcessW failed. */ - err = GetLastError(); - goto done; - } - - /* Spawn succeeded */ - /* Beyond this point, failure is reported asynchronously. */ - - process->process_handle = info.hProcess; - process->pid = info.dwProcessId; - - /* If the process isn't spawned as detached, assign to the global job */ - /* object so windows will kill it when the parent process dies. */ - if (!(options->flags & UV_PROCESS_DETACHED)) { - uv_once(&uv_global_job_handle_init_guard_, uv__init_global_job_handle); - - if (!AssignProcessToJobObject(uv_global_job_handle_, info.hProcess)) { - /* AssignProcessToJobObject might fail if this process is under job - * control and the job doesn't have the - * JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK flag set, on a Windows version - * that doesn't support nested jobs. - * - * When that happens we just swallow the error and continue without - * establishing a kill-child-on-parent-exit relationship, otherwise - * there would be no way for libuv applications run under job control - * to spawn processes at all. - */ - DWORD err = GetLastError(); - if (err != ERROR_ACCESS_DENIED) - uv_fatal_error(err, "AssignProcessToJobObject"); - } - } - - /* Set IPC pid to all IPC pipes. */ - for (i = 0; i < options->stdio_count; i++) { - const uv_stdio_container_t* fdopt = &options->stdio[i]; - if (fdopt->flags & UV_CREATE_PIPE && - fdopt->data.stream->type == UV_NAMED_PIPE && - ((uv_pipe_t*) fdopt->data.stream)->ipc) { - ((uv_pipe_t*) fdopt->data.stream)->ipc_pid = info.dwProcessId; - } - } - - /* Setup notifications for when the child process exits. */ - result = RegisterWaitForSingleObject(&process->wait_handle, - process->process_handle, exit_wait_callback, (void*)process, INFINITE, - WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE); - if (!result) { - uv_fatal_error(GetLastError(), "RegisterWaitForSingleObject"); - } - - CloseHandle(info.hThread); - - assert(!err); - - /* Make the handle active. It will remain active until the exit callback */ - /* is made or the handle is closed, whichever happens first. */ - uv__handle_start(process); - - /* Cleanup, whether we succeeded or failed. */ - done: - free(application); - free(application_path); - free(arguments); - free(cwd); - free(env); - free(alloc_path); - - if (process->child_stdio_buffer != NULL) { - /* Clean up child stdio handles. */ - uv__stdio_destroy(process->child_stdio_buffer); - process->child_stdio_buffer = NULL; - } - - return uv_translate_sys_error(err); -} - - -static int uv__kill(HANDLE process_handle, int signum) { - switch (signum) { - case SIGTERM: - case SIGKILL: - case SIGINT: { - /* Unconditionally terminate the process. On Windows, killed processes */ - /* normally return 1. */ - DWORD status; - int err; - - if (TerminateProcess(process_handle, 1)) - return 0; - - /* If the process already exited before TerminateProcess was called, */ - /* TerminateProcess will fail with ERROR_ACCESS_DENIED. */ - err = GetLastError(); - if (err == ERROR_ACCESS_DENIED && - GetExitCodeProcess(process_handle, &status) && - status != STILL_ACTIVE) { - return UV_ESRCH; - } - - return uv_translate_sys_error(err); - } - - case 0: { - /* Health check: is the process still alive? */ - DWORD status; - - if (!GetExitCodeProcess(process_handle, &status)) - return uv_translate_sys_error(GetLastError()); - - if (status != STILL_ACTIVE) - return UV_ESRCH; - - return 0; - } - - default: - /* Unsupported signal. */ - return UV_ENOSYS; - } -} - - -int uv_process_kill(uv_process_t* process, int signum) { - int err; - - if (process->process_handle == INVALID_HANDLE_VALUE) { - return UV_EINVAL; - } - - err = uv__kill(process->process_handle, signum); - if (err) { - return err; /* err is already translated. */ - } - - process->exit_signal = signum; - - return 0; -} - - -int uv_kill(int pid, int signum) { - int err; - HANDLE process_handle = OpenProcess(PROCESS_TERMINATE | - PROCESS_QUERY_INFORMATION, FALSE, pid); - - if (process_handle == NULL) { - err = GetLastError(); - if (err == ERROR_INVALID_PARAMETER) { - return UV_ESRCH; - } else { - return uv_translate_sys_error(err); - } - } - - err = uv__kill(process_handle, signum); - CloseHandle(process_handle); - - return err; /* err is already translated. */ -} diff --git a/libuv/src/win/req-inl.h b/libuv/src/win/req-inl.h deleted file mode 100644 index 46c7d9b..0000000 --- a/libuv/src/win/req-inl.h +++ /dev/null @@ -1,213 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_WIN_REQ_INL_H_ -#define UV_WIN_REQ_INL_H_ - -#include - -#include "uv.h" -#include "internal.h" - - -#define SET_REQ_STATUS(req, status) \ - (req)->overlapped.Internal = (ULONG_PTR) (status) - -#define SET_REQ_ERROR(req, error) \ - SET_REQ_STATUS((req), NTSTATUS_FROM_WIN32((error))) - -#define SET_REQ_SUCCESS(req) \ - SET_REQ_STATUS((req), STATUS_SUCCESS) - -#define GET_REQ_STATUS(req) \ - ((NTSTATUS) (req)->overlapped.Internal) - -#define REQ_SUCCESS(req) \ - (NT_SUCCESS(GET_REQ_STATUS((req)))) - -#define GET_REQ_ERROR(req) \ - (pRtlNtStatusToDosError(GET_REQ_STATUS((req)))) - -#define GET_REQ_SOCK_ERROR(req) \ - (uv_ntstatus_to_winsock_error(GET_REQ_STATUS((req)))) - - -#define REGISTER_HANDLE_REQ(loop, handle, req) \ - do { \ - INCREASE_ACTIVE_COUNT((loop), (handle)); \ - uv__req_register((loop), (req)); \ - } while (0) - -#define UNREGISTER_HANDLE_REQ(loop, handle, req) \ - do { \ - DECREASE_ACTIVE_COUNT((loop), (handle)); \ - uv__req_unregister((loop), (req)); \ - } while (0) - - -#define UV_SUCCEEDED_WITHOUT_IOCP(result) \ - ((result) && (handle->flags & UV_HANDLE_SYNC_BYPASS_IOCP)) - -#define UV_SUCCEEDED_WITH_IOCP(result) \ - ((result) || (GetLastError() == ERROR_IO_PENDING)) - - -#define POST_COMPLETION_FOR_REQ(loop, req) \ - if (!PostQueuedCompletionStatus((loop)->iocp, \ - 0, \ - 0, \ - &((req)->overlapped))) { \ - uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus"); \ - } - - -INLINE static void uv_req_init(uv_loop_t* loop, uv_req_t* req) { - req->type = UV_UNKNOWN_REQ; - SET_REQ_SUCCESS(req); -} - - -INLINE static uv_req_t* uv_overlapped_to_req(OVERLAPPED* overlapped) { - return CONTAINING_RECORD(overlapped, uv_req_t, overlapped); -} - - -INLINE static void uv_insert_pending_req(uv_loop_t* loop, uv_req_t* req) { - req->next_req = NULL; - if (loop->pending_reqs_tail) { - req->next_req = loop->pending_reqs_tail->next_req; - loop->pending_reqs_tail->next_req = req; - loop->pending_reqs_tail = req; - } else { - req->next_req = req; - loop->pending_reqs_tail = req; - } -} - - -#define DELEGATE_STREAM_REQ(loop, req, method, handle_at) \ - do { \ - switch (((uv_handle_t*) (req)->handle_at)->type) { \ - case UV_TCP: \ - uv_process_tcp_##method##_req(loop, \ - (uv_tcp_t*) ((req)->handle_at), \ - req); \ - break; \ - \ - case UV_NAMED_PIPE: \ - uv_process_pipe_##method##_req(loop, \ - (uv_pipe_t*) ((req)->handle_at), \ - req); \ - break; \ - \ - case UV_TTY: \ - uv_process_tty_##method##_req(loop, \ - (uv_tty_t*) ((req)->handle_at), \ - req); \ - break; \ - \ - default: \ - assert(0); \ - } \ - } while (0) - - -INLINE static int uv_process_reqs(uv_loop_t* loop) { - uv_req_t* req; - uv_req_t* first; - uv_req_t* next; - - if (loop->pending_reqs_tail == NULL) - return 0; - - first = loop->pending_reqs_tail->next_req; - next = first; - loop->pending_reqs_tail = NULL; - - while (next != NULL) { - req = next; - next = req->next_req != first ? req->next_req : NULL; - - switch (req->type) { - case UV_READ: - DELEGATE_STREAM_REQ(loop, req, read, data); - break; - - case UV_WRITE: - DELEGATE_STREAM_REQ(loop, (uv_write_t*) req, write, handle); - break; - - case UV_ACCEPT: - DELEGATE_STREAM_REQ(loop, req, accept, data); - break; - - case UV_CONNECT: - DELEGATE_STREAM_REQ(loop, (uv_connect_t*) req, connect, handle); - break; - - case UV_SHUTDOWN: - /* Tcp shutdown requests don't come here. */ - assert(((uv_shutdown_t*) req)->handle->type == UV_NAMED_PIPE); - uv_process_pipe_shutdown_req( - loop, - (uv_pipe_t*) ((uv_shutdown_t*) req)->handle, - (uv_shutdown_t*) req); - break; - - case UV_UDP_RECV: - uv_process_udp_recv_req(loop, (uv_udp_t*) req->data, req); - break; - - case UV_UDP_SEND: - uv_process_udp_send_req(loop, - ((uv_udp_send_t*) req)->handle, - (uv_udp_send_t*) req); - break; - - case UV_WAKEUP: - uv_process_async_wakeup_req(loop, (uv_async_t*) req->data, req); - break; - - case UV_SIGNAL_REQ: - uv_process_signal_req(loop, (uv_signal_t*) req->data, req); - break; - - case UV_POLL_REQ: - uv_process_poll_req(loop, (uv_poll_t*) req->data, req); - break; - - case UV_PROCESS_EXIT: - uv_process_proc_exit(loop, (uv_process_t*) req->data); - break; - - case UV_FS_EVENT_REQ: - uv_process_fs_event_req(loop, req, (uv_fs_event_t*) req->data); - break; - - default: - assert(0); - } - } - - return 1; -} - -#endif /* UV_WIN_REQ_INL_H_ */ diff --git a/libuv/src/win/req.c b/libuv/src/win/req.c deleted file mode 100644 index 111cc5e..0000000 --- a/libuv/src/win/req.c +++ /dev/null @@ -1,25 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include - -#include "uv.h" -#include "internal.h" diff --git a/libuv/src/win/signal.c b/libuv/src/win/signal.c deleted file mode 100644 index 2c64a55..0000000 --- a/libuv/src/win/signal.c +++ /dev/null @@ -1,356 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include - -#include "uv.h" -#include "internal.h" -#include "handle-inl.h" -#include "req-inl.h" - - -RB_HEAD(uv_signal_tree_s, uv_signal_s); - -static struct uv_signal_tree_s uv__signal_tree = RB_INITIALIZER(uv__signal_tree); -static ssize_t volatile uv__signal_control_handler_refs = 0; -static CRITICAL_SECTION uv__signal_lock; - - -void uv_signals_init() { - InitializeCriticalSection(&uv__signal_lock); -} - - -static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) { - /* Compare signums first so all watchers with the same signnum end up */ - /* adjacent. */ - if (w1->signum < w2->signum) return -1; - if (w1->signum > w2->signum) return 1; - - /* Sort by loop pointer, so we can easily look up the first item after */ - /* { .signum = x, .loop = NULL } */ - if ((uintptr_t) w1->loop < (uintptr_t) w2->loop) return -1; - if ((uintptr_t) w1->loop > (uintptr_t) w2->loop) return 1; - - if ((uintptr_t) w1 < (uintptr_t) w2) return -1; - if ((uintptr_t) w1 > (uintptr_t) w2) return 1; - - return 0; -} - - -RB_GENERATE_STATIC(uv_signal_tree_s, uv_signal_s, tree_entry, uv__signal_compare); - - -/* - * Dispatches signal {signum} to all active uv_signal_t watchers in all loops. - * Returns 1 if the signal was dispatched to any watcher, or 0 if there were - * no active signal watchers observing this signal. - */ -int uv__signal_dispatch(int signum) { - uv_signal_t lookup; - uv_signal_t* handle; - int dispatched = 0; - - EnterCriticalSection(&uv__signal_lock); - - lookup.signum = signum; - lookup.loop = NULL; - - for (handle = RB_NFIND(uv_signal_tree_s, &uv__signal_tree, &lookup); - handle != NULL && handle->signum == signum; - handle = RB_NEXT(uv_signal_tree_s, &uv__signal_tree, handle)) { - unsigned long previous = InterlockedExchange( - (volatile LONG*) &handle->pending_signum, signum); - - if (!previous) { - POST_COMPLETION_FOR_REQ(handle->loop, &handle->signal_req); - } - - dispatched = 1; - } - - LeaveCriticalSection(&uv__signal_lock); - - return dispatched; -} - - -static BOOL WINAPI uv__signal_control_handler(DWORD type) { - switch (type) { - case CTRL_C_EVENT: - return uv__signal_dispatch(SIGINT); - - case CTRL_BREAK_EVENT: - return uv__signal_dispatch(SIGBREAK); - - case CTRL_CLOSE_EVENT: - if (uv__signal_dispatch(SIGHUP)) { - /* Windows will terminate the process after the control handler */ - /* returns. After that it will just terminate our process. Therefore */ - /* block the signal handler so the main loop has some time to pick */ - /* up the signal and do something for a few seconds. */ - Sleep(INFINITE); - return TRUE; - } - return FALSE; - - case CTRL_LOGOFF_EVENT: - case CTRL_SHUTDOWN_EVENT: - /* These signals are only sent to services. Services have their own */ - /* notification mechanism, so there's no point in handling these. */ - - default: - /* We don't handle these. */ - return FALSE; - } -} - - -static int uv__signal_register_control_handler() { - /* When this function is called, the uv__signal_lock must be held. */ - - /* If the console control handler has already been hooked, just add a */ - /* reference. */ - if (uv__signal_control_handler_refs > 0) { - uv__signal_control_handler_refs++; - return 0; - } - - if (!SetConsoleCtrlHandler(uv__signal_control_handler, TRUE)) - return GetLastError(); - - uv__signal_control_handler_refs++; - - return 0; -} - - -static void uv__signal_unregister_control_handler() { - /* When this function is called, the uv__signal_lock must be held. */ - BOOL r; - - /* Don't unregister if the number of console control handlers exceeds one. */ - /* Just remove a reference in that case. */ - if (uv__signal_control_handler_refs > 1) { - uv__signal_control_handler_refs--; - return; - } - - assert(uv__signal_control_handler_refs == 1); - - r = SetConsoleCtrlHandler(uv__signal_control_handler, FALSE); - /* This should never fail; if it does it is probably a bug in libuv. */ - assert(r); - - uv__signal_control_handler_refs--; -} - - -static int uv__signal_register(int signum) { - switch (signum) { - case SIGINT: - case SIGBREAK: - case SIGHUP: - return uv__signal_register_control_handler(); - - case SIGWINCH: - /* SIGWINCH is generated in tty.c. No need to register anything. */ - return 0; - - case SIGILL: - case SIGABRT_COMPAT: - case SIGFPE: - case SIGSEGV: - case SIGTERM: - case SIGABRT: - /* Signal is never raised. */ - return 0; - - default: - /* Invalid signal. */ - return ERROR_INVALID_PARAMETER; - } -} - - -static void uv__signal_unregister(int signum) { - switch (signum) { - case SIGINT: - case SIGBREAK: - case SIGHUP: - uv__signal_unregister_control_handler(); - return; - - case SIGWINCH: - /* SIGWINCH is generated in tty.c. No need to unregister anything. */ - return; - - case SIGILL: - case SIGABRT_COMPAT: - case SIGFPE: - case SIGSEGV: - case SIGTERM: - case SIGABRT: - /* Nothing is registered for this signal. */ - return; - - default: - /* Libuv bug. */ - assert(0 && "Invalid signum"); - return; - } -} - - -int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle) { - uv_req_t* req; - - uv__handle_init(loop, (uv_handle_t*) handle, UV_SIGNAL); - handle->pending_signum = 0; - handle->signum = 0; - handle->signal_cb = NULL; - - req = &handle->signal_req; - uv_req_init(loop, req); - req->type = UV_SIGNAL_REQ; - req->data = handle; - - return 0; -} - - -int uv_signal_stop(uv_signal_t* handle) { - uv_signal_t* removed_handle; - - /* If the watcher wasn't started, this is a no-op. */ - if (handle->signum == 0) - return 0; - - EnterCriticalSection(&uv__signal_lock); - - uv__signal_unregister(handle->signum); - - removed_handle = RB_REMOVE(uv_signal_tree_s, &uv__signal_tree, handle); - assert(removed_handle == handle); - - LeaveCriticalSection(&uv__signal_lock); - - handle->signum = 0; - uv__handle_stop(handle); - - return 0; -} - - -int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) { - int err; - - /* If the user supplies signum == 0, then return an error already. If the */ - /* signum is otherwise invalid then uv__signal_register will find out */ - /* eventually. */ - if (signum == 0) { - return UV_EINVAL; - } - - /* Short circuit: if the signal watcher is already watching {signum} don't */ - /* go through the process of deregistering and registering the handler. */ - /* Additionally, this avoids pending signals getting lost in the (small) */ - /* time frame that handle->signum == 0. */ - if (signum == handle->signum) { - handle->signal_cb = signal_cb; - return 0; - } - - /* If the signal handler was already active, stop it first. */ - if (handle->signum != 0) { - int r = uv_signal_stop(handle); - /* uv_signal_stop is infallible. */ - assert(r == 0); - } - - EnterCriticalSection(&uv__signal_lock); - - err = uv__signal_register(signum); - if (err) { - /* Uh-oh, didn't work. */ - LeaveCriticalSection(&uv__signal_lock); - return uv_translate_sys_error(err); - } - - handle->signum = signum; - RB_INSERT(uv_signal_tree_s, &uv__signal_tree, handle); - - LeaveCriticalSection(&uv__signal_lock); - - handle->signal_cb = signal_cb; - uv__handle_start(handle); - - return 0; -} - - -void uv_process_signal_req(uv_loop_t* loop, uv_signal_t* handle, - uv_req_t* req) { - long dispatched_signum; - - assert(handle->type == UV_SIGNAL); - assert(req->type == UV_SIGNAL_REQ); - - dispatched_signum = InterlockedExchange( - (volatile LONG*) &handle->pending_signum, 0); - assert(dispatched_signum != 0); - - /* Check if the pending signal equals the signum that we are watching for. */ - /* These can get out of sync when the handler is stopped and restarted */ - /* while the signal_req is pending. */ - if (dispatched_signum == handle->signum) - handle->signal_cb(handle, dispatched_signum); - - if (handle->flags & UV__HANDLE_CLOSING) { - /* When it is closing, it must be stopped at this point. */ - assert(handle->signum == 0); - uv_want_endgame(loop, (uv_handle_t*) handle); - } -} - - -void uv_signal_close(uv_loop_t* loop, uv_signal_t* handle) { - uv_signal_stop(handle); - uv__handle_closing(handle); - - if (handle->pending_signum == 0) { - uv_want_endgame(loop, (uv_handle_t*) handle); - } -} - - -void uv_signal_endgame(uv_loop_t* loop, uv_signal_t* handle) { - assert(handle->flags & UV__HANDLE_CLOSING); - assert(!(handle->flags & UV_HANDLE_CLOSED)); - - assert(handle->signum == 0); - assert(handle->pending_signum == 0); - - handle->flags |= UV_HANDLE_CLOSED; - - uv__handle_close(handle); -} diff --git a/libuv/src/win/stream-inl.h b/libuv/src/win/stream-inl.h deleted file mode 100644 index 97a6b90..0000000 --- a/libuv/src/win/stream-inl.h +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_WIN_STREAM_INL_H_ -#define UV_WIN_STREAM_INL_H_ - -#include - -#include "uv.h" -#include "internal.h" -#include "handle-inl.h" -#include "req-inl.h" - - -INLINE static void uv_stream_init(uv_loop_t* loop, - uv_stream_t* handle, - uv_handle_type type) { - uv__handle_init(loop, (uv_handle_t*) handle, type); - handle->write_queue_size = 0; - handle->activecnt = 0; -} - - -INLINE static void uv_connection_init(uv_stream_t* handle) { - handle->flags |= UV_HANDLE_CONNECTION; - handle->write_reqs_pending = 0; - - uv_req_init(handle->loop, (uv_req_t*) &(handle->read_req)); - handle->read_req.event_handle = NULL; - handle->read_req.wait_handle = INVALID_HANDLE_VALUE; - handle->read_req.type = UV_READ; - handle->read_req.data = handle; - - handle->shutdown_req = NULL; -} - - -#endif /* UV_WIN_STREAM_INL_H_ */ diff --git a/libuv/src/win/stream.c b/libuv/src/win/stream.c deleted file mode 100644 index 36d88d0..0000000 --- a/libuv/src/win/stream.c +++ /dev/null @@ -1,249 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include - -#include "uv.h" -#include "internal.h" -#include "handle-inl.h" -#include "req-inl.h" - - -int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) { - int err; - - err = ERROR_INVALID_PARAMETER; - switch (stream->type) { - case UV_TCP: - err = uv_tcp_listen((uv_tcp_t*)stream, backlog, cb); - break; - case UV_NAMED_PIPE: - err = uv_pipe_listen((uv_pipe_t*)stream, backlog, cb); - break; - default: - assert(0); - } - - return uv_translate_sys_error(err); -} - - -int uv_accept(uv_stream_t* server, uv_stream_t* client) { - int err; - - err = ERROR_INVALID_PARAMETER; - switch (server->type) { - case UV_TCP: - err = uv_tcp_accept((uv_tcp_t*)server, (uv_tcp_t*)client); - break; - case UV_NAMED_PIPE: - err = uv_pipe_accept((uv_pipe_t*)server, client); - break; - default: - assert(0); - } - - return uv_translate_sys_error(err); -} - - -int uv_read_start(uv_stream_t* handle, uv_alloc_cb alloc_cb, - uv_read_cb read_cb) { - int err; - - if (handle->flags & UV_HANDLE_READING) { - return UV_EALREADY; - } - - if (!(handle->flags & UV_HANDLE_READABLE)) { - return UV_ENOTCONN; - } - - err = ERROR_INVALID_PARAMETER; - switch (handle->type) { - case UV_TCP: - err = uv_tcp_read_start((uv_tcp_t*)handle, alloc_cb, read_cb); - break; - case UV_NAMED_PIPE: - err = uv_pipe_read_start((uv_pipe_t*)handle, alloc_cb, read_cb); - break; - case UV_TTY: - err = uv_tty_read_start((uv_tty_t*) handle, alloc_cb, read_cb); - break; - default: - assert(0); - } - - return uv_translate_sys_error(err); -} - - -int uv_read_stop(uv_stream_t* handle) { - int err; - - if (!(handle->flags & UV_HANDLE_READING)) - return 0; - - err = 0; - if (handle->type == UV_TTY) { - err = uv_tty_read_stop((uv_tty_t*) handle); - } else { - if (handle->type == UV_NAMED_PIPE) { - uv__pipe_stop_read((uv_pipe_t*) handle); - } else { - handle->flags &= ~UV_HANDLE_READING; - } - DECREASE_ACTIVE_COUNT(handle->loop, handle); - } - - return uv_translate_sys_error(err); -} - - -int uv_write(uv_write_t* req, - uv_stream_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - uv_write_cb cb) { - uv_loop_t* loop = handle->loop; - int err; - - if (!(handle->flags & UV_HANDLE_WRITABLE)) { - return UV_EPIPE; - } - - err = ERROR_INVALID_PARAMETER; - switch (handle->type) { - case UV_TCP: - err = uv_tcp_write(loop, req, (uv_tcp_t*) handle, bufs, nbufs, cb); - break; - case UV_NAMED_PIPE: - err = uv_pipe_write(loop, req, (uv_pipe_t*) handle, bufs, nbufs, cb); - break; - case UV_TTY: - err = uv_tty_write(loop, req, (uv_tty_t*) handle, bufs, nbufs, cb); - break; - default: - assert(0); - } - - return uv_translate_sys_error(err); -} - - -int uv_write2(uv_write_t* req, - uv_stream_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - uv_stream_t* send_handle, - uv_write_cb cb) { - uv_loop_t* loop = handle->loop; - int err; - - if (!(handle->flags & UV_HANDLE_WRITABLE)) { - return UV_EPIPE; - } - - err = ERROR_INVALID_PARAMETER; - switch (handle->type) { - case UV_NAMED_PIPE: - err = uv_pipe_write2(loop, - req, - (uv_pipe_t*) handle, - bufs, - nbufs, - send_handle, - cb); - break; - default: - assert(0); - } - - return uv_translate_sys_error(err); -} - - -int uv_try_write(uv_stream_t* stream, - const uv_buf_t bufs[], - unsigned int nbufs) { - if (stream->flags & UV__HANDLE_CLOSING) - return UV_EBADF; - if (!(stream->flags & UV_HANDLE_WRITABLE)) - return UV_EPIPE; - - switch (stream->type) { - case UV_TCP: - return uv__tcp_try_write((uv_tcp_t*) stream, bufs, nbufs); - case UV_TTY: - return uv__tty_try_write((uv_tty_t*) stream, bufs, nbufs); - case UV_NAMED_PIPE: - return UV_EAGAIN; - default: - assert(0); - return UV_ENOSYS; - } -} - - -int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) { - uv_loop_t* loop = handle->loop; - - if (!(handle->flags & UV_HANDLE_WRITABLE)) { - return UV_EPIPE; - } - - uv_req_init(loop, (uv_req_t*) req); - req->type = UV_SHUTDOWN; - req->handle = handle; - req->cb = cb; - - handle->flags &= ~UV_HANDLE_WRITABLE; - handle->shutdown_req = req; - handle->reqs_pending++; - REGISTER_HANDLE_REQ(loop, handle, req); - - uv_want_endgame(loop, (uv_handle_t*)handle); - - return 0; -} - - -int uv_is_readable(const uv_stream_t* handle) { - return !!(handle->flags & UV_HANDLE_READABLE); -} - - -int uv_is_writable(const uv_stream_t* handle) { - return !!(handle->flags & UV_HANDLE_WRITABLE); -} - - -int uv_stream_set_blocking(uv_stream_t* handle, int blocking) { - if (handle->type != UV_NAMED_PIPE) - return UV_EINVAL; - - if (blocking != 0) - handle->flags |= UV_HANDLE_BLOCKING_WRITES; - else - handle->flags &= ~UV_HANDLE_BLOCKING_WRITES; - - return 0; -} diff --git a/libuv/src/win/tcp.c b/libuv/src/win/tcp.c deleted file mode 100644 index c5ddbed..0000000 --- a/libuv/src/win/tcp.c +++ /dev/null @@ -1,1474 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include - -#include "uv.h" -#include "internal.h" -#include "handle-inl.h" -#include "stream-inl.h" -#include "req-inl.h" - - -/* - * Threshold of active tcp streams for which to preallocate tcp read buffers. - * (Due to node slab allocator performing poorly under this pattern, - * the optimization is temporarily disabled (threshold=0). This will be - * revisited once node allocator is improved.) - */ -const unsigned int uv_active_tcp_streams_threshold = 0; - -/* - * Number of simultaneous pending AcceptEx calls. - */ -const unsigned int uv_simultaneous_server_accepts = 32; - -/* A zero-size buffer for use by uv_tcp_read */ -static char uv_zero_[] = ""; - -static int uv__tcp_nodelay(uv_tcp_t* handle, SOCKET socket, int enable) { - if (setsockopt(socket, - IPPROTO_TCP, - TCP_NODELAY, - (const char*)&enable, - sizeof enable) == -1) { - return WSAGetLastError(); - } - return 0; -} - - -static int uv__tcp_keepalive(uv_tcp_t* handle, SOCKET socket, int enable, unsigned int delay) { - if (setsockopt(socket, - SOL_SOCKET, - SO_KEEPALIVE, - (const char*)&enable, - sizeof enable) == -1) { - return WSAGetLastError(); - } - - if (enable && setsockopt(socket, - IPPROTO_TCP, - TCP_KEEPALIVE, - (const char*)&delay, - sizeof delay) == -1) { - return WSAGetLastError(); - } - - return 0; -} - - -static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle, - SOCKET socket, int family, int imported) { - DWORD yes = 1; - int non_ifs_lsp; - int err; - - assert(handle->socket == INVALID_SOCKET); - - /* Set the socket to nonblocking mode */ - if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) { - return WSAGetLastError(); - } - - /* Associate it with the I/O completion port. */ - /* Use uv_handle_t pointer as completion key. */ - if (CreateIoCompletionPort((HANDLE)socket, - loop->iocp, - (ULONG_PTR)socket, - 0) == NULL) { - if (imported) { - handle->flags |= UV_HANDLE_EMULATE_IOCP; - } else { - return GetLastError(); - } - } - - if (family == AF_INET6) { - non_ifs_lsp = uv_tcp_non_ifs_lsp_ipv6; - } else { - non_ifs_lsp = uv_tcp_non_ifs_lsp_ipv4; - } - - if (pSetFileCompletionNotificationModes && - !(handle->flags & UV_HANDLE_EMULATE_IOCP) && !non_ifs_lsp) { - if (pSetFileCompletionNotificationModes((HANDLE) socket, - FILE_SKIP_SET_EVENT_ON_HANDLE | - FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) { - handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP; - } else if (GetLastError() != ERROR_INVALID_FUNCTION) { - return GetLastError(); - } - } - - if (handle->flags & UV_HANDLE_TCP_NODELAY) { - err = uv__tcp_nodelay(handle, socket, 1); - if (err) - return err; - } - - /* TODO: Use stored delay. */ - if (handle->flags & UV_HANDLE_TCP_KEEPALIVE) { - err = uv__tcp_keepalive(handle, socket, 1, 60); - if (err) - return err; - } - - handle->socket = socket; - - if (family == AF_INET6) { - handle->flags |= UV_HANDLE_IPV6; - } else { - assert(!(handle->flags & UV_HANDLE_IPV6)); - } - - return 0; -} - - -int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle) { - uv_stream_init(loop, (uv_stream_t*) handle, UV_TCP); - - handle->accept_reqs = NULL; - handle->pending_accepts = NULL; - handle->socket = INVALID_SOCKET; - handle->reqs_pending = 0; - handle->func_acceptex = NULL; - handle->func_connectex = NULL; - handle->processed_accepts = 0; - handle->delayed_error = 0; - - return 0; -} - - -void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) { - int err; - unsigned int i; - uv_tcp_accept_t* req; - - if (handle->flags & UV_HANDLE_CONNECTION && - handle->shutdown_req != NULL && - handle->write_reqs_pending == 0) { - - UNREGISTER_HANDLE_REQ(loop, handle, handle->shutdown_req); - - err = 0; - if (handle->flags & UV__HANDLE_CLOSING) { - err = ERROR_OPERATION_ABORTED; - } else if (shutdown(handle->socket, SD_SEND) == SOCKET_ERROR) { - err = WSAGetLastError(); - } - - if (handle->shutdown_req->cb) { - handle->shutdown_req->cb(handle->shutdown_req, - uv_translate_sys_error(err)); - } - - handle->shutdown_req = NULL; - DECREASE_PENDING_REQ_COUNT(handle); - return; - } - - if (handle->flags & UV__HANDLE_CLOSING && - handle->reqs_pending == 0) { - assert(!(handle->flags & UV_HANDLE_CLOSED)); - - if (!(handle->flags & UV_HANDLE_TCP_SOCKET_CLOSED)) { - closesocket(handle->socket); - handle->socket = INVALID_SOCKET; - handle->flags |= UV_HANDLE_TCP_SOCKET_CLOSED; - } - - if (!(handle->flags & UV_HANDLE_CONNECTION) && handle->accept_reqs) { - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - for (i = 0; i < uv_simultaneous_server_accepts; i++) { - req = &handle->accept_reqs[i]; - if (req->wait_handle != INVALID_HANDLE_VALUE) { - UnregisterWait(req->wait_handle); - req->wait_handle = INVALID_HANDLE_VALUE; - } - if (req->event_handle) { - CloseHandle(req->event_handle); - req->event_handle = NULL; - } - } - } - - free(handle->accept_reqs); - handle->accept_reqs = NULL; - } - - if (handle->flags & UV_HANDLE_CONNECTION && - handle->flags & UV_HANDLE_EMULATE_IOCP) { - if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) { - UnregisterWait(handle->read_req.wait_handle); - handle->read_req.wait_handle = INVALID_HANDLE_VALUE; - } - if (handle->read_req.event_handle) { - CloseHandle(handle->read_req.event_handle); - handle->read_req.event_handle = NULL; - } - } - - uv__handle_close(handle); - loop->active_tcp_streams--; - } -} - - -/* Unlike on Unix, here we don't set SO_REUSEADDR, because it doesn't just - * allow binding to addresses that are in use by sockets in TIME_WAIT, it - * effectively allows 'stealing' a port which is in use by another application. - * - * SO_EXCLUSIVEADDRUSE is also not good here because it does check all sockets, - * regardless of state, so we'd get an error even if the port is in use by a - * socket in TIME_WAIT state. - * - * See issue #1360. - * - */ -static int uv_tcp_try_bind(uv_tcp_t* handle, - const struct sockaddr* addr, - unsigned int addrlen, - unsigned int flags) { - DWORD err; - int r; - - if (handle->socket == INVALID_SOCKET) { - SOCKET sock; - - /* Cannot set IPv6-only mode on non-IPv6 socket. */ - if ((flags & UV_TCP_IPV6ONLY) && addr->sa_family != AF_INET6) - return ERROR_INVALID_PARAMETER; - - sock = socket(addr->sa_family, SOCK_STREAM, 0); - if (sock == INVALID_SOCKET) { - return WSAGetLastError(); - } - - /* Make the socket non-inheritable */ - if (!SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0)) { - err = GetLastError(); - closesocket(sock); - return err; - } - - err = uv_tcp_set_socket(handle->loop, handle, sock, addr->sa_family, 0); - if (err) { - closesocket(sock); - return err; - } - } - -#ifdef IPV6_V6ONLY - if (addr->sa_family == AF_INET6) { - int on; - - on = (flags & UV_TCP_IPV6ONLY) != 0; - - /* TODO: how to handle errors? This may fail if there is no ipv4 stack */ - /* available, or when run on XP/2003 which have no support for dualstack */ - /* sockets. For now we're silently ignoring the error. */ - setsockopt(handle->socket, - IPPROTO_IPV6, - IPV6_V6ONLY, - (const char*)&on, - sizeof on); - } -#endif - - r = bind(handle->socket, addr, addrlen); - - if (r == SOCKET_ERROR) { - err = WSAGetLastError(); - if (err == WSAEADDRINUSE) { - /* Some errors are not to be reported until connect() or listen() */ - handle->delayed_error = err; - } else { - return err; - } - } - - handle->flags |= UV_HANDLE_BOUND; - - return 0; -} - - -static void CALLBACK post_completion(void* context, BOOLEAN timed_out) { - uv_req_t* req; - uv_tcp_t* handle; - - req = (uv_req_t*) context; - assert(req != NULL); - handle = (uv_tcp_t*)req->data; - assert(handle != NULL); - assert(!timed_out); - - if (!PostQueuedCompletionStatus(handle->loop->iocp, - req->overlapped.InternalHigh, - 0, - &req->overlapped)) { - uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus"); - } -} - - -static void CALLBACK post_write_completion(void* context, BOOLEAN timed_out) { - uv_write_t* req; - uv_tcp_t* handle; - - req = (uv_write_t*) context; - assert(req != NULL); - handle = (uv_tcp_t*)req->handle; - assert(handle != NULL); - assert(!timed_out); - - if (!PostQueuedCompletionStatus(handle->loop->iocp, - req->overlapped.InternalHigh, - 0, - &req->overlapped)) { - uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus"); - } -} - - -static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) { - uv_loop_t* loop = handle->loop; - BOOL success; - DWORD bytes; - SOCKET accept_socket; - short family; - - assert(handle->flags & UV_HANDLE_LISTENING); - assert(req->accept_socket == INVALID_SOCKET); - - /* choose family and extension function */ - if (handle->flags & UV_HANDLE_IPV6) { - family = AF_INET6; - } else { - family = AF_INET; - } - - /* Open a socket for the accepted connection. */ - accept_socket = socket(family, SOCK_STREAM, 0); - if (accept_socket == INVALID_SOCKET) { - SET_REQ_ERROR(req, WSAGetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); - handle->reqs_pending++; - return; - } - - /* Make the socket non-inheritable */ - if (!SetHandleInformation((HANDLE) accept_socket, HANDLE_FLAG_INHERIT, 0)) { - SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); - handle->reqs_pending++; - closesocket(accept_socket); - return; - } - - /* Prepare the overlapped structure. */ - memset(&(req->overlapped), 0, sizeof(req->overlapped)); - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - req->overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1); - } - - success = handle->func_acceptex(handle->socket, - accept_socket, - (void*)req->accept_buffer, - 0, - sizeof(struct sockaddr_storage), - sizeof(struct sockaddr_storage), - &bytes, - &req->overlapped); - - if (UV_SUCCEEDED_WITHOUT_IOCP(success)) { - /* Process the req without IOCP. */ - req->accept_socket = accept_socket; - handle->reqs_pending++; - uv_insert_pending_req(loop, (uv_req_t*)req); - } else if (UV_SUCCEEDED_WITH_IOCP(success)) { - /* The req will be processed with IOCP. */ - req->accept_socket = accept_socket; - handle->reqs_pending++; - if (handle->flags & UV_HANDLE_EMULATE_IOCP && - req->wait_handle == INVALID_HANDLE_VALUE && - !RegisterWaitForSingleObject(&req->wait_handle, - req->event_handle, post_completion, (void*) req, - INFINITE, WT_EXECUTEINWAITTHREAD)) { - SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); - handle->reqs_pending++; - return; - } - } else { - /* Make this req pending reporting an error. */ - SET_REQ_ERROR(req, WSAGetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); - handle->reqs_pending++; - /* Destroy the preallocated client socket. */ - closesocket(accept_socket); - /* Destroy the event handle */ - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - CloseHandle(req->overlapped.hEvent); - req->event_handle = NULL; - } - } -} - - -static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) { - uv_read_t* req; - uv_buf_t buf; - int result; - DWORD bytes, flags; - - assert(handle->flags & UV_HANDLE_READING); - assert(!(handle->flags & UV_HANDLE_READ_PENDING)); - - req = &handle->read_req; - memset(&req->overlapped, 0, sizeof(req->overlapped)); - - /* - * Preallocate a read buffer if the number of active streams is below - * the threshold. - */ - if (loop->active_tcp_streams < uv_active_tcp_streams_threshold) { - handle->flags &= ~UV_HANDLE_ZERO_READ; - handle->alloc_cb((uv_handle_t*) handle, 65536, &handle->read_buffer); - if (handle->read_buffer.len == 0) { - handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &handle->read_buffer); - return; - } - assert(handle->read_buffer.base != NULL); - buf = handle->read_buffer; - } else { - handle->flags |= UV_HANDLE_ZERO_READ; - buf.base = (char*) &uv_zero_; - buf.len = 0; - } - - /* Prepare the overlapped structure. */ - memset(&(req->overlapped), 0, sizeof(req->overlapped)); - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - assert(req->event_handle); - req->overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1); - } - - flags = 0; - result = WSARecv(handle->socket, - (WSABUF*)&buf, - 1, - &bytes, - &flags, - &req->overlapped, - NULL); - - if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) { - /* Process the req without IOCP. */ - handle->flags |= UV_HANDLE_READ_PENDING; - req->overlapped.InternalHigh = bytes; - handle->reqs_pending++; - uv_insert_pending_req(loop, (uv_req_t*)req); - } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { - /* The req will be processed with IOCP. */ - handle->flags |= UV_HANDLE_READ_PENDING; - handle->reqs_pending++; - if (handle->flags & UV_HANDLE_EMULATE_IOCP && - req->wait_handle == INVALID_HANDLE_VALUE && - !RegisterWaitForSingleObject(&req->wait_handle, - req->event_handle, post_completion, (void*) req, - INFINITE, WT_EXECUTEINWAITTHREAD)) { - SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); - } - } else { - /* Make this req pending reporting an error. */ - SET_REQ_ERROR(req, WSAGetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); - handle->reqs_pending++; - } -} - - -int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { - uv_loop_t* loop = handle->loop; - unsigned int i, simultaneous_accepts; - uv_tcp_accept_t* req; - int err; - - assert(backlog > 0); - - if (handle->flags & UV_HANDLE_LISTENING) { - handle->connection_cb = cb; - } - - if (handle->flags & UV_HANDLE_READING) { - return WSAEISCONN; - } - - if (handle->delayed_error) { - return handle->delayed_error; - } - - if (!(handle->flags & UV_HANDLE_BOUND)) { - err = uv_tcp_try_bind(handle, - (const struct sockaddr*) &uv_addr_ip4_any_, - sizeof(uv_addr_ip4_any_), - 0); - if (err) - return err; - if (handle->delayed_error) - return handle->delayed_error; - } - - if (!handle->func_acceptex) { - if (!uv_get_acceptex_function(handle->socket, &handle->func_acceptex)) { - return WSAEAFNOSUPPORT; - } - } - - if (!(handle->flags & UV_HANDLE_SHARED_TCP_SOCKET) && - listen(handle->socket, backlog) == SOCKET_ERROR) { - return WSAGetLastError(); - } - - handle->flags |= UV_HANDLE_LISTENING; - handle->connection_cb = cb; - INCREASE_ACTIVE_COUNT(loop, handle); - - simultaneous_accepts = handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT ? 1 - : uv_simultaneous_server_accepts; - - if(!handle->accept_reqs) { - handle->accept_reqs = (uv_tcp_accept_t*) - malloc(uv_simultaneous_server_accepts * sizeof(uv_tcp_accept_t)); - if (!handle->accept_reqs) { - uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); - } - - for (i = 0; i < simultaneous_accepts; i++) { - req = &handle->accept_reqs[i]; - uv_req_init(loop, (uv_req_t*)req); - req->type = UV_ACCEPT; - req->accept_socket = INVALID_SOCKET; - req->data = handle; - - req->wait_handle = INVALID_HANDLE_VALUE; - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - req->event_handle = CreateEvent(NULL, 0, 0, NULL); - if (!req->event_handle) { - uv_fatal_error(GetLastError(), "CreateEvent"); - } - } else { - req->event_handle = NULL; - } - - uv_tcp_queue_accept(handle, req); - } - - /* Initialize other unused requests too, because uv_tcp_endgame */ - /* doesn't know how how many requests were initialized, so it will */ - /* try to clean up {uv_simultaneous_server_accepts} requests. */ - for (i = simultaneous_accepts; i < uv_simultaneous_server_accepts; i++) { - req = &handle->accept_reqs[i]; - uv_req_init(loop, (uv_req_t*) req); - req->type = UV_ACCEPT; - req->accept_socket = INVALID_SOCKET; - req->data = handle; - req->wait_handle = INVALID_HANDLE_VALUE; - req->event_handle = NULL; - } - } - - return 0; -} - - -int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) { - uv_loop_t* loop = server->loop; - int err = 0; - int family; - - uv_tcp_accept_t* req = server->pending_accepts; - - if (!req) { - /* No valid connections found, so we error out. */ - return WSAEWOULDBLOCK; - } - - if (req->accept_socket == INVALID_SOCKET) { - return WSAENOTCONN; - } - - if (server->flags & UV_HANDLE_IPV6) { - family = AF_INET6; - } else { - family = AF_INET; - } - - err = uv_tcp_set_socket(client->loop, - client, - req->accept_socket, - family, - 0); - if (err) { - closesocket(req->accept_socket); - } else { - uv_connection_init((uv_stream_t*) client); - /* AcceptEx() implicitly binds the accepted socket. */ - client->flags |= UV_HANDLE_BOUND | UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; - } - - /* Prepare the req to pick up a new connection */ - server->pending_accepts = req->next_pending; - req->next_pending = NULL; - req->accept_socket = INVALID_SOCKET; - - if (!(server->flags & UV__HANDLE_CLOSING)) { - /* Check if we're in a middle of changing the number of pending accepts. */ - if (!(server->flags & UV_HANDLE_TCP_ACCEPT_STATE_CHANGING)) { - uv_tcp_queue_accept(server, req); - } else { - /* We better be switching to a single pending accept. */ - assert(server->flags & UV_HANDLE_TCP_SINGLE_ACCEPT); - - server->processed_accepts++; - - if (server->processed_accepts >= uv_simultaneous_server_accepts) { - server->processed_accepts = 0; - /* - * All previously queued accept requests are now processed. - * We now switch to queueing just a single accept. - */ - uv_tcp_queue_accept(server, &server->accept_reqs[0]); - server->flags &= ~UV_HANDLE_TCP_ACCEPT_STATE_CHANGING; - server->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT; - } - } - } - - loop->active_tcp_streams++; - - return err; -} - - -int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb, - uv_read_cb read_cb) { - uv_loop_t* loop = handle->loop; - - handle->flags |= UV_HANDLE_READING; - handle->read_cb = read_cb; - handle->alloc_cb = alloc_cb; - INCREASE_ACTIVE_COUNT(loop, handle); - - /* If reading was stopped and then started again, there could still be a */ - /* read request pending. */ - if (!(handle->flags & UV_HANDLE_READ_PENDING)) { - if (handle->flags & UV_HANDLE_EMULATE_IOCP && - !handle->read_req.event_handle) { - handle->read_req.event_handle = CreateEvent(NULL, 0, 0, NULL); - if (!handle->read_req.event_handle) { - uv_fatal_error(GetLastError(), "CreateEvent"); - } - } - uv_tcp_queue_read(loop, handle); - } - - return 0; -} - - -static int uv_tcp_try_connect(uv_connect_t* req, - uv_tcp_t* handle, - const struct sockaddr* addr, - unsigned int addrlen, - uv_connect_cb cb) { - uv_loop_t* loop = handle->loop; - const struct sockaddr* bind_addr; - BOOL success; - DWORD bytes; - int err; - - if (handle->delayed_error) { - return handle->delayed_error; - } - - if (!(handle->flags & UV_HANDLE_BOUND)) { - if (addrlen == sizeof(uv_addr_ip4_any_)) { - bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_; - } else if (addrlen == sizeof(uv_addr_ip6_any_)) { - bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_; - } else { - abort(); - } - err = uv_tcp_try_bind(handle, bind_addr, addrlen, 0); - if (err) - return err; - if (handle->delayed_error) - return handle->delayed_error; - } - - if (!handle->func_connectex) { - if (!uv_get_connectex_function(handle->socket, &handle->func_connectex)) { - return WSAEAFNOSUPPORT; - } - } - - uv_req_init(loop, (uv_req_t*) req); - req->type = UV_CONNECT; - req->handle = (uv_stream_t*) handle; - req->cb = cb; - memset(&req->overlapped, 0, sizeof(req->overlapped)); - - success = handle->func_connectex(handle->socket, - addr, - addrlen, - NULL, - 0, - &bytes, - &req->overlapped); - - if (UV_SUCCEEDED_WITHOUT_IOCP(success)) { - /* Process the req without IOCP. */ - handle->reqs_pending++; - REGISTER_HANDLE_REQ(loop, handle, req); - uv_insert_pending_req(loop, (uv_req_t*)req); - } else if (UV_SUCCEEDED_WITH_IOCP(success)) { - /* The req will be processed with IOCP. */ - handle->reqs_pending++; - REGISTER_HANDLE_REQ(loop, handle, req); - } else { - return WSAGetLastError(); - } - - return 0; -} - - -int uv_tcp_getsockname(const uv_tcp_t* handle, - struct sockaddr* name, - int* namelen) { - int result; - - if (!(handle->flags & UV_HANDLE_BOUND)) { - return UV_EINVAL; - } - - if (handle->delayed_error) { - return uv_translate_sys_error(handle->delayed_error); - } - - result = getsockname(handle->socket, name, namelen); - if (result != 0) { - return uv_translate_sys_error(WSAGetLastError()); - } - - return 0; -} - - -int uv_tcp_getpeername(const uv_tcp_t* handle, - struct sockaddr* name, - int* namelen) { - int result; - - if (!(handle->flags & UV_HANDLE_BOUND)) { - return UV_EINVAL; - } - - if (handle->delayed_error) { - return uv_translate_sys_error(handle->delayed_error); - } - - result = getpeername(handle->socket, name, namelen); - if (result != 0) { - return uv_translate_sys_error(WSAGetLastError()); - } - - return 0; -} - - -int uv_tcp_write(uv_loop_t* loop, - uv_write_t* req, - uv_tcp_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - uv_write_cb cb) { - int result; - DWORD bytes; - - uv_req_init(loop, (uv_req_t*) req); - req->type = UV_WRITE; - req->handle = (uv_stream_t*) handle; - req->cb = cb; - - /* Prepare the overlapped structure. */ - memset(&(req->overlapped), 0, sizeof(req->overlapped)); - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - req->event_handle = CreateEvent(NULL, 0, 0, NULL); - if (!req->event_handle) { - uv_fatal_error(GetLastError(), "CreateEvent"); - } - req->overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1); - req->wait_handle = INVALID_HANDLE_VALUE; - } - - result = WSASend(handle->socket, - (WSABUF*) bufs, - nbufs, - &bytes, - 0, - &req->overlapped, - NULL); - - if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) { - /* Request completed immediately. */ - req->queued_bytes = 0; - handle->reqs_pending++; - handle->write_reqs_pending++; - REGISTER_HANDLE_REQ(loop, handle, req); - uv_insert_pending_req(loop, (uv_req_t*) req); - } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { - /* Request queued by the kernel. */ - req->queued_bytes = uv__count_bufs(bufs, nbufs); - handle->reqs_pending++; - handle->write_reqs_pending++; - REGISTER_HANDLE_REQ(loop, handle, req); - handle->write_queue_size += req->queued_bytes; - if (handle->flags & UV_HANDLE_EMULATE_IOCP && - !RegisterWaitForSingleObject(&req->wait_handle, - req->event_handle, post_write_completion, (void*) req, - INFINITE, WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE)) { - SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); - } - } else { - /* Send failed due to an error. */ - return WSAGetLastError(); - } - - return 0; -} - - -int uv__tcp_try_write(uv_tcp_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs) { - int result; - DWORD bytes; - - if (handle->write_reqs_pending > 0) - return UV_EAGAIN; - - result = WSASend(handle->socket, - (WSABUF*) bufs, - nbufs, - &bytes, - 0, - NULL, - NULL); - - if (result == SOCKET_ERROR) - return uv_translate_sys_error(WSAGetLastError()); - else - return bytes; -} - - -void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, - uv_req_t* req) { - DWORD bytes, flags, err; - uv_buf_t buf; - - assert(handle->type == UV_TCP); - - handle->flags &= ~UV_HANDLE_READ_PENDING; - - if (!REQ_SUCCESS(req)) { - /* An error occurred doing the read. */ - if ((handle->flags & UV_HANDLE_READING) || - !(handle->flags & UV_HANDLE_ZERO_READ)) { - handle->flags &= ~UV_HANDLE_READING; - DECREASE_ACTIVE_COUNT(loop, handle); - buf = (handle->flags & UV_HANDLE_ZERO_READ) ? - uv_buf_init(NULL, 0) : handle->read_buffer; - - err = GET_REQ_SOCK_ERROR(req); - - if (err == WSAECONNABORTED) { - /* - * Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with Unix. - */ - err = WSAECONNRESET; - } - - handle->read_cb((uv_stream_t*)handle, - uv_translate_sys_error(err), - &buf); - } - } else { - if (!(handle->flags & UV_HANDLE_ZERO_READ)) { - /* The read was done with a non-zero buffer length. */ - if (req->overlapped.InternalHigh > 0) { - /* Successful read */ - handle->read_cb((uv_stream_t*)handle, - req->overlapped.InternalHigh, - &handle->read_buffer); - /* Read again only if bytes == buf.len */ - if (req->overlapped.InternalHigh < handle->read_buffer.len) { - goto done; - } - } else { - /* Connection closed */ - if (handle->flags & UV_HANDLE_READING) { - handle->flags &= ~UV_HANDLE_READING; - DECREASE_ACTIVE_COUNT(loop, handle); - } - handle->flags &= ~UV_HANDLE_READABLE; - - buf.base = 0; - buf.len = 0; - handle->read_cb((uv_stream_t*)handle, UV_EOF, &handle->read_buffer); - goto done; - } - } - - /* Do nonblocking reads until the buffer is empty */ - while (handle->flags & UV_HANDLE_READING) { - handle->alloc_cb((uv_handle_t*) handle, 65536, &buf); - if (buf.len == 0) { - handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &buf); - break; - } - assert(buf.base != NULL); - - flags = 0; - if (WSARecv(handle->socket, - (WSABUF*)&buf, - 1, - &bytes, - &flags, - NULL, - NULL) != SOCKET_ERROR) { - if (bytes > 0) { - /* Successful read */ - handle->read_cb((uv_stream_t*)handle, bytes, &buf); - /* Read again only if bytes == buf.len */ - if (bytes < buf.len) { - break; - } - } else { - /* Connection closed */ - handle->flags &= ~(UV_HANDLE_READING | UV_HANDLE_READABLE); - DECREASE_ACTIVE_COUNT(loop, handle); - - handle->read_cb((uv_stream_t*)handle, UV_EOF, &buf); - break; - } - } else { - err = WSAGetLastError(); - if (err == WSAEWOULDBLOCK) { - /* Read buffer was completely empty, report a 0-byte read. */ - handle->read_cb((uv_stream_t*)handle, 0, &buf); - } else { - /* Ouch! serious error. */ - handle->flags &= ~UV_HANDLE_READING; - DECREASE_ACTIVE_COUNT(loop, handle); - - if (err == WSAECONNABORTED) { - /* Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with */ - /* Unix. */ - err = WSAECONNRESET; - } - - handle->read_cb((uv_stream_t*)handle, - uv_translate_sys_error(err), - &buf); - } - break; - } - } - -done: - /* Post another read if still reading and not closing. */ - if ((handle->flags & UV_HANDLE_READING) && - !(handle->flags & UV_HANDLE_READ_PENDING)) { - uv_tcp_queue_read(loop, handle); - } - } - - DECREASE_PENDING_REQ_COUNT(handle); -} - - -void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle, - uv_write_t* req) { - int err; - - assert(handle->type == UV_TCP); - - assert(handle->write_queue_size >= req->queued_bytes); - handle->write_queue_size -= req->queued_bytes; - - UNREGISTER_HANDLE_REQ(loop, handle, req); - - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - if (req->wait_handle != INVALID_HANDLE_VALUE) { - UnregisterWait(req->wait_handle); - req->wait_handle = INVALID_HANDLE_VALUE; - } - if (req->event_handle) { - CloseHandle(req->event_handle); - req->event_handle = NULL; - } - } - - if (req->cb) { - err = uv_translate_sys_error(GET_REQ_SOCK_ERROR(req)); - if (err == UV_ECONNABORTED) { - /* use UV_ECANCELED for consistency with Unix */ - err = UV_ECANCELED; - } - req->cb(req, err); - } - - handle->write_reqs_pending--; - if (handle->shutdown_req != NULL && - handle->write_reqs_pending == 0) { - uv_want_endgame(loop, (uv_handle_t*)handle); - } - - DECREASE_PENDING_REQ_COUNT(handle); -} - - -void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle, - uv_req_t* raw_req) { - uv_tcp_accept_t* req = (uv_tcp_accept_t*) raw_req; - int err; - - assert(handle->type == UV_TCP); - - /* If handle->accepted_socket is not a valid socket, then */ - /* uv_queue_accept must have failed. This is a serious error. We stop */ - /* accepting connections and report this error to the connection */ - /* callback. */ - if (req->accept_socket == INVALID_SOCKET) { - if (handle->flags & UV_HANDLE_LISTENING) { - handle->flags &= ~UV_HANDLE_LISTENING; - DECREASE_ACTIVE_COUNT(loop, handle); - if (handle->connection_cb) { - err = GET_REQ_SOCK_ERROR(req); - handle->connection_cb((uv_stream_t*)handle, - uv_translate_sys_error(err)); - } - } - } else if (REQ_SUCCESS(req) && - setsockopt(req->accept_socket, - SOL_SOCKET, - SO_UPDATE_ACCEPT_CONTEXT, - (char*)&handle->socket, - sizeof(handle->socket)) == 0) { - req->next_pending = handle->pending_accepts; - handle->pending_accepts = req; - - /* Accept and SO_UPDATE_ACCEPT_CONTEXT were successful. */ - if (handle->connection_cb) { - handle->connection_cb((uv_stream_t*)handle, 0); - } - } else { - /* Error related to accepted socket is ignored because the server */ - /* socket may still be healthy. If the server socket is broken */ - /* uv_queue_accept will detect it. */ - closesocket(req->accept_socket); - req->accept_socket = INVALID_SOCKET; - if (handle->flags & UV_HANDLE_LISTENING) { - uv_tcp_queue_accept(handle, req); - } - } - - DECREASE_PENDING_REQ_COUNT(handle); -} - - -void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle, - uv_connect_t* req) { - int err; - - assert(handle->type == UV_TCP); - - UNREGISTER_HANDLE_REQ(loop, handle, req); - - err = 0; - if (REQ_SUCCESS(req)) { - if (setsockopt(handle->socket, - SOL_SOCKET, - SO_UPDATE_CONNECT_CONTEXT, - NULL, - 0) == 0) { - uv_connection_init((uv_stream_t*)handle); - handle->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; - loop->active_tcp_streams++; - } else { - err = WSAGetLastError(); - } - } else { - err = GET_REQ_SOCK_ERROR(req); - } - req->cb(req, uv_translate_sys_error(err)); - - DECREASE_PENDING_REQ_COUNT(handle); -} - - -int uv_tcp_import(uv_tcp_t* tcp, uv__ipc_socket_info_ex* socket_info_ex, - int tcp_connection) { - int err; - SOCKET socket = WSASocketW(FROM_PROTOCOL_INFO, - FROM_PROTOCOL_INFO, - FROM_PROTOCOL_INFO, - &socket_info_ex->socket_info, - 0, - WSA_FLAG_OVERLAPPED); - - if (socket == INVALID_SOCKET) { - return WSAGetLastError(); - } - - if (!SetHandleInformation((HANDLE) socket, HANDLE_FLAG_INHERIT, 0)) { - err = GetLastError(); - closesocket(socket); - return err; - } - - err = uv_tcp_set_socket(tcp->loop, - tcp, - socket, - socket_info_ex->socket_info.iAddressFamily, - 1); - if (err) { - closesocket(socket); - return err; - } - - if (tcp_connection) { - uv_connection_init((uv_stream_t*)tcp); - tcp->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; - } - - tcp->flags |= UV_HANDLE_BOUND; - tcp->flags |= UV_HANDLE_SHARED_TCP_SOCKET; - - tcp->delayed_error = socket_info_ex->delayed_error; - - tcp->loop->active_tcp_streams++; - return 0; -} - - -int uv_tcp_nodelay(uv_tcp_t* handle, int enable) { - int err; - - if (handle->socket != INVALID_SOCKET) { - err = uv__tcp_nodelay(handle, handle->socket, enable); - if (err) - return err; - } - - if (enable) { - handle->flags |= UV_HANDLE_TCP_NODELAY; - } else { - handle->flags &= ~UV_HANDLE_TCP_NODELAY; - } - - return 0; -} - - -int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) { - int err; - - if (handle->socket != INVALID_SOCKET) { - err = uv__tcp_keepalive(handle, handle->socket, enable, delay); - if (err) - return err; - } - - if (enable) { - handle->flags |= UV_HANDLE_TCP_KEEPALIVE; - } else { - handle->flags &= ~UV_HANDLE_TCP_KEEPALIVE; - } - - /* TODO: Store delay if handle->socket isn't created yet. */ - - return 0; -} - - -int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid, - LPWSAPROTOCOL_INFOW protocol_info) { - if (!(handle->flags & UV_HANDLE_CONNECTION)) { - /* - * We're about to share the socket with another process. Because - * this is a listening socket, we assume that the other process will - * be accepting connections on it. So, before sharing the socket - * with another process, we call listen here in the parent process. - */ - - if (!(handle->flags & UV_HANDLE_LISTENING)) { - if (!(handle->flags & UV_HANDLE_BOUND)) { - return ERROR_INVALID_PARAMETER; - } - - if (!(handle->delayed_error)) { - if (listen(handle->socket, SOMAXCONN) == SOCKET_ERROR) { - handle->delayed_error = WSAGetLastError(); - } - } - } - } - - if (WSADuplicateSocketW(handle->socket, pid, protocol_info)) { - return WSAGetLastError(); - } - - handle->flags |= UV_HANDLE_SHARED_TCP_SOCKET; - - return 0; -} - - -int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) { - if (handle->flags & UV_HANDLE_CONNECTION) { - return UV_EINVAL; - } - - /* Check if we're already in the desired mode. */ - if ((enable && !(handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT)) || - (!enable && handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT)) { - return 0; - } - - /* Don't allow switching from single pending accept to many. */ - if (enable) { - return UV_ENOTSUP; - } - - /* Check if we're in a middle of changing the number of pending accepts. */ - if (handle->flags & UV_HANDLE_TCP_ACCEPT_STATE_CHANGING) { - return 0; - } - - handle->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT; - - /* Flip the changing flag if we have already queued multiple accepts. */ - if (handle->flags & UV_HANDLE_LISTENING) { - handle->flags |= UV_HANDLE_TCP_ACCEPT_STATE_CHANGING; - } - - return 0; -} - - -static int uv_tcp_try_cancel_io(uv_tcp_t* tcp) { - SOCKET socket = tcp->socket; - int non_ifs_lsp; - - /* Check if we have any non-IFS LSPs stacked on top of TCP */ - non_ifs_lsp = (tcp->flags & UV_HANDLE_IPV6) ? uv_tcp_non_ifs_lsp_ipv6 : - uv_tcp_non_ifs_lsp_ipv4; - - /* If there are non-ifs LSPs then try to obtain a base handle for the */ - /* socket. This will always fail on Windows XP/3k. */ - if (non_ifs_lsp) { - DWORD bytes; - if (WSAIoctl(socket, - SIO_BASE_HANDLE, - NULL, - 0, - &socket, - sizeof socket, - &bytes, - NULL, - NULL) != 0) { - /* Failed. We can't do CancelIo. */ - return -1; - } - } - - assert(socket != 0 && socket != INVALID_SOCKET); - - if (!CancelIo((HANDLE) socket)) { - return GetLastError(); - } - - /* It worked. */ - return 0; -} - - -void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) { - int close_socket = 1; - - if (tcp->flags & UV_HANDLE_READ_PENDING) { - /* In order for winsock to do a graceful close there must not be any */ - /* any pending reads, or the socket must be shut down for writing */ - if (!(tcp->flags & UV_HANDLE_SHARED_TCP_SOCKET)) { - /* Just do shutdown on non-shared sockets, which ensures graceful close. */ - shutdown(tcp->socket, SD_SEND); - - } else if (uv_tcp_try_cancel_io(tcp) == 0) { - /* In case of a shared socket, we try to cancel all outstanding I/O, */ - /* If that works, don't close the socket yet - wait for the read req to */ - /* return and close the socket in uv_tcp_endgame. */ - close_socket = 0; - - } else { - /* When cancelling isn't possible - which could happen when an LSP is */ - /* present on an old Windows version, we will have to close the socket */ - /* with a read pending. That is not nice because trailing sent bytes */ - /* may not make it to the other side. */ - } - - } else if ((tcp->flags & UV_HANDLE_SHARED_TCP_SOCKET) && - tcp->accept_reqs != NULL) { - /* Under normal circumstances closesocket() will ensure that all pending */ - /* accept reqs are canceled. However, when the socket is shared the */ - /* presence of another reference to the socket in another process will */ - /* keep the accept reqs going, so we have to ensure that these are */ - /* canceled. */ - if (uv_tcp_try_cancel_io(tcp) != 0) { - /* When cancellation is not possible, there is another option: we can */ - /* close the incoming sockets, which will also cancel the accept */ - /* operations. However this is not cool because we might inadvertently */ - /* close a socket that just accepted a new connection, which will */ - /* cause the connection to be aborted. */ - unsigned int i; - for (i = 0; i < uv_simultaneous_server_accepts; i++) { - uv_tcp_accept_t* req = &tcp->accept_reqs[i]; - if (req->accept_socket != INVALID_SOCKET && - !HasOverlappedIoCompleted(&req->overlapped)) { - closesocket(req->accept_socket); - req->accept_socket = INVALID_SOCKET; - } - } - } - } - - if (tcp->flags & UV_HANDLE_READING) { - tcp->flags &= ~UV_HANDLE_READING; - DECREASE_ACTIVE_COUNT(loop, tcp); - } - - if (tcp->flags & UV_HANDLE_LISTENING) { - tcp->flags &= ~UV_HANDLE_LISTENING; - DECREASE_ACTIVE_COUNT(loop, tcp); - } - - if (close_socket) { - closesocket(tcp->socket); - tcp->socket = INVALID_SOCKET; - tcp->flags |= UV_HANDLE_TCP_SOCKET_CLOSED; - } - - tcp->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); - uv__handle_closing(tcp); - - if (tcp->reqs_pending == 0) { - uv_want_endgame(tcp->loop, (uv_handle_t*)tcp); - } -} - - -int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) { - WSAPROTOCOL_INFOW protocol_info; - int opt_len; - int err; - - /* Detect the address family of the socket. */ - opt_len = (int) sizeof protocol_info; - if (getsockopt(sock, - SOL_SOCKET, - SO_PROTOCOL_INFOW, - (char*) &protocol_info, - &opt_len) == SOCKET_ERROR) { - return uv_translate_sys_error(GetLastError()); - } - - /* Make the socket non-inheritable */ - if (!SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0)) { - return uv_translate_sys_error(GetLastError()); - } - - err = uv_tcp_set_socket(handle->loop, - handle, - sock, - protocol_info.iAddressFamily, - 1); - if (err) { - return uv_translate_sys_error(err); - } - - return 0; -} - - -/* This function is an egress point, i.e. it returns libuv errors rather than - * system errors. - */ -int uv__tcp_bind(uv_tcp_t* handle, - const struct sockaddr* addr, - unsigned int addrlen, - unsigned int flags) { - int err; - - err = uv_tcp_try_bind(handle, addr, addrlen, flags); - if (err) - return uv_translate_sys_error(err); - - return 0; -} - - -/* This function is an egress point, i.e. it returns libuv errors rather than - * system errors. - */ -int uv__tcp_connect(uv_connect_t* req, - uv_tcp_t* handle, - const struct sockaddr* addr, - unsigned int addrlen, - uv_connect_cb cb) { - int err; - - err = uv_tcp_try_connect(req, handle, addr, addrlen, cb); - if (err) - return uv_translate_sys_error(err); - - return 0; -} diff --git a/libuv/src/win/thread.c b/libuv/src/win/thread.c deleted file mode 100644 index 993d661..0000000 --- a/libuv/src/win/thread.c +++ /dev/null @@ -1,801 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include - -#include "uv.h" -#include "internal.h" - - -#define HAVE_SRWLOCK_API() (pTryAcquireSRWLockShared != NULL) -#define HAVE_CONDVAR_API() (pInitializeConditionVariable != NULL) - -#ifdef _MSC_VER /* msvc */ -# define inline __inline -# define NOINLINE __declspec (noinline) -#else /* gcc */ -# define inline inline -# define NOINLINE __attribute__ ((noinline)) -#endif - - -inline static int uv__rwlock_srwlock_init(uv_rwlock_t* rwlock); -inline static void uv__rwlock_srwlock_destroy(uv_rwlock_t* rwlock); -inline static void uv__rwlock_srwlock_rdlock(uv_rwlock_t* rwlock); -inline static int uv__rwlock_srwlock_tryrdlock(uv_rwlock_t* rwlock); -inline static void uv__rwlock_srwlock_rdunlock(uv_rwlock_t* rwlock); -inline static void uv__rwlock_srwlock_wrlock(uv_rwlock_t* rwlock); -inline static int uv__rwlock_srwlock_trywrlock(uv_rwlock_t* rwlock); -inline static void uv__rwlock_srwlock_wrunlock(uv_rwlock_t* rwlock); - -inline static int uv__rwlock_fallback_init(uv_rwlock_t* rwlock); -inline static void uv__rwlock_fallback_destroy(uv_rwlock_t* rwlock); -inline static void uv__rwlock_fallback_rdlock(uv_rwlock_t* rwlock); -inline static int uv__rwlock_fallback_tryrdlock(uv_rwlock_t* rwlock); -inline static void uv__rwlock_fallback_rdunlock(uv_rwlock_t* rwlock); -inline static void uv__rwlock_fallback_wrlock(uv_rwlock_t* rwlock); -inline static int uv__rwlock_fallback_trywrlock(uv_rwlock_t* rwlock); -inline static void uv__rwlock_fallback_wrunlock(uv_rwlock_t* rwlock); - - -inline static int uv_cond_fallback_init(uv_cond_t* cond); -inline static void uv_cond_fallback_destroy(uv_cond_t* cond); -inline static void uv_cond_fallback_signal(uv_cond_t* cond); -inline static void uv_cond_fallback_broadcast(uv_cond_t* cond); -inline static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex); -inline static int uv_cond_fallback_timedwait(uv_cond_t* cond, - uv_mutex_t* mutex, uint64_t timeout); - -inline static int uv_cond_condvar_init(uv_cond_t* cond); -inline static void uv_cond_condvar_destroy(uv_cond_t* cond); -inline static void uv_cond_condvar_signal(uv_cond_t* cond); -inline static void uv_cond_condvar_broadcast(uv_cond_t* cond); -inline static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex); -inline static int uv_cond_condvar_timedwait(uv_cond_t* cond, - uv_mutex_t* mutex, uint64_t timeout); - - -static NOINLINE void uv__once_inner(uv_once_t* guard, - void (*callback)(void)) { - DWORD result; - HANDLE existing_event, created_event; - - created_event = CreateEvent(NULL, 1, 0, NULL); - if (created_event == 0) { - /* Could fail in a low-memory situation? */ - uv_fatal_error(GetLastError(), "CreateEvent"); - } - - existing_event = InterlockedCompareExchangePointer(&guard->event, - created_event, - NULL); - - if (existing_event == NULL) { - /* We won the race */ - callback(); - - result = SetEvent(created_event); - assert(result); - guard->ran = 1; - - } else { - /* We lost the race. Destroy the event we created and wait for the */ - /* existing one to become signaled. */ - CloseHandle(created_event); - result = WaitForSingleObject(existing_event, INFINITE); - assert(result == WAIT_OBJECT_0); - } -} - - -void uv_once(uv_once_t* guard, void (*callback)(void)) { - /* Fast case - avoid WaitForSingleObject. */ - if (guard->ran) { - return; - } - - uv__once_inner(guard, callback); -} - - -/* Verify that uv_thread_t can be stored in a TLS slot. */ -STATIC_ASSERT(sizeof(uv_thread_t) <= sizeof(void*)); - -static uv_key_t uv__current_thread_key; -static uv_once_t uv__current_thread_init_guard = UV_ONCE_INIT; - - -static void uv__init_current_thread_key(void) { - if (uv_key_create(&uv__current_thread_key)) - abort(); -} - - -struct thread_ctx { - void (*entry)(void* arg); - void* arg; - uv_thread_t self; -}; - - -static UINT __stdcall uv__thread_start(void* arg) { - struct thread_ctx *ctx_p; - struct thread_ctx ctx; - - ctx_p = arg; - ctx = *ctx_p; - free(ctx_p); - - uv_once(&uv__current_thread_init_guard, uv__init_current_thread_key); - uv_key_set(&uv__current_thread_key, (void*) ctx.self); - - ctx.entry(ctx.arg); - - return 0; -} - - -int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { - struct thread_ctx* ctx; - int err; - HANDLE thread; - - ctx = malloc(sizeof(*ctx)); - if (ctx == NULL) - return UV_ENOMEM; - - ctx->entry = entry; - ctx->arg = arg; - - /* Create the thread in suspended state so we have a chance to pass - * its own creation handle to it */ - thread = (HANDLE) _beginthreadex(NULL, - 0, - uv__thread_start, - ctx, - CREATE_SUSPENDED, - NULL); - if (thread == NULL) { - err = errno; - free(ctx); - } else { - err = 0; - *tid = thread; - ctx->self = thread; - ResumeThread(thread); - } - - return err; -} - - -uv_thread_t uv_thread_self(void) { - return (uv_thread_t) uv_key_get(&uv__current_thread_key); -} - - -int uv_thread_join(uv_thread_t *tid) { - if (WaitForSingleObject(*tid, INFINITE)) - return uv_translate_sys_error(GetLastError()); - else { - CloseHandle(*tid); - *tid = 0; - return 0; - } -} - - -int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) { - return *t1 == *t2; -} - - -int uv_mutex_init(uv_mutex_t* mutex) { - InitializeCriticalSection(mutex); - return 0; -} - - -void uv_mutex_destroy(uv_mutex_t* mutex) { - DeleteCriticalSection(mutex); -} - - -void uv_mutex_lock(uv_mutex_t* mutex) { - EnterCriticalSection(mutex); -} - - -int uv_mutex_trylock(uv_mutex_t* mutex) { - if (TryEnterCriticalSection(mutex)) - return 0; - else - return UV_EAGAIN; -} - - -void uv_mutex_unlock(uv_mutex_t* mutex) { - LeaveCriticalSection(mutex); -} - - -int uv_rwlock_init(uv_rwlock_t* rwlock) { - uv__once_init(); - - if (HAVE_SRWLOCK_API()) - return uv__rwlock_srwlock_init(rwlock); - else - return uv__rwlock_fallback_init(rwlock); -} - - -void uv_rwlock_destroy(uv_rwlock_t* rwlock) { - if (HAVE_SRWLOCK_API()) - uv__rwlock_srwlock_destroy(rwlock); - else - uv__rwlock_fallback_destroy(rwlock); -} - - -void uv_rwlock_rdlock(uv_rwlock_t* rwlock) { - if (HAVE_SRWLOCK_API()) - uv__rwlock_srwlock_rdlock(rwlock); - else - uv__rwlock_fallback_rdlock(rwlock); -} - - -int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock) { - if (HAVE_SRWLOCK_API()) - return uv__rwlock_srwlock_tryrdlock(rwlock); - else - return uv__rwlock_fallback_tryrdlock(rwlock); -} - - -void uv_rwlock_rdunlock(uv_rwlock_t* rwlock) { - if (HAVE_SRWLOCK_API()) - uv__rwlock_srwlock_rdunlock(rwlock); - else - uv__rwlock_fallback_rdunlock(rwlock); -} - - -void uv_rwlock_wrlock(uv_rwlock_t* rwlock) { - if (HAVE_SRWLOCK_API()) - uv__rwlock_srwlock_wrlock(rwlock); - else - uv__rwlock_fallback_wrlock(rwlock); -} - - -int uv_rwlock_trywrlock(uv_rwlock_t* rwlock) { - if (HAVE_SRWLOCK_API()) - return uv__rwlock_srwlock_trywrlock(rwlock); - else - return uv__rwlock_fallback_trywrlock(rwlock); -} - - -void uv_rwlock_wrunlock(uv_rwlock_t* rwlock) { - if (HAVE_SRWLOCK_API()) - uv__rwlock_srwlock_wrunlock(rwlock); - else - uv__rwlock_fallback_wrunlock(rwlock); -} - - -int uv_sem_init(uv_sem_t* sem, unsigned int value) { - *sem = CreateSemaphore(NULL, value, INT_MAX, NULL); - if (*sem == NULL) - return uv_translate_sys_error(GetLastError()); - else - return 0; -} - - -void uv_sem_destroy(uv_sem_t* sem) { - if (!CloseHandle(*sem)) - abort(); -} - - -void uv_sem_post(uv_sem_t* sem) { - if (!ReleaseSemaphore(*sem, 1, NULL)) - abort(); -} - - -void uv_sem_wait(uv_sem_t* sem) { - if (WaitForSingleObject(*sem, INFINITE) != WAIT_OBJECT_0) - abort(); -} - - -int uv_sem_trywait(uv_sem_t* sem) { - DWORD r = WaitForSingleObject(*sem, 0); - - if (r == WAIT_OBJECT_0) - return 0; - - if (r == WAIT_TIMEOUT) - return UV_EAGAIN; - - abort(); - return -1; /* Satisfy the compiler. */ -} - - -inline static int uv__rwlock_srwlock_init(uv_rwlock_t* rwlock) { - pInitializeSRWLock(&rwlock->srwlock_); - return 0; -} - - -inline static void uv__rwlock_srwlock_destroy(uv_rwlock_t* rwlock) { - (void) rwlock; -} - - -inline static void uv__rwlock_srwlock_rdlock(uv_rwlock_t* rwlock) { - pAcquireSRWLockShared(&rwlock->srwlock_); -} - - -inline static int uv__rwlock_srwlock_tryrdlock(uv_rwlock_t* rwlock) { - if (pTryAcquireSRWLockShared(&rwlock->srwlock_)) - return 0; - else - return UV_EBUSY; /* TODO(bnoordhuis) EAGAIN when owned by this thread. */ -} - - -inline static void uv__rwlock_srwlock_rdunlock(uv_rwlock_t* rwlock) { - pReleaseSRWLockShared(&rwlock->srwlock_); -} - - -inline static void uv__rwlock_srwlock_wrlock(uv_rwlock_t* rwlock) { - pAcquireSRWLockExclusive(&rwlock->srwlock_); -} - - -inline static int uv__rwlock_srwlock_trywrlock(uv_rwlock_t* rwlock) { - if (pTryAcquireSRWLockExclusive(&rwlock->srwlock_)) - return 0; - else - return UV_EBUSY; /* TODO(bnoordhuis) EAGAIN when owned by this thread. */ -} - - -inline static void uv__rwlock_srwlock_wrunlock(uv_rwlock_t* rwlock) { - pReleaseSRWLockExclusive(&rwlock->srwlock_); -} - - -inline static int uv__rwlock_fallback_init(uv_rwlock_t* rwlock) { - int err; - - err = uv_mutex_init(&rwlock->fallback_.read_mutex_); - if (err) - return err; - - err = uv_mutex_init(&rwlock->fallback_.write_mutex_); - if (err) { - uv_mutex_destroy(&rwlock->fallback_.read_mutex_); - return err; - } - - rwlock->fallback_.num_readers_ = 0; - - return 0; -} - - -inline static void uv__rwlock_fallback_destroy(uv_rwlock_t* rwlock) { - uv_mutex_destroy(&rwlock->fallback_.read_mutex_); - uv_mutex_destroy(&rwlock->fallback_.write_mutex_); -} - - -inline static void uv__rwlock_fallback_rdlock(uv_rwlock_t* rwlock) { - uv_mutex_lock(&rwlock->fallback_.read_mutex_); - - if (++rwlock->fallback_.num_readers_ == 1) - uv_mutex_lock(&rwlock->fallback_.write_mutex_); - - uv_mutex_unlock(&rwlock->fallback_.read_mutex_); -} - - -inline static int uv__rwlock_fallback_tryrdlock(uv_rwlock_t* rwlock) { - int err; - - err = uv_mutex_trylock(&rwlock->fallback_.read_mutex_); - if (err) - goto out; - - err = 0; - if (rwlock->fallback_.num_readers_ == 0) - err = uv_mutex_trylock(&rwlock->fallback_.write_mutex_); - - if (err == 0) - rwlock->fallback_.num_readers_++; - - uv_mutex_unlock(&rwlock->fallback_.read_mutex_); - -out: - return err; -} - - -inline static void uv__rwlock_fallback_rdunlock(uv_rwlock_t* rwlock) { - uv_mutex_lock(&rwlock->fallback_.read_mutex_); - - if (--rwlock->fallback_.num_readers_ == 0) - uv_mutex_unlock(&rwlock->fallback_.write_mutex_); - - uv_mutex_unlock(&rwlock->fallback_.read_mutex_); -} - - -inline static void uv__rwlock_fallback_wrlock(uv_rwlock_t* rwlock) { - uv_mutex_lock(&rwlock->fallback_.write_mutex_); -} - - -inline static int uv__rwlock_fallback_trywrlock(uv_rwlock_t* rwlock) { - return uv_mutex_trylock(&rwlock->fallback_.write_mutex_); -} - - -inline static void uv__rwlock_fallback_wrunlock(uv_rwlock_t* rwlock) { - uv_mutex_unlock(&rwlock->fallback_.write_mutex_); -} - - - -/* This condition variable implementation is based on the SetEvent solution - * (section 3.2) at http://www.cs.wustl.edu/~schmidt/win32-cv-1.html - * We could not use the SignalObjectAndWait solution (section 3.4) because - * it want the 2nd argument (type uv_mutex_t) of uv_cond_wait() and - * uv_cond_timedwait() to be HANDLEs, but we use CRITICAL_SECTIONs. - */ - -inline static int uv_cond_fallback_init(uv_cond_t* cond) { - int err; - - /* Initialize the count to 0. */ - cond->fallback.waiters_count = 0; - - InitializeCriticalSection(&cond->fallback.waiters_count_lock); - - /* Create an auto-reset event. */ - cond->fallback.signal_event = CreateEvent(NULL, /* no security */ - FALSE, /* auto-reset event */ - FALSE, /* non-signaled initially */ - NULL); /* unnamed */ - if (!cond->fallback.signal_event) { - err = GetLastError(); - goto error2; - } - - /* Create a manual-reset event. */ - cond->fallback.broadcast_event = CreateEvent(NULL, /* no security */ - TRUE, /* manual-reset */ - FALSE, /* non-signaled */ - NULL); /* unnamed */ - if (!cond->fallback.broadcast_event) { - err = GetLastError(); - goto error; - } - - return 0; - -error: - CloseHandle(cond->fallback.signal_event); -error2: - DeleteCriticalSection(&cond->fallback.waiters_count_lock); - return uv_translate_sys_error(err); -} - - -inline static int uv_cond_condvar_init(uv_cond_t* cond) { - pInitializeConditionVariable(&cond->cond_var); - return 0; -} - - -int uv_cond_init(uv_cond_t* cond) { - uv__once_init(); - - if (HAVE_CONDVAR_API()) - return uv_cond_condvar_init(cond); - else - return uv_cond_fallback_init(cond); -} - - -inline static void uv_cond_fallback_destroy(uv_cond_t* cond) { - if (!CloseHandle(cond->fallback.broadcast_event)) - abort(); - if (!CloseHandle(cond->fallback.signal_event)) - abort(); - DeleteCriticalSection(&cond->fallback.waiters_count_lock); -} - - -inline static void uv_cond_condvar_destroy(uv_cond_t* cond) { - /* nothing to do */ -} - - -void uv_cond_destroy(uv_cond_t* cond) { - if (HAVE_CONDVAR_API()) - uv_cond_condvar_destroy(cond); - else - uv_cond_fallback_destroy(cond); -} - - -inline static void uv_cond_fallback_signal(uv_cond_t* cond) { - int have_waiters; - - /* Avoid race conditions. */ - EnterCriticalSection(&cond->fallback.waiters_count_lock); - have_waiters = cond->fallback.waiters_count > 0; - LeaveCriticalSection(&cond->fallback.waiters_count_lock); - - if (have_waiters) - SetEvent(cond->fallback.signal_event); -} - - -inline static void uv_cond_condvar_signal(uv_cond_t* cond) { - pWakeConditionVariable(&cond->cond_var); -} - - -void uv_cond_signal(uv_cond_t* cond) { - if (HAVE_CONDVAR_API()) - uv_cond_condvar_signal(cond); - else - uv_cond_fallback_signal(cond); -} - - -inline static void uv_cond_fallback_broadcast(uv_cond_t* cond) { - int have_waiters; - - /* Avoid race conditions. */ - EnterCriticalSection(&cond->fallback.waiters_count_lock); - have_waiters = cond->fallback.waiters_count > 0; - LeaveCriticalSection(&cond->fallback.waiters_count_lock); - - if (have_waiters) - SetEvent(cond->fallback.broadcast_event); -} - - -inline static void uv_cond_condvar_broadcast(uv_cond_t* cond) { - pWakeAllConditionVariable(&cond->cond_var); -} - - -void uv_cond_broadcast(uv_cond_t* cond) { - if (HAVE_CONDVAR_API()) - uv_cond_condvar_broadcast(cond); - else - uv_cond_fallback_broadcast(cond); -} - - -inline int uv_cond_wait_helper(uv_cond_t* cond, uv_mutex_t* mutex, - DWORD dwMilliseconds) { - DWORD result; - int last_waiter; - HANDLE handles[2] = { - cond->fallback.signal_event, - cond->fallback.broadcast_event - }; - - /* Avoid race conditions. */ - EnterCriticalSection(&cond->fallback.waiters_count_lock); - cond->fallback.waiters_count++; - LeaveCriticalSection(&cond->fallback.waiters_count_lock); - - /* It's ok to release the here since Win32 manual-reset events */ - /* maintain state when used with . This avoids the "lost wakeup" */ - /* bug. */ - uv_mutex_unlock(mutex); - - /* Wait for either event to become signaled due to being */ - /* called or being called. */ - result = WaitForMultipleObjects(2, handles, FALSE, dwMilliseconds); - - EnterCriticalSection(&cond->fallback.waiters_count_lock); - cond->fallback.waiters_count--; - last_waiter = result == WAIT_OBJECT_0 + 1 - && cond->fallback.waiters_count == 0; - LeaveCriticalSection(&cond->fallback.waiters_count_lock); - - /* Some thread called . */ - if (last_waiter) { - /* We're the last waiter to be notified or to stop waiting, so reset the */ - /* the manual-reset event. */ - ResetEvent(cond->fallback.broadcast_event); - } - - /* Reacquire the . */ - uv_mutex_lock(mutex); - - if (result == WAIT_OBJECT_0 || result == WAIT_OBJECT_0 + 1) - return 0; - - if (result == WAIT_TIMEOUT) - return UV_ETIMEDOUT; - - abort(); - return -1; /* Satisfy the compiler. */ -} - - -inline static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex) { - if (uv_cond_wait_helper(cond, mutex, INFINITE)) - abort(); -} - - -inline static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex) { - if (!pSleepConditionVariableCS(&cond->cond_var, mutex, INFINITE)) - abort(); -} - - -void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) { - if (HAVE_CONDVAR_API()) - uv_cond_condvar_wait(cond, mutex); - else - uv_cond_fallback_wait(cond, mutex); -} - - -inline static int uv_cond_fallback_timedwait(uv_cond_t* cond, - uv_mutex_t* mutex, uint64_t timeout) { - return uv_cond_wait_helper(cond, mutex, (DWORD)(timeout / 1e6)); -} - - -inline static int uv_cond_condvar_timedwait(uv_cond_t* cond, - uv_mutex_t* mutex, uint64_t timeout) { - if (pSleepConditionVariableCS(&cond->cond_var, mutex, (DWORD)(timeout / 1e6))) - return 0; - if (GetLastError() != ERROR_TIMEOUT) - abort(); - return UV_ETIMEDOUT; -} - - -int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, - uint64_t timeout) { - if (HAVE_CONDVAR_API()) - return uv_cond_condvar_timedwait(cond, mutex, timeout); - else - return uv_cond_fallback_timedwait(cond, mutex, timeout); -} - - -int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) { - int err; - - barrier->n = count; - barrier->count = 0; - - err = uv_mutex_init(&barrier->mutex); - if (err) - return err; - - err = uv_sem_init(&barrier->turnstile1, 0); - if (err) - goto error2; - - err = uv_sem_init(&barrier->turnstile2, 1); - if (err) - goto error; - - return 0; - -error: - uv_sem_destroy(&barrier->turnstile1); -error2: - uv_mutex_destroy(&barrier->mutex); - return err; - -} - - -void uv_barrier_destroy(uv_barrier_t* barrier) { - uv_sem_destroy(&barrier->turnstile2); - uv_sem_destroy(&barrier->turnstile1); - uv_mutex_destroy(&barrier->mutex); -} - - -int uv_barrier_wait(uv_barrier_t* barrier) { - int serial_thread; - - uv_mutex_lock(&barrier->mutex); - if (++barrier->count == barrier->n) { - uv_sem_wait(&barrier->turnstile2); - uv_sem_post(&barrier->turnstile1); - } - uv_mutex_unlock(&barrier->mutex); - - uv_sem_wait(&barrier->turnstile1); - uv_sem_post(&barrier->turnstile1); - - uv_mutex_lock(&barrier->mutex); - serial_thread = (--barrier->count == 0); - if (serial_thread) { - uv_sem_wait(&barrier->turnstile1); - uv_sem_post(&barrier->turnstile2); - } - uv_mutex_unlock(&barrier->mutex); - - uv_sem_wait(&barrier->turnstile2); - uv_sem_post(&barrier->turnstile2); - return serial_thread; -} - - -int uv_key_create(uv_key_t* key) { - key->tls_index = TlsAlloc(); - if (key->tls_index == TLS_OUT_OF_INDEXES) - return UV_ENOMEM; - return 0; -} - - -void uv_key_delete(uv_key_t* key) { - if (TlsFree(key->tls_index) == FALSE) - abort(); - key->tls_index = TLS_OUT_OF_INDEXES; -} - - -void* uv_key_get(uv_key_t* key) { - void* value; - - value = TlsGetValue(key->tls_index); - if (value == NULL) - if (GetLastError() != ERROR_SUCCESS) - abort(); - - return value; -} - - -void uv_key_set(uv_key_t* key, void* value) { - if (TlsSetValue(key->tls_index, value) == FALSE) - abort(); -} diff --git a/libuv/src/win/timer.c b/libuv/src/win/timer.c deleted file mode 100644 index 0da541a..0000000 --- a/libuv/src/win/timer.c +++ /dev/null @@ -1,200 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include - -#include "uv.h" -#include "internal.h" -#include "tree.h" -#include "handle-inl.h" - - -/* The number of milliseconds in one second. */ -#define UV__MILLISEC 1000 - - -void uv_update_time(uv_loop_t* loop) { - uint64_t new_time = uv__hrtime(UV__MILLISEC); - if (new_time > loop->time) { - loop->time = new_time; - } -} - -void uv__time_forward(uv_loop_t* loop, uint64_t msecs) { - loop->time += msecs; -} - - -static int uv_timer_compare(uv_timer_t* a, uv_timer_t* b) { - if (a->due < b->due) - return -1; - if (a->due > b->due) - return 1; - /* - * compare start_id when both has the same due. start_id is - * allocated with loop->timer_counter in uv_timer_start(). - */ - if (a->start_id < b->start_id) - return -1; - if (a->start_id > b->start_id) - return 1; - return 0; -} - - -RB_GENERATE_STATIC(uv_timer_tree_s, uv_timer_s, tree_entry, uv_timer_compare); - - -int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) { - uv__handle_init(loop, (uv_handle_t*) handle, UV_TIMER); - handle->timer_cb = NULL; - handle->repeat = 0; - - return 0; -} - - -void uv_timer_endgame(uv_loop_t* loop, uv_timer_t* handle) { - if (handle->flags & UV__HANDLE_CLOSING) { - assert(!(handle->flags & UV_HANDLE_CLOSED)); - uv__handle_close(handle); - } -} - - -static uint64_t get_clamped_due_time(uint64_t loop_time, uint64_t timeout) { - uint64_t clamped_timeout; - - clamped_timeout = loop_time + timeout; - if (clamped_timeout < timeout) - clamped_timeout = (uint64_t) -1; - - return clamped_timeout; -} - - -int uv_timer_start(uv_timer_t* handle, uv_timer_cb timer_cb, uint64_t timeout, - uint64_t repeat) { - uv_loop_t* loop = handle->loop; - uv_timer_t* old; - - if (timer_cb == NULL) - return UV_EINVAL; - - if (uv__is_active(handle)) - uv_timer_stop(handle); - - handle->timer_cb = timer_cb; - handle->due = get_clamped_due_time(loop->time, timeout); - handle->repeat = repeat; - uv__handle_start(handle); - - /* start_id is the second index to be compared in uv__timer_cmp() */ - handle->start_id = handle->loop->timer_counter++; - - old = RB_INSERT(uv_timer_tree_s, &loop->timers, handle); - assert(old == NULL); - - return 0; -} - - -int uv_timer_stop(uv_timer_t* handle) { - uv_loop_t* loop = handle->loop; - - if (!uv__is_active(handle)) - return 0; - - RB_REMOVE(uv_timer_tree_s, &loop->timers, handle); - uv__handle_stop(handle); - - return 0; -} - - -int uv_timer_again(uv_timer_t* handle) { - /* If timer_cb is NULL that means that the timer was never started. */ - if (!handle->timer_cb) { - return UV_EINVAL; - } - - if (handle->repeat) { - uv_timer_stop(handle); - uv_timer_start(handle, handle->timer_cb, handle->repeat, handle->repeat); - } - - return 0; -} - - -void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat) { - assert(handle->type == UV_TIMER); - handle->repeat = repeat; -} - - -uint64_t uv_timer_get_repeat(const uv_timer_t* handle) { - assert(handle->type == UV_TIMER); - return handle->repeat; -} - - -DWORD uv__next_timeout(const uv_loop_t* loop) { - uv_timer_t* timer; - int64_t delta; - - /* Check if there are any running timers - * Need to cast away const first, since RB_MIN doesn't know what we are - * going to do with this return value, it can't be marked const - */ - timer = RB_MIN(uv_timer_tree_s, &((uv_loop_t*)loop)->timers); - if (timer) { - delta = timer->due - loop->time; - if (delta >= UINT_MAX - 1) { - /* A timeout value of UINT_MAX means infinite, so that's no good. */ - return UINT_MAX - 1; - } else if (delta < 0) { - /* Negative timeout values are not allowed */ - return 0; - } else { - return (DWORD)delta; - } - } else { - /* No timers */ - return INFINITE; - } -} - - -void uv_process_timers(uv_loop_t* loop) { - uv_timer_t* timer; - - /* Call timer callbacks */ - for (timer = RB_MIN(uv_timer_tree_s, &loop->timers); - timer != NULL && timer->due <= loop->time; - timer = RB_MIN(uv_timer_tree_s, &loop->timers)) { - - uv_timer_stop(timer); - uv_timer_again(timer); - timer->timer_cb((uv_timer_t*) timer); - } -} diff --git a/libuv/src/win/tty.c b/libuv/src/win/tty.c deleted file mode 100644 index 6034210..0000000 --- a/libuv/src/win/tty.c +++ /dev/null @@ -1,1990 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include - -#if defined(_MSC_VER) && _MSC_VER < 1600 -# include "stdint-msvc2008.h" -#else -# include -#endif - -#ifndef COMMON_LVB_REVERSE_VIDEO -# define COMMON_LVB_REVERSE_VIDEO 0x4000 -#endif - -#include "uv.h" -#include "internal.h" -#include "handle-inl.h" -#include "stream-inl.h" -#include "req-inl.h" - - -#define UNICODE_REPLACEMENT_CHARACTER (0xfffd) - -#define ANSI_NORMAL 0x00 -#define ANSI_ESCAPE_SEEN 0x02 -#define ANSI_CSI 0x04 -#define ANSI_ST_CONTROL 0x08 -#define ANSI_IGNORE 0x10 -#define ANSI_IN_ARG 0x20 -#define ANSI_IN_STRING 0x40 -#define ANSI_BACKSLASH_SEEN 0x80 - -#define MAX_INPUT_BUFFER_LENGTH 8192 - - -static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info); - - -/* Null uv_buf_t */ -static const uv_buf_t uv_null_buf_ = { 0, NULL }; - - -/* - * The console virtual window. - * - * Normally cursor movement in windows is relative to the console screen buffer, - * e.g. the application is allowed to overwrite the 'history'. This is very - * inconvenient, it makes absolute cursor movement pretty useless. There is - * also the concept of 'client rect' which is defined by the actual size of - * the console window and the scroll position of the screen buffer, but it's - * very volatile because it changes when the user scrolls. - * - * To make cursor movement behave sensibly we define a virtual window to which - * cursor movement is confined. The virtual window is always as wide as the - * console screen buffer, but it's height is defined by the size of the - * console window. The top of the virtual window aligns with the position - * of the caret when the first stdout/err handle is created, unless that would - * mean that it would extend beyond the bottom of the screen buffer - in that - * that case it's located as far down as possible. - * - * When the user writes a long text or many newlines, such that the output - * reaches beyond the bottom of the virtual window, the virtual window is - * shifted downwards, but not resized. - * - * Since all tty i/o happens on the same console, this window is shared - * between all stdout/stderr handles. - */ - -static int uv_tty_virtual_offset = -1; -static int uv_tty_virtual_height = -1; -static int uv_tty_virtual_width = -1; - -static CRITICAL_SECTION uv_tty_output_lock; - -static HANDLE uv_tty_output_handle = INVALID_HANDLE_VALUE; - - -void uv_console_init() { - InitializeCriticalSection(&uv_tty_output_lock); -} - - -int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) { - HANDLE handle; - CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info; - - handle = (HANDLE) _get_osfhandle(fd); - if (handle == INVALID_HANDLE_VALUE) { - return UV_EBADF; - } - - if (!readable) { - /* Obtain the screen buffer info with the output handle. */ - if (!GetConsoleScreenBufferInfo(handle, &screen_buffer_info)) { - return uv_translate_sys_error(GetLastError()); - } - - /* Obtain the the tty_output_lock because the virtual window state is */ - /* shared between all uv_tty_t handles. */ - EnterCriticalSection(&uv_tty_output_lock); - - /* Store the global tty output handle. This handle is used by TTY read */ - /* streams to update the virtual window when a CONSOLE_BUFFER_SIZE_EVENT */ - /* is received. */ - uv_tty_output_handle = handle; - - uv_tty_update_virtual_window(&screen_buffer_info); - - LeaveCriticalSection(&uv_tty_output_lock); - } - - - uv_stream_init(loop, (uv_stream_t*) tty, UV_TTY); - uv_connection_init((uv_stream_t*) tty); - - tty->handle = handle; - tty->reqs_pending = 0; - tty->flags |= UV_HANDLE_BOUND; - - if (readable) { - /* Initialize TTY input specific fields. */ - tty->flags |= UV_HANDLE_TTY_READABLE | UV_HANDLE_READABLE; - tty->read_line_handle = NULL; - tty->read_line_buffer = uv_null_buf_; - tty->read_raw_wait = NULL; - - /* Init keycode-to-vt100 mapper state. */ - tty->last_key_len = 0; - tty->last_key_offset = 0; - tty->last_utf16_high_surrogate = 0; - memset(&tty->last_input_record, 0, sizeof tty->last_input_record); - } else { - /* TTY output specific fields. */ - tty->flags |= UV_HANDLE_WRITABLE; - - /* Init utf8-to-utf16 conversion state. */ - tty->utf8_bytes_left = 0; - tty->utf8_codepoint = 0; - - /* Initialize eol conversion state */ - tty->previous_eol = 0; - - /* Init ANSI parser state. */ - tty->ansi_parser_state = ANSI_NORMAL; - } - - return 0; -} - - -int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) { - DWORD flags; - unsigned char was_reading; - uv_alloc_cb alloc_cb; - uv_read_cb read_cb; - int err; - - if (!(tty->flags & UV_HANDLE_TTY_READABLE)) { - return UV_EINVAL; - } - - if (!!mode == !!(tty->flags & UV_HANDLE_TTY_RAW)) { - return 0; - } - - switch (mode) { - case UV_TTY_MODE_NORMAL: - flags = ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT; - break; - case UV_TTY_MODE_RAW: - flags = ENABLE_WINDOW_INPUT; - break; - case UV_TTY_MODE_IO: - return UV_ENOTSUP; - } - - if (!SetConsoleMode(tty->handle, flags)) { - return uv_translate_sys_error(GetLastError()); - } - - /* If currently reading, stop, and restart reading. */ - if (tty->flags & UV_HANDLE_READING) { - was_reading = 1; - alloc_cb = tty->alloc_cb; - read_cb = tty->read_cb; - - if (was_reading) { - err = uv_tty_read_stop(tty); - if (err) { - return uv_translate_sys_error(err); - } - } - } else { - was_reading = 0; - } - - /* Update flag. */ - tty->flags &= ~UV_HANDLE_TTY_RAW; - tty->flags |= mode ? UV_HANDLE_TTY_RAW : 0; - - /* If we just stopped reading, restart. */ - if (was_reading) { - err = uv_tty_read_start(tty, alloc_cb, read_cb); - if (err) { - return uv_translate_sys_error(err); - } - } - - return 0; -} - - -int uv_is_tty(uv_file file) { - DWORD result; - return GetConsoleMode((HANDLE) _get_osfhandle(file), &result) != 0; -} - - -int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) { - CONSOLE_SCREEN_BUFFER_INFO info; - - if (!GetConsoleScreenBufferInfo(tty->handle, &info)) { - return uv_translate_sys_error(GetLastError()); - } - - EnterCriticalSection(&uv_tty_output_lock); - uv_tty_update_virtual_window(&info); - LeaveCriticalSection(&uv_tty_output_lock); - - *width = uv_tty_virtual_width; - *height = uv_tty_virtual_height; - - return 0; -} - - -static void CALLBACK uv_tty_post_raw_read(void* data, BOOLEAN didTimeout) { - uv_loop_t* loop; - uv_tty_t* handle; - uv_req_t* req; - - assert(data); - assert(!didTimeout); - - req = (uv_req_t*) data; - handle = (uv_tty_t*) req->data; - loop = handle->loop; - - UnregisterWait(handle->read_raw_wait); - handle->read_raw_wait = NULL; - - SET_REQ_SUCCESS(req); - POST_COMPLETION_FOR_REQ(loop, req); -} - - -static void uv_tty_queue_read_raw(uv_loop_t* loop, uv_tty_t* handle) { - uv_read_t* req; - BOOL r; - - assert(handle->flags & UV_HANDLE_READING); - assert(!(handle->flags & UV_HANDLE_READ_PENDING)); - - assert(handle->handle && handle->handle != INVALID_HANDLE_VALUE); - - handle->read_line_buffer = uv_null_buf_; - - req = &handle->read_req; - memset(&req->overlapped, 0, sizeof(req->overlapped)); - - r = RegisterWaitForSingleObject(&handle->read_raw_wait, - handle->handle, - uv_tty_post_raw_read, - (void*) req, - INFINITE, - WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE); - if (!r) { - handle->read_raw_wait = NULL; - SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); - } - - handle->flags |= UV_HANDLE_READ_PENDING; - handle->reqs_pending++; -} - - -static DWORD CALLBACK uv_tty_line_read_thread(void* data) { - uv_loop_t* loop; - uv_tty_t* handle; - uv_req_t* req; - DWORD bytes, read_bytes; - WCHAR utf16[MAX_INPUT_BUFFER_LENGTH / 3]; - DWORD chars, read_chars; - - assert(data); - - req = (uv_req_t*) data; - handle = (uv_tty_t*) req->data; - loop = handle->loop; - - assert(handle->read_line_buffer.base != NULL); - assert(handle->read_line_buffer.len > 0); - - /* ReadConsole can't handle big buffers. */ - if (handle->read_line_buffer.len < MAX_INPUT_BUFFER_LENGTH) { - bytes = handle->read_line_buffer.len; - } else { - bytes = MAX_INPUT_BUFFER_LENGTH; - } - - /* At last, unicode! */ - /* One utf-16 codeunit never takes more than 3 utf-8 codeunits to encode */ - chars = bytes / 3; - - if (ReadConsoleW(handle->read_line_handle, - (void*) utf16, - chars, - &read_chars, - NULL)) { - read_bytes = WideCharToMultiByte(CP_UTF8, - 0, - utf16, - read_chars, - handle->read_line_buffer.base, - bytes, - NULL, - NULL); - SET_REQ_SUCCESS(req); - req->overlapped.InternalHigh = read_bytes; - } else { - SET_REQ_ERROR(req, GetLastError()); - } - - POST_COMPLETION_FOR_REQ(loop, req); - return 0; -} - - -static void uv_tty_queue_read_line(uv_loop_t* loop, uv_tty_t* handle) { - uv_read_t* req; - BOOL r; - - assert(handle->flags & UV_HANDLE_READING); - assert(!(handle->flags & UV_HANDLE_READ_PENDING)); - assert(handle->handle && handle->handle != INVALID_HANDLE_VALUE); - - req = &handle->read_req; - memset(&req->overlapped, 0, sizeof(req->overlapped)); - - handle->alloc_cb((uv_handle_t*) handle, 8192, &handle->read_line_buffer); - if (handle->read_line_buffer.len == 0) { - handle->read_cb((uv_stream_t*) handle, - UV_ENOBUFS, - &handle->read_line_buffer); - return; - } - assert(handle->read_line_buffer.base != NULL); - - /* Duplicate the console handle, so if we want to cancel the read, we can */ - /* just close this handle duplicate. */ - if (handle->read_line_handle == NULL) { - HANDLE this_process = GetCurrentProcess(); - r = DuplicateHandle(this_process, - handle->handle, - this_process, - &handle->read_line_handle, - 0, - 0, - DUPLICATE_SAME_ACCESS); - if (!r) { - handle->read_line_handle = NULL; - SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); - goto out; - } - } - - r = QueueUserWorkItem(uv_tty_line_read_thread, - (void*) req, - WT_EXECUTELONGFUNCTION); - if (!r) { - SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); - } - - out: - handle->flags |= UV_HANDLE_READ_PENDING; - handle->reqs_pending++; -} - - -static void uv_tty_queue_read(uv_loop_t* loop, uv_tty_t* handle) { - if (handle->flags & UV_HANDLE_TTY_RAW) { - uv_tty_queue_read_raw(loop, handle); - } else { - uv_tty_queue_read_line(loop, handle); - } -} - - -static const char* get_vt100_fn_key(DWORD code, char shift, char ctrl, - size_t* len) { -#define VK_CASE(vk, normal_str, shift_str, ctrl_str, shift_ctrl_str) \ - case (vk): \ - if (shift && ctrl) { \ - *len = sizeof shift_ctrl_str; \ - return "\033" shift_ctrl_str; \ - } else if (shift) { \ - *len = sizeof shift_str ; \ - return "\033" shift_str; \ - } else if (ctrl) { \ - *len = sizeof ctrl_str; \ - return "\033" ctrl_str; \ - } else { \ - *len = sizeof normal_str; \ - return "\033" normal_str; \ - } - - switch (code) { - /* These mappings are the same as Cygwin's. Unmodified and alt-modified */ - /* keypad keys comply with linux console, modifiers comply with xterm */ - /* modifier usage. F1..f12 and shift-f1..f10 comply with linux console, */ - /* f6..f12 with and without modifiers comply with rxvt. */ - VK_CASE(VK_INSERT, "[2~", "[2;2~", "[2;5~", "[2;6~") - VK_CASE(VK_END, "[4~", "[4;2~", "[4;5~", "[4;6~") - VK_CASE(VK_DOWN, "[B", "[1;2B", "[1;5B", "[1;6B") - VK_CASE(VK_NEXT, "[6~", "[6;2~", "[6;5~", "[6;6~") - VK_CASE(VK_LEFT, "[D", "[1;2D", "[1;5D", "[1;6D") - VK_CASE(VK_CLEAR, "[G", "[1;2G", "[1;5G", "[1;6G") - VK_CASE(VK_RIGHT, "[C", "[1;2C", "[1;5C", "[1;6C") - VK_CASE(VK_UP, "[A", "[1;2A", "[1;5A", "[1;6A") - VK_CASE(VK_HOME, "[1~", "[1;2~", "[1;5~", "[1;6~") - VK_CASE(VK_PRIOR, "[5~", "[5;2~", "[5;5~", "[5;6~") - VK_CASE(VK_DELETE, "[3~", "[3;2~", "[3;5~", "[3;6~") - VK_CASE(VK_NUMPAD0, "[2~", "[2;2~", "[2;5~", "[2;6~") - VK_CASE(VK_NUMPAD1, "[4~", "[4;2~", "[4;5~", "[4;6~") - VK_CASE(VK_NUMPAD2, "[B", "[1;2B", "[1;5B", "[1;6B") - VK_CASE(VK_NUMPAD3, "[6~", "[6;2~", "[6;5~", "[6;6~") - VK_CASE(VK_NUMPAD4, "[D", "[1;2D", "[1;5D", "[1;6D") - VK_CASE(VK_NUMPAD5, "[G", "[1;2G", "[1;5G", "[1;6G") - VK_CASE(VK_NUMPAD6, "[C", "[1;2C", "[1;5C", "[1;6C") - VK_CASE(VK_NUMPAD7, "[A", "[1;2A", "[1;5A", "[1;6A") - VK_CASE(VK_NUMPAD8, "[1~", "[1;2~", "[1;5~", "[1;6~") - VK_CASE(VK_NUMPAD9, "[5~", "[5;2~", "[5;5~", "[5;6~") - VK_CASE(VK_DECIMAL, "[3~", "[3;2~", "[3;5~", "[3;6~") - VK_CASE(VK_F1, "[[A", "[23~", "[11^", "[23^" ) - VK_CASE(VK_F2, "[[B", "[24~", "[12^", "[24^" ) - VK_CASE(VK_F3, "[[C", "[25~", "[13^", "[25^" ) - VK_CASE(VK_F4, "[[D", "[26~", "[14^", "[26^" ) - VK_CASE(VK_F5, "[[E", "[28~", "[15^", "[28^" ) - VK_CASE(VK_F6, "[17~", "[29~", "[17^", "[29^" ) - VK_CASE(VK_F7, "[18~", "[31~", "[18^", "[31^" ) - VK_CASE(VK_F8, "[19~", "[32~", "[19^", "[32^" ) - VK_CASE(VK_F9, "[20~", "[33~", "[20^", "[33^" ) - VK_CASE(VK_F10, "[21~", "[34~", "[21^", "[34^" ) - VK_CASE(VK_F11, "[23~", "[23$", "[23^", "[23@" ) - VK_CASE(VK_F12, "[24~", "[24$", "[24^", "[24@" ) - - default: - *len = 0; - return NULL; - } -#undef VK_CASE -} - - -void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, - uv_req_t* req) { - /* Shortcut for handle->last_input_record.Event.KeyEvent. */ -#define KEV handle->last_input_record.Event.KeyEvent - - DWORD records_left, records_read; - uv_buf_t buf; - off_t buf_used; - - assert(handle->type == UV_TTY); - assert(handle->flags & UV_HANDLE_TTY_READABLE); - handle->flags &= ~UV_HANDLE_READ_PENDING; - - if (!(handle->flags & UV_HANDLE_READING) || - !(handle->flags & UV_HANDLE_TTY_RAW)) { - goto out; - } - - if (!REQ_SUCCESS(req)) { - /* An error occurred while waiting for the event. */ - if ((handle->flags & UV_HANDLE_READING)) { - handle->flags &= ~UV_HANDLE_READING; - handle->read_cb((uv_stream_t*)handle, - uv_translate_sys_error(GET_REQ_ERROR(req)), - &uv_null_buf_); - } - goto out; - } - - /* Fetch the number of events */ - if (!GetNumberOfConsoleInputEvents(handle->handle, &records_left)) { - handle->flags &= ~UV_HANDLE_READING; - DECREASE_ACTIVE_COUNT(loop, handle); - handle->read_cb((uv_stream_t*)handle, - uv_translate_sys_error(GetLastError()), - &uv_null_buf_); - goto out; - } - - /* Windows sends a lot of events that we're not interested in, so buf */ - /* will be allocated on demand, when there's actually something to emit. */ - buf = uv_null_buf_; - buf_used = 0; - - while ((records_left > 0 || handle->last_key_len > 0) && - (handle->flags & UV_HANDLE_READING)) { - if (handle->last_key_len == 0) { - /* Read the next input record */ - if (!ReadConsoleInputW(handle->handle, - &handle->last_input_record, - 1, - &records_read)) { - handle->flags &= ~UV_HANDLE_READING; - DECREASE_ACTIVE_COUNT(loop, handle); - handle->read_cb((uv_stream_t*) handle, - uv_translate_sys_error(GetLastError()), - &buf); - goto out; - } - records_left--; - - /* If the window was resized, recompute the virtual window size. This */ - /* will trigger a SIGWINCH signal if the window size changed in an */ - /* way that matters to libuv. */ - if (handle->last_input_record.EventType == WINDOW_BUFFER_SIZE_EVENT) { - CONSOLE_SCREEN_BUFFER_INFO info; - - EnterCriticalSection(&uv_tty_output_lock); - - if (uv_tty_output_handle != INVALID_HANDLE_VALUE && - GetConsoleScreenBufferInfo(uv_tty_output_handle, &info)) { - uv_tty_update_virtual_window(&info); - } - - LeaveCriticalSection(&uv_tty_output_lock); - - continue; - } - - /* Ignore other events that are not key or resize events. */ - if (handle->last_input_record.EventType != KEY_EVENT) { - continue; - } - - /* Ignore keyup events, unless the left alt key was held and a valid */ - /* unicode character was emitted. */ - if (!KEV.bKeyDown && !(((KEV.dwControlKeyState & LEFT_ALT_PRESSED) || - KEV.wVirtualKeyCode==VK_MENU) && KEV.uChar.UnicodeChar != 0)) { - continue; - } - - /* Ignore keypresses to numpad number keys if the left alt is held */ - /* because the user is composing a character, or windows simulating */ - /* this. */ - if ((KEV.dwControlKeyState & LEFT_ALT_PRESSED) && - !(KEV.dwControlKeyState & ENHANCED_KEY) && - (KEV.wVirtualKeyCode == VK_INSERT || - KEV.wVirtualKeyCode == VK_END || - KEV.wVirtualKeyCode == VK_DOWN || - KEV.wVirtualKeyCode == VK_NEXT || - KEV.wVirtualKeyCode == VK_LEFT || - KEV.wVirtualKeyCode == VK_CLEAR || - KEV.wVirtualKeyCode == VK_RIGHT || - KEV.wVirtualKeyCode == VK_HOME || - KEV.wVirtualKeyCode == VK_UP || - KEV.wVirtualKeyCode == VK_PRIOR || - KEV.wVirtualKeyCode == VK_NUMPAD0 || - KEV.wVirtualKeyCode == VK_NUMPAD1 || - KEV.wVirtualKeyCode == VK_NUMPAD2 || - KEV.wVirtualKeyCode == VK_NUMPAD3 || - KEV.wVirtualKeyCode == VK_NUMPAD4 || - KEV.wVirtualKeyCode == VK_NUMPAD5 || - KEV.wVirtualKeyCode == VK_NUMPAD6 || - KEV.wVirtualKeyCode == VK_NUMPAD7 || - KEV.wVirtualKeyCode == VK_NUMPAD8 || - KEV.wVirtualKeyCode == VK_NUMPAD9)) { - continue; - } - - if (KEV.uChar.UnicodeChar != 0) { - int prefix_len, char_len; - - /* Character key pressed */ - if (KEV.uChar.UnicodeChar >= 0xD800 && - KEV.uChar.UnicodeChar < 0xDC00) { - /* UTF-16 high surrogate */ - handle->last_utf16_high_surrogate = KEV.uChar.UnicodeChar; - continue; - } - - /* Prefix with \u033 if alt was held, but alt was not used as part */ - /* a compose sequence. */ - if ((KEV.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) - && !(KEV.dwControlKeyState & (LEFT_CTRL_PRESSED | - RIGHT_CTRL_PRESSED)) && KEV.bKeyDown) { - handle->last_key[0] = '\033'; - prefix_len = 1; - } else { - prefix_len = 0; - } - - if (KEV.uChar.UnicodeChar >= 0xDC00 && - KEV.uChar.UnicodeChar < 0xE000) { - /* UTF-16 surrogate pair */ - WCHAR utf16_buffer[2] = { handle->last_utf16_high_surrogate, - KEV.uChar.UnicodeChar}; - char_len = WideCharToMultiByte(CP_UTF8, - 0, - utf16_buffer, - 2, - &handle->last_key[prefix_len], - sizeof handle->last_key, - NULL, - NULL); - } else { - /* Single UTF-16 character */ - char_len = WideCharToMultiByte(CP_UTF8, - 0, - &KEV.uChar.UnicodeChar, - 1, - &handle->last_key[prefix_len], - sizeof handle->last_key, - NULL, - NULL); - } - - /* Whatever happened, the last character wasn't a high surrogate. */ - handle->last_utf16_high_surrogate = 0; - - /* If the utf16 character(s) couldn't be converted something must */ - /* be wrong. */ - if (!char_len) { - handle->flags &= ~UV_HANDLE_READING; - DECREASE_ACTIVE_COUNT(loop, handle); - handle->read_cb((uv_stream_t*) handle, - uv_translate_sys_error(GetLastError()), - &buf); - goto out; - } - - handle->last_key_len = (unsigned char) (prefix_len + char_len); - handle->last_key_offset = 0; - continue; - - } else { - /* Function key pressed */ - const char* vt100; - size_t prefix_len, vt100_len; - - vt100 = get_vt100_fn_key(KEV.wVirtualKeyCode, - !!(KEV.dwControlKeyState & SHIFT_PRESSED), - !!(KEV.dwControlKeyState & ( - LEFT_CTRL_PRESSED | - RIGHT_CTRL_PRESSED)), - &vt100_len); - - /* If we were unable to map to a vt100 sequence, just ignore. */ - if (!vt100) { - continue; - } - - /* Prefix with \x033 when the alt key was held. */ - if (KEV.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) { - handle->last_key[0] = '\033'; - prefix_len = 1; - } else { - prefix_len = 0; - } - - /* Copy the vt100 sequence to the handle buffer. */ - assert(prefix_len + vt100_len < sizeof handle->last_key); - memcpy(&handle->last_key[prefix_len], vt100, vt100_len); - - handle->last_key_len = (unsigned char) (prefix_len + vt100_len); - handle->last_key_offset = 0; - continue; - } - } else { - /* Copy any bytes left from the last keypress to the user buffer. */ - if (handle->last_key_offset < handle->last_key_len) { - /* Allocate a buffer if needed */ - if (buf_used == 0) { - handle->alloc_cb((uv_handle_t*) handle, 1024, &buf); - if (buf.len == 0) { - handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &buf); - goto out; - } - assert(buf.base != NULL); - } - - buf.base[buf_used++] = handle->last_key[handle->last_key_offset++]; - - /* If the buffer is full, emit it */ - if ((size_t) buf_used == buf.len) { - handle->read_cb((uv_stream_t*) handle, buf_used, &buf); - buf = uv_null_buf_; - buf_used = 0; - } - - continue; - } - - /* Apply dwRepeat from the last input record. */ - if (--KEV.wRepeatCount > 0) { - handle->last_key_offset = 0; - continue; - } - - handle->last_key_len = 0; - continue; - } - } - - /* Send the buffer back to the user */ - if (buf_used > 0) { - handle->read_cb((uv_stream_t*) handle, buf_used, &buf); - } - - out: - /* Wait for more input events. */ - if ((handle->flags & UV_HANDLE_READING) && - !(handle->flags & UV_HANDLE_READ_PENDING)) { - uv_tty_queue_read(loop, handle); - } - - DECREASE_PENDING_REQ_COUNT(handle); - -#undef KEV -} - - - -void uv_process_tty_read_line_req(uv_loop_t* loop, uv_tty_t* handle, - uv_req_t* req) { - uv_buf_t buf; - - assert(handle->type == UV_TTY); - assert(handle->flags & UV_HANDLE_TTY_READABLE); - - buf = handle->read_line_buffer; - - handle->flags &= ~UV_HANDLE_READ_PENDING; - handle->read_line_buffer = uv_null_buf_; - - if (!REQ_SUCCESS(req)) { - /* Read was not successful */ - if ((handle->flags & UV_HANDLE_READING) && - handle->read_line_handle != NULL) { - /* Real error */ - handle->flags &= ~UV_HANDLE_READING; - DECREASE_ACTIVE_COUNT(loop, handle); - handle->read_cb((uv_stream_t*) handle, - uv_translate_sys_error(GET_REQ_ERROR(req)), - &buf); - } else { - /* The read was cancelled, or whatever we don't care */ - handle->read_cb((uv_stream_t*) handle, 0, &buf); - } - - } else { - /* Read successful */ - /* TODO: read unicode, convert to utf-8 */ - DWORD bytes = req->overlapped.InternalHigh; - handle->read_cb((uv_stream_t*) handle, bytes, &buf); - } - - /* Wait for more input events. */ - if ((handle->flags & UV_HANDLE_READING) && - !(handle->flags & UV_HANDLE_READ_PENDING)) { - uv_tty_queue_read(loop, handle); - } - - DECREASE_PENDING_REQ_COUNT(handle); -} - - -void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle, - uv_req_t* req) { - assert(handle->type == UV_TTY); - assert(handle->flags & UV_HANDLE_TTY_READABLE); - - /* If the read_line_buffer member is zero, it must have been an raw read. */ - /* Otherwise it was a line-buffered read. */ - /* FIXME: This is quite obscure. Use a flag or something. */ - if (handle->read_line_buffer.len == 0) { - uv_process_tty_read_raw_req(loop, handle, req); - } else { - uv_process_tty_read_line_req(loop, handle, req); - } -} - - -int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb, - uv_read_cb read_cb) { - uv_loop_t* loop = handle->loop; - - if (!(handle->flags & UV_HANDLE_TTY_READABLE)) { - return ERROR_INVALID_PARAMETER; - } - - handle->flags |= UV_HANDLE_READING; - INCREASE_ACTIVE_COUNT(loop, handle); - handle->read_cb = read_cb; - handle->alloc_cb = alloc_cb; - - /* If reading was stopped and then started again, there could still be a */ - /* read request pending. */ - if (handle->flags & UV_HANDLE_READ_PENDING) { - return 0; - } - - /* Maybe the user stopped reading half-way while processing key events. */ - /* Short-circuit if this could be the case. */ - if (handle->last_key_len > 0) { - SET_REQ_SUCCESS(&handle->read_req); - uv_insert_pending_req(handle->loop, (uv_req_t*) &handle->read_req); - return 0; - } - - uv_tty_queue_read(loop, handle); - - return 0; -} - - -int uv_tty_read_stop(uv_tty_t* handle) { - handle->flags &= ~UV_HANDLE_READING; - DECREASE_ACTIVE_COUNT(handle->loop, handle); - - /* Cancel raw read */ - if ((handle->flags & UV_HANDLE_READ_PENDING) && - (handle->flags & UV_HANDLE_TTY_RAW)) { - /* Write some bullshit event to force the console wait to return. */ - INPUT_RECORD record; - DWORD written; - memset(&record, 0, sizeof record); - if (!WriteConsoleInputW(handle->handle, &record, 1, &written)) { - return GetLastError(); - } - } - - /* Cancel line-buffered read */ - if (handle->read_line_handle != NULL) { - /* Closing this handle will cancel the ReadConsole operation */ - CloseHandle(handle->read_line_handle); - handle->read_line_handle = NULL; - } - - - return 0; -} - - -static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info) { - int old_virtual_width = uv_tty_virtual_width; - int old_virtual_height = uv_tty_virtual_height; - - uv_tty_virtual_width = info->dwSize.X; - uv_tty_virtual_height = info->srWindow.Bottom - info->srWindow.Top + 1; - - /* Recompute virtual window offset row. */ - if (uv_tty_virtual_offset == -1) { - uv_tty_virtual_offset = info->dwCursorPosition.Y; - } else if (uv_tty_virtual_offset < info->dwCursorPosition.Y - - uv_tty_virtual_height + 1) { - /* If suddenly find the cursor outside of the virtual window, it must */ - /* have somehow scrolled. Update the virtual window offset. */ - uv_tty_virtual_offset = info->dwCursorPosition.Y - - uv_tty_virtual_height + 1; - } - if (uv_tty_virtual_offset + uv_tty_virtual_height > info->dwSize.Y) { - uv_tty_virtual_offset = info->dwSize.Y - uv_tty_virtual_height; - } - if (uv_tty_virtual_offset < 0) { - uv_tty_virtual_offset = 0; - } - - /* If the virtual window size changed, emit a SIGWINCH signal. Don't emit */ - /* if this was the first time the virtual window size was computed. */ - if (old_virtual_width != -1 && old_virtual_height != -1 && - (uv_tty_virtual_width != old_virtual_width || - uv_tty_virtual_height != old_virtual_height)) { - uv__signal_dispatch(SIGWINCH); - } -} - - -static COORD uv_tty_make_real_coord(uv_tty_t* handle, - CONSOLE_SCREEN_BUFFER_INFO* info, int x, unsigned char x_relative, int y, - unsigned char y_relative) { - COORD result; - - uv_tty_update_virtual_window(info); - - /* Adjust y position */ - if (y_relative) { - y = info->dwCursorPosition.Y + y; - } else { - y = uv_tty_virtual_offset + y; - } - /* Clip y to virtual client rectangle */ - if (y < uv_tty_virtual_offset) { - y = uv_tty_virtual_offset; - } else if (y >= uv_tty_virtual_offset + uv_tty_virtual_height) { - y = uv_tty_virtual_offset + uv_tty_virtual_height - 1; - } - - /* Adjust x */ - if (x_relative) { - x = info->dwCursorPosition.X + x; - } - /* Clip x */ - if (x < 0) { - x = 0; - } else if (x >= uv_tty_virtual_width) { - x = uv_tty_virtual_width - 1; - } - - result.X = (unsigned short) x; - result.Y = (unsigned short) y; - return result; -} - - -static int uv_tty_emit_text(uv_tty_t* handle, WCHAR buffer[], DWORD length, - DWORD* error) { - DWORD written; - - if (*error != ERROR_SUCCESS) { - return -1; - } - - if (!WriteConsoleW(handle->handle, - (void*) buffer, - length, - &written, - NULL)) { - *error = GetLastError(); - return -1; - } - - return 0; -} - - -static int uv_tty_move_caret(uv_tty_t* handle, int x, unsigned char x_relative, - int y, unsigned char y_relative, DWORD* error) { - CONSOLE_SCREEN_BUFFER_INFO info; - COORD pos; - - if (*error != ERROR_SUCCESS) { - return -1; - } - - retry: - if (!GetConsoleScreenBufferInfo(handle->handle, &info)) { - *error = GetLastError(); - } - - pos = uv_tty_make_real_coord(handle, &info, x, x_relative, y, y_relative); - - if (!SetConsoleCursorPosition(handle->handle, pos)) { - if (GetLastError() == ERROR_INVALID_PARAMETER) { - /* The console may be resized - retry */ - goto retry; - } else { - *error = GetLastError(); - return -1; - } - } - - return 0; -} - - -static int uv_tty_reset(uv_tty_t* handle, DWORD* error) { - const COORD origin = {0, 0}; - const WORD char_attrs = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; - CONSOLE_SCREEN_BUFFER_INFO info; - DWORD count, written; - - if (*error != ERROR_SUCCESS) { - return -1; - } - - /* Reset original text attributes. */ - if (!SetConsoleTextAttribute(handle->handle, char_attrs)) { - *error = GetLastError(); - return -1; - } - - /* Move the cursor position to (0, 0). */ - if (!SetConsoleCursorPosition(handle->handle, origin)) { - *error = GetLastError(); - return -1; - } - - /* Clear the screen buffer. */ - retry: - if (!GetConsoleScreenBufferInfo(handle->handle, &info)) { - *error = GetLastError(); - return -1; - } - - count = info.dwSize.X * info.dwSize.Y; - - if (!(FillConsoleOutputCharacterW(handle->handle, - L'\x20', - count, - origin, - &written) && - FillConsoleOutputAttribute(handle->handle, - char_attrs, - written, - origin, - &written))) { - if (GetLastError() == ERROR_INVALID_PARAMETER) { - /* The console may be resized - retry */ - goto retry; - } else { - *error = GetLastError(); - return -1; - } - } - - /* Move the virtual window up to the top. */ - uv_tty_virtual_offset = 0; - uv_tty_update_virtual_window(&info); - - return 0; -} - - -static int uv_tty_clear(uv_tty_t* handle, int dir, char entire_screen, - DWORD* error) { - CONSOLE_SCREEN_BUFFER_INFO info; - COORD start, end; - DWORD count, written; - - int x1, x2, y1, y2; - int x1r, x2r, y1r, y2r; - - if (*error != ERROR_SUCCESS) { - return -1; - } - - if (dir == 0) { - /* Clear from current position */ - x1 = 0; - x1r = 1; - } else { - /* Clear from column 0 */ - x1 = 0; - x1r = 0; - } - - if (dir == 1) { - /* Clear to current position */ - x2 = 0; - x2r = 1; - } else { - /* Clear to end of row. We pretend the console is 65536 characters wide, */ - /* uv_tty_make_real_coord will clip it to the actual console width. */ - x2 = 0xffff; - x2r = 0; - } - - if (!entire_screen) { - /* Stay on our own row */ - y1 = y2 = 0; - y1r = y2r = 1; - } else { - /* Apply columns direction to row */ - y1 = x1; - y1r = x1r; - y2 = x2; - y2r = x2r; - } - - retry: - if (!GetConsoleScreenBufferInfo(handle->handle, &info)) { - *error = GetLastError(); - return -1; - } - - start = uv_tty_make_real_coord(handle, &info, x1, x1r, y1, y1r); - end = uv_tty_make_real_coord(handle, &info, x2, x2r, y2, y2r); - count = (end.Y * info.dwSize.X + end.X) - - (start.Y * info.dwSize.X + start.X) + 1; - - if (!(FillConsoleOutputCharacterW(handle->handle, - L'\x20', - count, - start, - &written) && - FillConsoleOutputAttribute(handle->handle, - info.wAttributes, - written, - start, - &written))) { - if (GetLastError() == ERROR_INVALID_PARAMETER) { - /* The console may be resized - retry */ - goto retry; - } else { - *error = GetLastError(); - return -1; - } - } - - return 0; -} - -#define FLIP_FGBG \ - do { \ - WORD fg = info.wAttributes & 0xF; \ - WORD bg = info.wAttributes & 0xF0; \ - info.wAttributes &= 0xFF00; \ - info.wAttributes |= fg << 4; \ - info.wAttributes |= bg >> 4; \ - } while (0) - -static int uv_tty_set_style(uv_tty_t* handle, DWORD* error) { - unsigned short argc = handle->ansi_csi_argc; - unsigned short* argv = handle->ansi_csi_argv; - int i; - CONSOLE_SCREEN_BUFFER_INFO info; - - char fg_color = -1, bg_color = -1; - char fg_bright = -1, bg_bright = -1; - char inverse = -1; - - if (argc == 0) { - /* Reset mode */ - fg_color = 7; - bg_color = 0; - fg_bright = 0; - bg_bright = 0; - inverse = 0; - } - - for (i = 0; i < argc; i++) { - short arg = argv[i]; - - if (arg == 0) { - /* Reset mode */ - fg_color = 7; - bg_color = 0; - fg_bright = 0; - bg_bright = 0; - inverse = 0; - - } else if (arg == 1) { - /* Foreground bright on */ - fg_bright = 1; - - } else if (arg == 2) { - /* Both bright off */ - fg_bright = 0; - bg_bright = 0; - - } else if (arg == 5) { - /* Background bright on */ - bg_bright = 1; - - } else if (arg == 7) { - /* Inverse: on */ - inverse = 1; - - } else if (arg == 21 || arg == 22) { - /* Foreground bright off */ - fg_bright = 0; - - } else if (arg == 25) { - /* Background bright off */ - bg_bright = 0; - - } else if (arg == 27) { - /* Inverse: off */ - inverse = 0; - - } else if (arg >= 30 && arg <= 37) { - /* Set foreground color */ - fg_color = arg - 30; - - } else if (arg == 39) { - /* Default text color */ - fg_color = 7; - fg_bright = 0; - - } else if (arg >= 40 && arg <= 47) { - /* Set background color */ - bg_color = arg - 40; - - } else if (arg == 49) { - /* Default background color */ - bg_color = 0; - bg_bright = 0; - - } else if (arg >= 90 && arg <= 97) { - /* Set bold foreground color */ - fg_bright = 1; - fg_color = arg - 90; - - } else if (arg >= 100 && arg <= 107) { - /* Set bold background color */ - bg_bright = 1; - bg_color = arg - 100; - - } - } - - if (fg_color == -1 && bg_color == -1 && fg_bright == -1 && - bg_bright == -1 && inverse == -1) { - /* Nothing changed */ - return 0; - } - - if (!GetConsoleScreenBufferInfo(handle->handle, &info)) { - *error = GetLastError(); - return -1; - } - - if ((info.wAttributes & COMMON_LVB_REVERSE_VIDEO) > 0) { - FLIP_FGBG; - } - - if (fg_color != -1) { - info.wAttributes &= ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); - if (fg_color & 1) info.wAttributes |= FOREGROUND_RED; - if (fg_color & 2) info.wAttributes |= FOREGROUND_GREEN; - if (fg_color & 4) info.wAttributes |= FOREGROUND_BLUE; - } - - if (fg_bright != -1) { - if (fg_bright) { - info.wAttributes |= FOREGROUND_INTENSITY; - } else { - info.wAttributes &= ~FOREGROUND_INTENSITY; - } - } - - if (bg_color != -1) { - info.wAttributes &= ~(BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); - if (bg_color & 1) info.wAttributes |= BACKGROUND_RED; - if (bg_color & 2) info.wAttributes |= BACKGROUND_GREEN; - if (bg_color & 4) info.wAttributes |= BACKGROUND_BLUE; - } - - if (bg_bright != -1) { - if (bg_bright) { - info.wAttributes |= BACKGROUND_INTENSITY; - } else { - info.wAttributes &= ~BACKGROUND_INTENSITY; - } - } - - if (inverse != -1) { - if (inverse) { - info.wAttributes |= COMMON_LVB_REVERSE_VIDEO; - } else { - info.wAttributes &= ~COMMON_LVB_REVERSE_VIDEO; - } - } - - if ((info.wAttributes & COMMON_LVB_REVERSE_VIDEO) > 0) { - FLIP_FGBG; - } - - if (!SetConsoleTextAttribute(handle->handle, info.wAttributes)) { - *error = GetLastError(); - return -1; - } - - return 0; -} - - -static int uv_tty_save_state(uv_tty_t* handle, unsigned char save_attributes, - DWORD* error) { - CONSOLE_SCREEN_BUFFER_INFO info; - - if (*error != ERROR_SUCCESS) { - return -1; - } - - if (!GetConsoleScreenBufferInfo(handle->handle, &info)) { - *error = GetLastError(); - return -1; - } - - uv_tty_update_virtual_window(&info); - - handle->saved_position.X = info.dwCursorPosition.X; - handle->saved_position.Y = info.dwCursorPosition.Y - uv_tty_virtual_offset; - handle->flags |= UV_HANDLE_TTY_SAVED_POSITION; - - if (save_attributes) { - handle->saved_attributes = info.wAttributes & - (FOREGROUND_INTENSITY | BACKGROUND_INTENSITY); - handle->flags |= UV_HANDLE_TTY_SAVED_ATTRIBUTES; - } - - return 0; -} - - -static int uv_tty_restore_state(uv_tty_t* handle, - unsigned char restore_attributes, DWORD* error) { - CONSOLE_SCREEN_BUFFER_INFO info; - WORD new_attributes; - - if (*error != ERROR_SUCCESS) { - return -1; - } - - if (handle->flags & UV_HANDLE_TTY_SAVED_POSITION) { - if (uv_tty_move_caret(handle, - handle->saved_position.X, - 0, - handle->saved_position.Y, - 0, - error) != 0) { - return -1; - } - } - - if (restore_attributes && - (handle->flags & UV_HANDLE_TTY_SAVED_ATTRIBUTES)) { - if (!GetConsoleScreenBufferInfo(handle->handle, &info)) { - *error = GetLastError(); - return -1; - } - - new_attributes = info.wAttributes; - new_attributes &= ~(FOREGROUND_INTENSITY | BACKGROUND_INTENSITY); - new_attributes |= handle->saved_attributes; - - if (!SetConsoleTextAttribute(handle->handle, new_attributes)) { - *error = GetLastError(); - return -1; - } - } - - return 0; -} - -static int uv_tty_set_cursor_visibility(uv_tty_t* handle, - BOOL visible, - DWORD* error) { - CONSOLE_CURSOR_INFO cursor_info; - - if (!GetConsoleCursorInfo(handle->handle, &cursor_info)) { - *error = GetLastError(); - return -1; - } - - cursor_info.bVisible = visible; - - if (!SetConsoleCursorInfo(handle->handle, &cursor_info)) { - *error = GetLastError(); - return -1; - } - - return 0; -} - -static int uv_tty_write_bufs(uv_tty_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - DWORD* error) { - /* We can only write 8k characters at a time. Windows can't handle */ - /* much more characters in a single console write anyway. */ - WCHAR utf16_buf[8192]; - DWORD utf16_buf_used = 0; - unsigned int i; - -#define FLUSH_TEXT() \ - do { \ - if (utf16_buf_used > 0) { \ - uv_tty_emit_text(handle, utf16_buf, utf16_buf_used, error); \ - utf16_buf_used = 0; \ - } \ - } while (0) - - /* Cache for fast access */ - unsigned char utf8_bytes_left = handle->utf8_bytes_left; - unsigned int utf8_codepoint = handle->utf8_codepoint; - unsigned char previous_eol = handle->previous_eol; - unsigned char ansi_parser_state = handle->ansi_parser_state; - - /* Store the error here. If we encounter an error, stop trying to do i/o */ - /* but keep parsing the buffer so we leave the parser in a consistent */ - /* state. */ - *error = ERROR_SUCCESS; - - EnterCriticalSection(&uv_tty_output_lock); - - for (i = 0; i < nbufs; i++) { - uv_buf_t buf = bufs[i]; - unsigned int j; - - for (j = 0; j < buf.len; j++) { - unsigned char c = buf.base[j]; - - /* Run the character through the utf8 decoder We happily accept non */ - /* shortest form encodings and invalid code points - there's no real */ - /* harm that can be done. */ - if (utf8_bytes_left == 0) { - /* Read utf-8 start byte */ - DWORD first_zero_bit; - unsigned char not_c = ~c; -#ifdef _MSC_VER /* msvc */ - if (_BitScanReverse(&first_zero_bit, not_c)) { -#else /* assume gcc */ - if (c != 0) { - first_zero_bit = (sizeof(int) * 8) - 1 - __builtin_clz(not_c); -#endif - if (first_zero_bit == 7) { - /* Ascii - pass right through */ - utf8_codepoint = (unsigned int) c; - - } else if (first_zero_bit <= 5) { - /* Multibyte sequence */ - utf8_codepoint = (0xff >> (8 - first_zero_bit)) & c; - utf8_bytes_left = (char) (6 - first_zero_bit); - - } else { - /* Invalid continuation */ - utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER; - } - - } else { - /* 0xff -- invalid */ - utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER; - } - - } else if ((c & 0xc0) == 0x80) { - /* Valid continuation of utf-8 multibyte sequence */ - utf8_bytes_left--; - utf8_codepoint <<= 6; - utf8_codepoint |= ((unsigned int) c & 0x3f); - - } else { - /* Start byte where continuation was expected. */ - utf8_bytes_left = 0; - utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER; - /* Patch buf offset so this character will be parsed again as a */ - /* start byte. */ - j--; - } - - /* Maybe we need to parse more bytes to find a character. */ - if (utf8_bytes_left != 0) { - continue; - } - - /* Parse vt100/ansi escape codes */ - if (ansi_parser_state == ANSI_NORMAL) { - switch (utf8_codepoint) { - case '\033': - ansi_parser_state = ANSI_ESCAPE_SEEN; - continue; - - case 0233: - ansi_parser_state = ANSI_CSI; - handle->ansi_csi_argc = 0; - continue; - } - - } else if (ansi_parser_state == ANSI_ESCAPE_SEEN) { - switch (utf8_codepoint) { - case '[': - ansi_parser_state = ANSI_CSI; - handle->ansi_csi_argc = 0; - continue; - - case '^': - case '_': - case 'P': - case ']': - /* Not supported, but we'll have to parse until we see a stop */ - /* code, e.g. ESC \ or BEL. */ - ansi_parser_state = ANSI_ST_CONTROL; - continue; - - case '\033': - /* Ignore double escape. */ - continue; - - case 'c': - /* Full console reset. */ - FLUSH_TEXT(); - uv_tty_reset(handle, error); - ansi_parser_state = ANSI_NORMAL; - continue; - - case '7': - /* Save the cursor position and text attributes. */ - FLUSH_TEXT(); - uv_tty_save_state(handle, 1, error); - ansi_parser_state = ANSI_NORMAL; - continue; - - case '8': - /* Restore the cursor position and text attributes */ - FLUSH_TEXT(); - uv_tty_restore_state(handle, 1, error); - ansi_parser_state = ANSI_NORMAL; - continue; - - default: - if (utf8_codepoint >= '@' && utf8_codepoint <= '_') { - /* Single-char control. */ - ansi_parser_state = ANSI_NORMAL; - continue; - } else { - /* Invalid - proceed as normal, */ - ansi_parser_state = ANSI_NORMAL; - } - } - - } else if (ansi_parser_state & ANSI_CSI) { - if (!(ansi_parser_state & ANSI_IGNORE)) { - if (utf8_codepoint >= '0' && utf8_codepoint <= '9') { - /* Parsing a numerical argument */ - - if (!(ansi_parser_state & ANSI_IN_ARG)) { - /* We were not currently parsing a number */ - - /* Check for too many arguments */ - if (handle->ansi_csi_argc >= ARRAY_SIZE(handle->ansi_csi_argv)) { - ansi_parser_state |= ANSI_IGNORE; - continue; - } - - ansi_parser_state |= ANSI_IN_ARG; - handle->ansi_csi_argc++; - handle->ansi_csi_argv[handle->ansi_csi_argc - 1] = - (unsigned short) utf8_codepoint - '0'; - continue; - } else { - /* We were already parsing a number. Parse next digit. */ - uint32_t value = 10 * - handle->ansi_csi_argv[handle->ansi_csi_argc - 1]; - - /* Check for overflow. */ - if (value > UINT16_MAX) { - ansi_parser_state |= ANSI_IGNORE; - continue; - } - - handle->ansi_csi_argv[handle->ansi_csi_argc - 1] = - (unsigned short) value + (utf8_codepoint - '0'); - continue; - } - - } else if (utf8_codepoint == ';') { - /* Denotes the end of an argument. */ - if (ansi_parser_state & ANSI_IN_ARG) { - ansi_parser_state &= ~ANSI_IN_ARG; - continue; - - } else { - /* If ANSI_IN_ARG is not set, add another argument and */ - /* default it to 0. */ - /* Check for too many arguments */ - if (handle->ansi_csi_argc >= ARRAY_SIZE(handle->ansi_csi_argv)) { - ansi_parser_state |= ANSI_IGNORE; - continue; - } - - handle->ansi_csi_argc++; - handle->ansi_csi_argv[handle->ansi_csi_argc - 1] = 0; - continue; - } - - } else if (utf8_codepoint == '?' && !(ansi_parser_state & ANSI_IN_ARG) && - handle->ansi_csi_argc == 0) { - /* Ignores '?' if it is the first character after CSI[ */ - /* This is an extension character from the VT100 codeset */ - /* that is supported and used by most ANSI terminals today. */ - continue; - - } else if (utf8_codepoint >= '@' && utf8_codepoint <= '~' && - (handle->ansi_csi_argc > 0 || utf8_codepoint != '[')) { - int x, y, d; - - /* Command byte */ - switch (utf8_codepoint) { - case 'A': - /* cursor up */ - FLUSH_TEXT(); - y = -(handle->ansi_csi_argc ? handle->ansi_csi_argv[0] : 1); - uv_tty_move_caret(handle, 0, 1, y, 1, error); - break; - - case 'B': - /* cursor down */ - FLUSH_TEXT(); - y = handle->ansi_csi_argc ? handle->ansi_csi_argv[0] : 1; - uv_tty_move_caret(handle, 0, 1, y, 1, error); - break; - - case 'C': - /* cursor forward */ - FLUSH_TEXT(); - x = handle->ansi_csi_argc ? handle->ansi_csi_argv[0] : 1; - uv_tty_move_caret(handle, x, 1, 0, 1, error); - break; - - case 'D': - /* cursor back */ - FLUSH_TEXT(); - x = -(handle->ansi_csi_argc ? handle->ansi_csi_argv[0] : 1); - uv_tty_move_caret(handle, x, 1, 0, 1, error); - break; - - case 'E': - /* cursor next line */ - FLUSH_TEXT(); - y = handle->ansi_csi_argc ? handle->ansi_csi_argv[0] : 1; - uv_tty_move_caret(handle, 0, 0, y, 1, error); - break; - - case 'F': - /* cursor previous line */ - FLUSH_TEXT(); - y = -(handle->ansi_csi_argc ? handle->ansi_csi_argv[0] : 1); - uv_tty_move_caret(handle, 0, 0, y, 1, error); - break; - - case 'G': - /* cursor horizontal move absolute */ - FLUSH_TEXT(); - x = (handle->ansi_csi_argc >= 1 && handle->ansi_csi_argv[0]) - ? handle->ansi_csi_argv[0] - 1 : 0; - uv_tty_move_caret(handle, x, 0, 0, 1, error); - break; - - case 'H': - case 'f': - /* cursor move absolute */ - FLUSH_TEXT(); - y = (handle->ansi_csi_argc >= 1 && handle->ansi_csi_argv[0]) - ? handle->ansi_csi_argv[0] - 1 : 0; - x = (handle->ansi_csi_argc >= 2 && handle->ansi_csi_argv[1]) - ? handle->ansi_csi_argv[1] - 1 : 0; - uv_tty_move_caret(handle, x, 0, y, 0, error); - break; - - case 'J': - /* Erase screen */ - FLUSH_TEXT(); - d = handle->ansi_csi_argc ? handle->ansi_csi_argv[0] : 0; - if (d >= 0 && d <= 2) { - uv_tty_clear(handle, d, 1, error); - } - break; - - case 'K': - /* Erase line */ - FLUSH_TEXT(); - d = handle->ansi_csi_argc ? handle->ansi_csi_argv[0] : 0; - if (d >= 0 && d <= 2) { - uv_tty_clear(handle, d, 0, error); - } - break; - - case 'm': - /* Set style */ - FLUSH_TEXT(); - uv_tty_set_style(handle, error); - break; - - case 's': - /* Save the cursor position. */ - FLUSH_TEXT(); - uv_tty_save_state(handle, 0, error); - break; - - case 'u': - /* Restore the cursor position */ - FLUSH_TEXT(); - uv_tty_restore_state(handle, 0, error); - break; - - case 'l': - /* Hide the cursor */ - if (handle->ansi_csi_argc == 1 && - handle->ansi_csi_argv[0] == 25) { - FLUSH_TEXT(); - uv_tty_set_cursor_visibility(handle, 0, error); - } - break; - - case 'h': - /* Show the cursor */ - if (handle->ansi_csi_argc == 1 && - handle->ansi_csi_argv[0] == 25) { - FLUSH_TEXT(); - uv_tty_set_cursor_visibility(handle, 1, error); - } - break; - } - - /* Sequence ended - go back to normal state. */ - ansi_parser_state = ANSI_NORMAL; - continue; - - } else { - /* We don't support commands that use private mode characters or */ - /* intermediaries. Ignore the rest of the sequence. */ - ansi_parser_state |= ANSI_IGNORE; - continue; - } - } else { - /* We're ignoring this command. Stop only on command character. */ - if (utf8_codepoint >= '@' && utf8_codepoint <= '~') { - ansi_parser_state = ANSI_NORMAL; - } - continue; - } - - } else if (ansi_parser_state & ANSI_ST_CONTROL) { - /* Unsupported control code */ - /* Ignore everything until we see BEL or ESC \ */ - if (ansi_parser_state & ANSI_IN_STRING) { - if (!(ansi_parser_state & ANSI_BACKSLASH_SEEN)) { - if (utf8_codepoint == '"') { - ansi_parser_state &= ~ANSI_IN_STRING; - } else if (utf8_codepoint == '\\') { - ansi_parser_state |= ANSI_BACKSLASH_SEEN; - } - } else { - ansi_parser_state &= ~ANSI_BACKSLASH_SEEN; - } - } else { - if (utf8_codepoint == '\007' || (utf8_codepoint == '\\' && - (ansi_parser_state & ANSI_ESCAPE_SEEN))) { - /* End of sequence */ - ansi_parser_state = ANSI_NORMAL; - } else if (utf8_codepoint == '\033') { - /* Escape character */ - ansi_parser_state |= ANSI_ESCAPE_SEEN; - } else if (utf8_codepoint == '"') { - /* String starting */ - ansi_parser_state |= ANSI_IN_STRING; - ansi_parser_state &= ~ANSI_ESCAPE_SEEN; - ansi_parser_state &= ~ANSI_BACKSLASH_SEEN; - } else { - ansi_parser_state &= ~ANSI_ESCAPE_SEEN; - } - } - continue; - } else { - /* Inconsistent state */ - abort(); - } - - /* We wouldn't mind emitting utf-16 surrogate pairs. Too bad, the */ - /* windows console doesn't really support UTF-16, so just emit the */ - /* replacement character. */ - if (utf8_codepoint > 0xffff) { - utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER; - } - - if (utf8_codepoint == 0x0a || utf8_codepoint == 0x0d) { - /* EOL conversion - emit \r\n, when we see either \r or \n. */ - /* If a \n immediately follows a \r or vice versa, ignore it. */ - if (previous_eol == 0 || utf8_codepoint == previous_eol) { - /* If there's no room in the utf16 buf, flush it first. */ - if (2 > ARRAY_SIZE(utf16_buf) - utf16_buf_used) { - uv_tty_emit_text(handle, utf16_buf, utf16_buf_used, error); - utf16_buf_used = 0; - } - - utf16_buf[utf16_buf_used++] = L'\r'; - utf16_buf[utf16_buf_used++] = L'\n'; - previous_eol = (char) utf8_codepoint; - } else { - /* Ignore this newline, but don't ignore later ones. */ - previous_eol = 0; - } - - } else if (utf8_codepoint <= 0xffff) { - /* Encode character into utf-16 buffer. */ - - /* If there's no room in the utf16 buf, flush it first. */ - if (1 > ARRAY_SIZE(utf16_buf) - utf16_buf_used) { - uv_tty_emit_text(handle, utf16_buf, utf16_buf_used, error); - utf16_buf_used = 0; - } - - utf16_buf[utf16_buf_used++] = (WCHAR) utf8_codepoint; - previous_eol = 0; - } - } - } - - /* Flush remaining characters */ - FLUSH_TEXT(); - - /* Copy cached values back to struct. */ - handle->utf8_bytes_left = utf8_bytes_left; - handle->utf8_codepoint = utf8_codepoint; - handle->previous_eol = previous_eol; - handle->ansi_parser_state = ansi_parser_state; - - LeaveCriticalSection(&uv_tty_output_lock); - - if (*error == STATUS_SUCCESS) { - return 0; - } else { - return -1; - } - -#undef FLUSH_TEXT -} - - -int uv_tty_write(uv_loop_t* loop, - uv_write_t* req, - uv_tty_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - uv_write_cb cb) { - DWORD error; - - uv_req_init(loop, (uv_req_t*) req); - req->type = UV_WRITE; - req->handle = (uv_stream_t*) handle; - req->cb = cb; - - handle->reqs_pending++; - handle->write_reqs_pending++; - REGISTER_HANDLE_REQ(loop, handle, req); - - req->queued_bytes = 0; - - if (!uv_tty_write_bufs(handle, bufs, nbufs, &error)) { - SET_REQ_SUCCESS(req); - } else { - SET_REQ_ERROR(req, error); - } - - uv_insert_pending_req(loop, (uv_req_t*) req); - - return 0; -} - - -int uv__tty_try_write(uv_tty_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs) { - DWORD error; - - if (handle->write_reqs_pending > 0) - return UV_EAGAIN; - - if (uv_tty_write_bufs(handle, bufs, nbufs, &error)) - return uv_translate_sys_error(error); - - return uv__count_bufs(bufs, nbufs); -} - - -void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle, - uv_write_t* req) { - int err; - - handle->write_queue_size -= req->queued_bytes; - UNREGISTER_HANDLE_REQ(loop, handle, req); - - if (req->cb) { - err = GET_REQ_ERROR(req); - req->cb(req, uv_translate_sys_error(err)); - } - - handle->write_reqs_pending--; - if (handle->shutdown_req != NULL && - handle->write_reqs_pending == 0) { - uv_want_endgame(loop, (uv_handle_t*)handle); - } - - DECREASE_PENDING_REQ_COUNT(handle); -} - - -void uv_tty_close(uv_tty_t* handle) { - CloseHandle(handle->handle); - - if (handle->flags & UV_HANDLE_READING) - uv_tty_read_stop(handle); - - handle->handle = INVALID_HANDLE_VALUE; - handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); - uv__handle_closing(handle); - - if (handle->reqs_pending == 0) { - uv_want_endgame(handle->loop, (uv_handle_t*) handle); - } -} - - -void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) { - if (!(handle->flags & UV_HANDLE_TTY_READABLE) && - handle->shutdown_req != NULL && - handle->write_reqs_pending == 0) { - UNREGISTER_HANDLE_REQ(loop, handle, handle->shutdown_req); - - /* TTY shutdown is really just a no-op */ - if (handle->shutdown_req->cb) { - if (handle->flags & UV__HANDLE_CLOSING) { - handle->shutdown_req->cb(handle->shutdown_req, UV_ECANCELED); - } else { - handle->shutdown_req->cb(handle->shutdown_req, 0); - } - } - - handle->shutdown_req = NULL; - - DECREASE_PENDING_REQ_COUNT(handle); - return; - } - - if (handle->flags & UV__HANDLE_CLOSING && - handle->reqs_pending == 0) { - /* The console handle duplicate used for line reading should be destroyed */ - /* by uv_tty_read_stop. */ - assert(!(handle->flags & UV_HANDLE_TTY_READABLE) || - handle->read_line_handle == NULL); - - /* The wait handle used for raw reading should be unregistered when the */ - /* wait callback runs. */ - assert(!(handle->flags & UV_HANDLE_TTY_READABLE) || - handle->read_raw_wait == NULL); - - assert(!(handle->flags & UV_HANDLE_CLOSED)); - uv__handle_close(handle); - } -} - - -/* TODO: remove me */ -void uv_process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle, - uv_req_t* raw_req) { - abort(); -} - - -/* TODO: remove me */ -void uv_process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle, - uv_connect_t* req) { - abort(); -} - - -int uv_tty_reset_mode(void) { - /* Not necessary to do anything. */ - return 0; -} diff --git a/libuv/src/win/udp.c b/libuv/src/win/udp.c deleted file mode 100644 index 73b5bd5..0000000 --- a/libuv/src/win/udp.c +++ /dev/null @@ -1,890 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include - -#include "uv.h" -#include "internal.h" -#include "handle-inl.h" -#include "stream-inl.h" -#include "req-inl.h" - - -/* - * Threshold of active udp streams for which to preallocate udp read buffers. - */ -const unsigned int uv_active_udp_streams_threshold = 0; - -/* A zero-size buffer for use by uv_udp_read */ -static char uv_zero_[] = ""; - -int uv_udp_getsockname(const uv_udp_t* handle, - struct sockaddr* name, - int* namelen) { - int result; - - if (!(handle->flags & UV_HANDLE_BOUND)) { - return UV_EINVAL; - } - - result = getsockname(handle->socket, name, namelen); - if (result != 0) { - return uv_translate_sys_error(WSAGetLastError()); - } - - return 0; -} - - -static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket, - int family) { - DWORD yes = 1; - WSAPROTOCOL_INFOW info; - int opt_len; - - assert(handle->socket == INVALID_SOCKET); - - /* Set the socket to nonblocking mode */ - if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) { - return WSAGetLastError(); - } - - /* Make the socket non-inheritable */ - if (!SetHandleInformation((HANDLE)socket, HANDLE_FLAG_INHERIT, 0)) { - return GetLastError(); - } - - /* Associate it with the I/O completion port. */ - /* Use uv_handle_t pointer as completion key. */ - if (CreateIoCompletionPort((HANDLE)socket, - loop->iocp, - (ULONG_PTR)socket, - 0) == NULL) { - return GetLastError(); - } - - if (pSetFileCompletionNotificationModes) { - /* All known Windows that support SetFileCompletionNotificationModes */ - /* have a bug that makes it impossible to use this function in */ - /* conjunction with datagram sockets. We can work around that but only */ - /* if the user is using the default UDP driver (AFD) and has no other */ - /* LSPs stacked on top. Here we check whether that is the case. */ - opt_len = (int) sizeof info; - if (getsockopt(socket, - SOL_SOCKET, - SO_PROTOCOL_INFOW, - (char*) &info, - &opt_len) == SOCKET_ERROR) { - return GetLastError(); - } - - if (info.ProtocolChain.ChainLen == 1) { - if (pSetFileCompletionNotificationModes((HANDLE)socket, - FILE_SKIP_SET_EVENT_ON_HANDLE | - FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) { - handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP; - handle->func_wsarecv = uv_wsarecv_workaround; - handle->func_wsarecvfrom = uv_wsarecvfrom_workaround; - } else if (GetLastError() != ERROR_INVALID_FUNCTION) { - return GetLastError(); - } - } - } - - handle->socket = socket; - - if (family == AF_INET6) { - handle->flags |= UV_HANDLE_IPV6; - } else { - assert(!(handle->flags & UV_HANDLE_IPV6)); - } - - return 0; -} - - -int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) { - uv__handle_init(loop, (uv_handle_t*) handle, UV_UDP); - - handle->socket = INVALID_SOCKET; - handle->reqs_pending = 0; - handle->activecnt = 0; - handle->func_wsarecv = WSARecv; - handle->func_wsarecvfrom = WSARecvFrom; - handle->send_queue_size = 0; - handle->send_queue_count = 0; - - uv_req_init(loop, (uv_req_t*) &(handle->recv_req)); - handle->recv_req.type = UV_UDP_RECV; - handle->recv_req.data = handle; - - return 0; -} - - -void uv_udp_close(uv_loop_t* loop, uv_udp_t* handle) { - uv_udp_recv_stop(handle); - closesocket(handle->socket); - handle->socket = INVALID_SOCKET; - - uv__handle_closing(handle); - - if (handle->reqs_pending == 0) { - uv_want_endgame(loop, (uv_handle_t*) handle); - } -} - - -void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle) { - if (handle->flags & UV__HANDLE_CLOSING && - handle->reqs_pending == 0) { - assert(!(handle->flags & UV_HANDLE_CLOSED)); - uv__handle_close(handle); - } -} - - -static int uv_udp_maybe_bind(uv_udp_t* handle, - const struct sockaddr* addr, - unsigned int addrlen, - unsigned int flags) { - int r; - int err; - DWORD no = 0; - - if (handle->flags & UV_HANDLE_BOUND) - return 0; - - if ((flags & UV_UDP_IPV6ONLY) && addr->sa_family != AF_INET6) { - /* UV_UDP_IPV6ONLY is supported only for IPV6 sockets */ - return ERROR_INVALID_PARAMETER; - } - - if (handle->socket == INVALID_SOCKET) { - SOCKET sock = socket(addr->sa_family, SOCK_DGRAM, 0); - if (sock == INVALID_SOCKET) { - return WSAGetLastError(); - } - - err = uv_udp_set_socket(handle->loop, handle, sock, addr->sa_family); - if (err) { - closesocket(sock); - return err; - } - - if (flags & UV_UDP_REUSEADDR) { - DWORD yes = 1; - /* Set SO_REUSEADDR on the socket. */ - if (setsockopt(sock, - SOL_SOCKET, - SO_REUSEADDR, - (char*) &yes, - sizeof yes) == SOCKET_ERROR) { - err = WSAGetLastError(); - closesocket(sock); - return err; - } - } - - if (addr->sa_family == AF_INET6) - handle->flags |= UV_HANDLE_IPV6; - } - - if (addr->sa_family == AF_INET6 && !(flags & UV_UDP_IPV6ONLY)) { - /* On windows IPV6ONLY is on by default. */ - /* If the user doesn't specify it libuv turns it off. */ - - /* TODO: how to handle errors? This may fail if there is no ipv4 stack */ - /* available, or when run on XP/2003 which have no support for dualstack */ - /* sockets. For now we're silently ignoring the error. */ - setsockopt(handle->socket, - IPPROTO_IPV6, - IPV6_V6ONLY, - (char*) &no, - sizeof no); - } - - r = bind(handle->socket, addr, addrlen); - if (r == SOCKET_ERROR) { - return WSAGetLastError(); - } - - handle->flags |= UV_HANDLE_BOUND; - - return 0; -} - - -static void uv_udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) { - uv_req_t* req; - uv_buf_t buf; - DWORD bytes, flags; - int result; - - assert(handle->flags & UV_HANDLE_READING); - assert(!(handle->flags & UV_HANDLE_READ_PENDING)); - - req = &handle->recv_req; - memset(&req->overlapped, 0, sizeof(req->overlapped)); - - /* - * Preallocate a read buffer if the number of active streams is below - * the threshold. - */ - if (loop->active_udp_streams < uv_active_udp_streams_threshold) { - handle->flags &= ~UV_HANDLE_ZERO_READ; - - handle->alloc_cb((uv_handle_t*) handle, 65536, &handle->recv_buffer); - if (handle->recv_buffer.len == 0) { - handle->recv_cb(handle, UV_ENOBUFS, &handle->recv_buffer, NULL, 0); - return; - } - assert(handle->recv_buffer.base != NULL); - - buf = handle->recv_buffer; - memset(&handle->recv_from, 0, sizeof handle->recv_from); - handle->recv_from_len = sizeof handle->recv_from; - flags = 0; - - result = handle->func_wsarecvfrom(handle->socket, - (WSABUF*) &buf, - 1, - &bytes, - &flags, - (struct sockaddr*) &handle->recv_from, - &handle->recv_from_len, - &req->overlapped, - NULL); - - if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) { - /* Process the req without IOCP. */ - handle->flags |= UV_HANDLE_READ_PENDING; - req->overlapped.InternalHigh = bytes; - handle->reqs_pending++; - uv_insert_pending_req(loop, req); - } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { - /* The req will be processed with IOCP. */ - handle->flags |= UV_HANDLE_READ_PENDING; - handle->reqs_pending++; - } else { - /* Make this req pending reporting an error. */ - SET_REQ_ERROR(req, WSAGetLastError()); - uv_insert_pending_req(loop, req); - handle->reqs_pending++; - } - - } else { - handle->flags |= UV_HANDLE_ZERO_READ; - - buf.base = (char*) uv_zero_; - buf.len = 0; - flags = MSG_PEEK; - - result = handle->func_wsarecv(handle->socket, - (WSABUF*) &buf, - 1, - &bytes, - &flags, - &req->overlapped, - NULL); - - if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) { - /* Process the req without IOCP. */ - handle->flags |= UV_HANDLE_READ_PENDING; - req->overlapped.InternalHigh = bytes; - handle->reqs_pending++; - uv_insert_pending_req(loop, req); - } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { - /* The req will be processed with IOCP. */ - handle->flags |= UV_HANDLE_READ_PENDING; - handle->reqs_pending++; - } else { - /* Make this req pending reporting an error. */ - SET_REQ_ERROR(req, WSAGetLastError()); - uv_insert_pending_req(loop, req); - handle->reqs_pending++; - } - } -} - - -int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb, - uv_udp_recv_cb recv_cb) { - uv_loop_t* loop = handle->loop; - int err; - - if (handle->flags & UV_HANDLE_READING) { - return WSAEALREADY; - } - - err = uv_udp_maybe_bind(handle, - (const struct sockaddr*) &uv_addr_ip4_any_, - sizeof(uv_addr_ip4_any_), - 0); - if (err) - return err; - - handle->flags |= UV_HANDLE_READING; - INCREASE_ACTIVE_COUNT(loop, handle); - loop->active_udp_streams++; - - handle->recv_cb = recv_cb; - handle->alloc_cb = alloc_cb; - - /* If reading was stopped and then started again, there could still be a */ - /* recv request pending. */ - if (!(handle->flags & UV_HANDLE_READ_PENDING)) - uv_udp_queue_recv(loop, handle); - - return 0; -} - - -int uv__udp_recv_stop(uv_udp_t* handle) { - if (handle->flags & UV_HANDLE_READING) { - handle->flags &= ~UV_HANDLE_READING; - handle->loop->active_udp_streams--; - DECREASE_ACTIVE_COUNT(loop, handle); - } - - return 0; -} - - -static int uv__send(uv_udp_send_t* req, - uv_udp_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - const struct sockaddr* addr, - unsigned int addrlen, - uv_udp_send_cb cb) { - uv_loop_t* loop = handle->loop; - DWORD result, bytes; - - uv_req_init(loop, (uv_req_t*) req); - req->type = UV_UDP_SEND; - req->handle = handle; - req->cb = cb; - memset(&req->overlapped, 0, sizeof(req->overlapped)); - - result = WSASendTo(handle->socket, - (WSABUF*)bufs, - nbufs, - &bytes, - 0, - addr, - addrlen, - &req->overlapped, - NULL); - - if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) { - /* Request completed immediately. */ - req->queued_bytes = 0; - handle->reqs_pending++; - handle->send_queue_size += req->queued_bytes; - handle->send_queue_count++; - REGISTER_HANDLE_REQ(loop, handle, req); - uv_insert_pending_req(loop, (uv_req_t*)req); - } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { - /* Request queued by the kernel. */ - req->queued_bytes = uv__count_bufs(bufs, nbufs); - handle->reqs_pending++; - handle->send_queue_size += req->queued_bytes; - handle->send_queue_count++; - REGISTER_HANDLE_REQ(loop, handle, req); - } else { - /* Send failed due to an error. */ - return WSAGetLastError(); - } - - return 0; -} - - -void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle, - uv_req_t* req) { - uv_buf_t buf; - int partial; - - assert(handle->type == UV_UDP); - - handle->flags &= ~UV_HANDLE_READ_PENDING; - - if (!REQ_SUCCESS(req)) { - DWORD err = GET_REQ_SOCK_ERROR(req); - if (err == WSAEMSGSIZE) { - /* Not a real error, it just indicates that the received packet */ - /* was bigger than the receive buffer. */ - } else if (err == WSAECONNRESET || err == WSAENETRESET) { - /* A previous sendto operation failed; ignore this error. If */ - /* zero-reading we need to call WSARecv/WSARecvFrom _without_ the */ - /* MSG_PEEK flag to clear out the error queue. For nonzero reads, */ - /* immediately queue a new receive. */ - if (!(handle->flags & UV_HANDLE_ZERO_READ)) { - goto done; - } - } else { - /* A real error occurred. Report the error to the user only if we're */ - /* currently reading. */ - if (handle->flags & UV_HANDLE_READING) { - uv_udp_recv_stop(handle); - buf = (handle->flags & UV_HANDLE_ZERO_READ) ? - uv_buf_init(NULL, 0) : handle->recv_buffer; - handle->recv_cb(handle, uv_translate_sys_error(err), &buf, NULL, 0); - } - goto done; - } - } - - if (!(handle->flags & UV_HANDLE_ZERO_READ)) { - /* Successful read */ - partial = !REQ_SUCCESS(req); - handle->recv_cb(handle, - req->overlapped.InternalHigh, - &handle->recv_buffer, - (const struct sockaddr*) &handle->recv_from, - partial ? UV_UDP_PARTIAL : 0); - } else if (handle->flags & UV_HANDLE_READING) { - DWORD bytes, err, flags; - struct sockaddr_storage from; - int from_len; - - /* Do a nonblocking receive */ - /* TODO: try to read multiple datagrams at once. FIONREAD maybe? */ - handle->alloc_cb((uv_handle_t*) handle, 65536, &buf); - if (buf.len == 0) { - handle->recv_cb(handle, UV_ENOBUFS, &buf, NULL, 0); - goto done; - } - assert(buf.base != NULL); - - memset(&from, 0, sizeof from); - from_len = sizeof from; - - flags = 0; - - if (WSARecvFrom(handle->socket, - (WSABUF*)&buf, - 1, - &bytes, - &flags, - (struct sockaddr*) &from, - &from_len, - NULL, - NULL) != SOCKET_ERROR) { - - /* Message received */ - handle->recv_cb(handle, bytes, &buf, (const struct sockaddr*) &from, 0); - } else { - err = WSAGetLastError(); - if (err == WSAEMSGSIZE) { - /* Message truncated */ - handle->recv_cb(handle, - bytes, - &buf, - (const struct sockaddr*) &from, - UV_UDP_PARTIAL); - } else if (err == WSAEWOULDBLOCK) { - /* Kernel buffer empty */ - handle->recv_cb(handle, 0, &buf, NULL, 0); - } else if (err == WSAECONNRESET || err == WSAENETRESET) { - /* WSAECONNRESET/WSANETRESET is ignored because this just indicates - * that a previous sendto operation failed. - */ - handle->recv_cb(handle, 0, &buf, NULL, 0); - } else { - /* Any other error that we want to report back to the user. */ - uv_udp_recv_stop(handle); - handle->recv_cb(handle, uv_translate_sys_error(err), &buf, NULL, 0); - } - } - } - -done: - /* Post another read if still reading and not closing. */ - if ((handle->flags & UV_HANDLE_READING) && - !(handle->flags & UV_HANDLE_READ_PENDING)) { - uv_udp_queue_recv(loop, handle); - } - - DECREASE_PENDING_REQ_COUNT(handle); -} - - -void uv_process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle, - uv_udp_send_t* req) { - int err; - - assert(handle->type == UV_UDP); - - assert(handle->send_queue_size >= req->queued_bytes); - assert(handle->send_queue_count >= 1); - handle->send_queue_size -= req->queued_bytes; - handle->send_queue_count--; - - UNREGISTER_HANDLE_REQ(loop, handle, req); - - if (req->cb) { - err = 0; - if (!REQ_SUCCESS(req)) { - err = GET_REQ_SOCK_ERROR(req); - } - req->cb(req, uv_translate_sys_error(err)); - } - - DECREASE_PENDING_REQ_COUNT(handle); -} - - -static int uv__udp_set_membership4(uv_udp_t* handle, - const struct sockaddr_in* multicast_addr, - const char* interface_addr, - uv_membership membership) { - int err; - int optname; - struct ip_mreq mreq; - - if (handle->flags & UV_HANDLE_IPV6) - return UV_EINVAL; - - /* If the socket is unbound, bind to inaddr_any. */ - err = uv_udp_maybe_bind(handle, - (const struct sockaddr*) &uv_addr_ip4_any_, - sizeof(uv_addr_ip4_any_), - UV_UDP_REUSEADDR); - if (err) - return uv_translate_sys_error(err); - - memset(&mreq, 0, sizeof mreq); - - if (interface_addr) { - err = uv_inet_pton(AF_INET, interface_addr, &mreq.imr_interface.s_addr); - if (err) - return err; - } else { - mreq.imr_interface.s_addr = htonl(INADDR_ANY); - } - - mreq.imr_multiaddr.s_addr = multicast_addr->sin_addr.s_addr; - - switch (membership) { - case UV_JOIN_GROUP: - optname = IP_ADD_MEMBERSHIP; - break; - case UV_LEAVE_GROUP: - optname = IP_DROP_MEMBERSHIP; - break; - default: - return UV_EINVAL; - } - - if (setsockopt(handle->socket, - IPPROTO_IP, - optname, - (char*) &mreq, - sizeof mreq) == SOCKET_ERROR) { - return uv_translate_sys_error(WSAGetLastError()); - } - - return 0; -} - - -int uv__udp_set_membership6(uv_udp_t* handle, - const struct sockaddr_in6* multicast_addr, - const char* interface_addr, - uv_membership membership) { - int optname; - int err; - struct ipv6_mreq mreq; - struct sockaddr_in6 addr6; - - if ((handle->flags & UV_HANDLE_BOUND) && !(handle->flags & UV_HANDLE_IPV6)) - return UV_EINVAL; - - err = uv_udp_maybe_bind(handle, - (const struct sockaddr*) &uv_addr_ip6_any_, - sizeof(uv_addr_ip6_any_), - UV_UDP_REUSEADDR); - - if (err) - return uv_translate_sys_error(err); - - memset(&mreq, 0, sizeof(mreq)); - - if (interface_addr) { - if (uv_ip6_addr(interface_addr, 0, &addr6)) - return UV_EINVAL; - mreq.ipv6mr_interface = addr6.sin6_scope_id; - } else { - mreq.ipv6mr_interface = 0; - } - - mreq.ipv6mr_multiaddr = multicast_addr->sin6_addr; - - switch (membership) { - case UV_JOIN_GROUP: - optname = IPV6_ADD_MEMBERSHIP; - break; - case UV_LEAVE_GROUP: - optname = IPV6_DROP_MEMBERSHIP; - break; - default: - return UV_EINVAL; - } - - if (setsockopt(handle->socket, - IPPROTO_IPV6, - optname, - (char*) &mreq, - sizeof mreq) == SOCKET_ERROR) { - return uv_translate_sys_error(WSAGetLastError()); - } - - return 0; -} - - -int uv_udp_set_membership(uv_udp_t* handle, - const char* multicast_addr, - const char* interface_addr, - uv_membership membership) { - struct sockaddr_in addr4; - struct sockaddr_in6 addr6; - - if (uv_ip4_addr(multicast_addr, 0, &addr4) == 0) - return uv__udp_set_membership4(handle, &addr4, interface_addr, membership); - else if (uv_ip6_addr(multicast_addr, 0, &addr6) == 0) - return uv__udp_set_membership6(handle, &addr6, interface_addr, membership); - else - return UV_EINVAL; -} - - -int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) { - struct sockaddr_storage addr_st; - struct sockaddr_in* addr4; - struct sockaddr_in6* addr6; - - addr4 = (struct sockaddr_in*) &addr_st; - addr6 = (struct sockaddr_in6*) &addr_st; - - if (!interface_addr) { - memset(&addr_st, 0, sizeof addr_st); - if (handle->flags & UV_HANDLE_IPV6) { - addr_st.ss_family = AF_INET6; - addr6->sin6_scope_id = 0; - } else { - addr_st.ss_family = AF_INET; - addr4->sin_addr.s_addr = htonl(INADDR_ANY); - } - } else if (uv_ip4_addr(interface_addr, 0, addr4) == 0) { - /* nothing, address was parsed */ - } else if (uv_ip6_addr(interface_addr, 0, addr6) == 0) { - /* nothing, address was parsed */ - } else { - return UV_EINVAL; - } - - if (!(handle->flags & UV_HANDLE_BOUND)) - return UV_EBADF; - - if (addr_st.ss_family == AF_INET) { - if (setsockopt(handle->socket, - IPPROTO_IP, - IP_MULTICAST_IF, - (char*) &addr4->sin_addr, - sizeof(addr4->sin_addr)) == SOCKET_ERROR) { - return uv_translate_sys_error(WSAGetLastError()); - } - } else if (addr_st.ss_family == AF_INET6) { - if (setsockopt(handle->socket, - IPPROTO_IPV6, - IPV6_MULTICAST_IF, - (char*) &addr6->sin6_scope_id, - sizeof(addr6->sin6_scope_id)) == SOCKET_ERROR) { - return uv_translate_sys_error(WSAGetLastError()); - } - } else { - assert(0 && "unexpected address family"); - abort(); - } - - return 0; -} - - -int uv_udp_set_broadcast(uv_udp_t* handle, int value) { - BOOL optval = (BOOL) value; - - if (!(handle->flags & UV_HANDLE_BOUND)) - return UV_EBADF; - - if (setsockopt(handle->socket, - SOL_SOCKET, - SO_BROADCAST, - (char*) &optval, - sizeof optval)) { - return uv_translate_sys_error(WSAGetLastError()); - } - - return 0; -} - - -int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) { - WSAPROTOCOL_INFOW protocol_info; - int opt_len; - int err; - - /* Detect the address family of the socket. */ - opt_len = (int) sizeof protocol_info; - if (getsockopt(sock, - SOL_SOCKET, - SO_PROTOCOL_INFOW, - (char*) &protocol_info, - &opt_len) == SOCKET_ERROR) { - return uv_translate_sys_error(GetLastError()); - } - - err = uv_udp_set_socket(handle->loop, - handle, - sock, - protocol_info.iAddressFamily); - return uv_translate_sys_error(err); -} - - -#define SOCKOPT_SETTER(name, option4, option6, validate) \ - int uv_udp_set_##name(uv_udp_t* handle, int value) { \ - DWORD optval = (DWORD) value; \ - \ - if (!(validate(value))) { \ - return UV_EINVAL; \ - } \ - \ - if (!(handle->flags & UV_HANDLE_BOUND)) \ - return UV_EBADF; \ - \ - if (!(handle->flags & UV_HANDLE_IPV6)) { \ - /* Set IPv4 socket option */ \ - if (setsockopt(handle->socket, \ - IPPROTO_IP, \ - option4, \ - (char*) &optval, \ - sizeof optval)) { \ - return uv_translate_sys_error(WSAGetLastError()); \ - } \ - } else { \ - /* Set IPv6 socket option */ \ - if (setsockopt(handle->socket, \ - IPPROTO_IPV6, \ - option6, \ - (char*) &optval, \ - sizeof optval)) { \ - return uv_translate_sys_error(WSAGetLastError()); \ - } \ - } \ - return 0; \ - } - -#define VALIDATE_TTL(value) ((value) >= 1 && (value) <= 255) -#define VALIDATE_MULTICAST_TTL(value) ((value) >= -1 && (value) <= 255) -#define VALIDATE_MULTICAST_LOOP(value) (1) - -SOCKOPT_SETTER(ttl, - IP_TTL, - IPV6_HOPLIMIT, - VALIDATE_TTL) -SOCKOPT_SETTER(multicast_ttl, - IP_MULTICAST_TTL, - IPV6_MULTICAST_HOPS, - VALIDATE_MULTICAST_TTL) -SOCKOPT_SETTER(multicast_loop, - IP_MULTICAST_LOOP, - IPV6_MULTICAST_LOOP, - VALIDATE_MULTICAST_LOOP) - -#undef SOCKOPT_SETTER -#undef VALIDATE_TTL -#undef VALIDATE_MULTICAST_TTL -#undef VALIDATE_MULTICAST_LOOP - - -/* This function is an egress point, i.e. it returns libuv errors rather than - * system errors. - */ -int uv__udp_bind(uv_udp_t* handle, - const struct sockaddr* addr, - unsigned int addrlen, - unsigned int flags) { - int err; - - err = uv_udp_maybe_bind(handle, addr, addrlen, flags); - if (err) - return uv_translate_sys_error(err); - - return 0; -} - - -/* This function is an egress point, i.e. it returns libuv errors rather than - * system errors. - */ -int uv__udp_send(uv_udp_send_t* req, - uv_udp_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - const struct sockaddr* addr, - unsigned int addrlen, - uv_udp_send_cb send_cb) { - const struct sockaddr* bind_addr; - int err; - - if (!(handle->flags & UV_HANDLE_BOUND)) { - if (addrlen == sizeof(uv_addr_ip4_any_)) { - bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_; - } else if (addrlen == sizeof(uv_addr_ip6_any_)) { - bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_; - } else { - abort(); - } - err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0); - if (err) - return uv_translate_sys_error(err); - } - - err = uv__send(req, handle, bufs, nbufs, addr, addrlen, send_cb); - if (err) - return uv_translate_sys_error(err); - - return 0; -} - - -int uv__udp_try_send(uv_udp_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - const struct sockaddr* addr, - unsigned int addrlen) { - return UV_ENOSYS; -} diff --git a/libuv/src/win/util.c b/libuv/src/win/util.c deleted file mode 100644 index 43d843f..0000000 --- a/libuv/src/win/util.c +++ /dev/null @@ -1,1156 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include -#include -#include - - -/* - * Max title length; the only thing MSDN tells us about the maximum length - * of the console title is that it is smaller than 64K. However in practice - * it is much smaller, and there is no way to figure out what the exact length - * of the title is or can be, at least not on XP. To make it even more - * annoying, GetConsoleTitle fails when the buffer to be read into is bigger - * than the actual maximum length. So we make a conservative guess here; - * just don't put the novel you're writing in the title, unless the plot - * survives truncation. - */ -#define MAX_TITLE_LENGTH 8192 - -/* The number of nanoseconds in one second. */ -#define UV__NANOSEC 1000000000 - - -/* Cached copy of the process title, plus a mutex guarding it. */ -static char *process_title; -static CRITICAL_SECTION process_title_lock; - -/* Interval (in seconds) of the high-resolution clock. */ -static double hrtime_interval_ = 0; - - -/* - * One-time initialization code for functionality defined in util.c. - */ -void uv__util_init() { - LARGE_INTEGER perf_frequency; - - /* Initialize process title access mutex. */ - InitializeCriticalSection(&process_title_lock); - - /* Retrieve high-resolution timer frequency - * and precompute its reciprocal. - */ - if (QueryPerformanceFrequency(&perf_frequency)) { - hrtime_interval_ = 1.0 / perf_frequency.QuadPart; - } else { - hrtime_interval_= 0; - } -} - - -int uv_utf16_to_utf8(const WCHAR* utf16Buffer, size_t utf16Size, - char* utf8Buffer, size_t utf8Size) { - return WideCharToMultiByte(CP_UTF8, - 0, - utf16Buffer, - utf16Size, - utf8Buffer, - utf8Size, - NULL, - NULL); -} - - -int uv_utf8_to_utf16(const char* utf8Buffer, WCHAR* utf16Buffer, - size_t utf16Size) { - return MultiByteToWideChar(CP_UTF8, - 0, - utf8Buffer, - -1, - utf16Buffer, - utf16Size); -} - - -int uv_exepath(char* buffer, size_t* size_ptr) { - int utf8_len, utf16_buffer_len, utf16_len; - WCHAR* utf16_buffer; - int err; - - if (buffer == NULL || size_ptr == NULL || *size_ptr == 0) { - return UV_EINVAL; - } - - if (*size_ptr > 32768) { - /* Windows paths can never be longer than this. */ - utf16_buffer_len = 32768; - } else { - utf16_buffer_len = (int) *size_ptr; - } - - utf16_buffer = (WCHAR*) malloc(sizeof(WCHAR) * utf16_buffer_len); - if (!utf16_buffer) { - return UV_ENOMEM; - } - - /* Get the path as UTF-16. */ - utf16_len = GetModuleFileNameW(NULL, utf16_buffer, utf16_buffer_len); - if (utf16_len <= 0) { - err = GetLastError(); - goto error; - } - - /* utf16_len contains the length, *not* including the terminating null. */ - utf16_buffer[utf16_len] = L'\0'; - - /* Convert to UTF-8 */ - utf8_len = WideCharToMultiByte(CP_UTF8, - 0, - utf16_buffer, - -1, - buffer, - *size_ptr > INT_MAX ? INT_MAX : (int) *size_ptr, - NULL, - NULL); - if (utf8_len == 0) { - err = GetLastError(); - goto error; - } - - free(utf16_buffer); - - /* utf8_len *does* include the terminating null at this point, but the */ - /* returned size shouldn't. */ - *size_ptr = utf8_len - 1; - return 0; - - error: - free(utf16_buffer); - return uv_translate_sys_error(err); -} - - -int uv_cwd(char* buffer, size_t* size) { - DWORD utf16_len; - WCHAR utf16_buffer[MAX_PATH]; - int r; - - if (buffer == NULL || size == NULL) { - return UV_EINVAL; - } - - utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer); - if (utf16_len == 0) { - return uv_translate_sys_error(GetLastError()); - } else if (utf16_len > MAX_PATH) { - /* This should be impossible; however the CRT has a code path to deal */ - /* with this scenario, so I added a check anyway. */ - return UV_EIO; - } - - /* utf16_len contains the length, *not* including the terminating null. */ - utf16_buffer[utf16_len] = L'\0'; - - /* The returned directory should not have a trailing slash, unless it */ - /* points at a drive root, like c:\. Remove it if needed.*/ - if (utf16_buffer[utf16_len - 1] == L'\\' && - !(utf16_len == 3 && utf16_buffer[1] == L':')) { - utf16_len--; - utf16_buffer[utf16_len] = L'\0'; - } - - /* Check how much space we need */ - r = WideCharToMultiByte(CP_UTF8, - 0, - utf16_buffer, - -1, - NULL, - 0, - NULL, - NULL); - if (r == 0) { - return uv_translate_sys_error(GetLastError()); - } else if (r > (int) *size) { - *size = r -1; - return UV_ENOBUFS; - } - - /* Convert to UTF-8 */ - r = WideCharToMultiByte(CP_UTF8, - 0, - utf16_buffer, - -1, - buffer, - *size > INT_MAX ? INT_MAX : (int) *size, - NULL, - NULL); - if (r == 0) { - return uv_translate_sys_error(GetLastError()); - } - - *size = r - 1; - return 0; -} - - -int uv_chdir(const char* dir) { - WCHAR utf16_buffer[MAX_PATH]; - size_t utf16_len; - WCHAR drive_letter, env_var[4]; - - if (dir == NULL) { - return UV_EINVAL; - } - - if (MultiByteToWideChar(CP_UTF8, - 0, - dir, - -1, - utf16_buffer, - MAX_PATH) == 0) { - DWORD error = GetLastError(); - /* The maximum length of the current working directory is 260 chars, */ - /* including terminating null. If it doesn't fit, the path name must be */ - /* too long. */ - if (error == ERROR_INSUFFICIENT_BUFFER) { - return UV_ENAMETOOLONG; - } else { - return uv_translate_sys_error(error); - } - } - - if (!SetCurrentDirectoryW(utf16_buffer)) { - return uv_translate_sys_error(GetLastError()); - } - - /* Windows stores the drive-local path in an "hidden" environment variable, */ - /* which has the form "=C:=C:\Windows". SetCurrentDirectory does not */ - /* update this, so we'll have to do it. */ - utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer); - if (utf16_len == 0) { - return uv_translate_sys_error(GetLastError()); - } else if (utf16_len > MAX_PATH) { - return UV_EIO; - } - - /* The returned directory should not have a trailing slash, unless it */ - /* points at a drive root, like c:\. Remove it if needed. */ - if (utf16_buffer[utf16_len - 1] == L'\\' && - !(utf16_len == 3 && utf16_buffer[1] == L':')) { - utf16_len--; - utf16_buffer[utf16_len] = L'\0'; - } - - if (utf16_len < 2 || utf16_buffer[1] != L':') { - /* Doesn't look like a drive letter could be there - probably an UNC */ - /* path. TODO: Need to handle win32 namespaces like \\?\C:\ ? */ - drive_letter = 0; - } else if (utf16_buffer[0] >= L'A' && utf16_buffer[0] <= L'Z') { - drive_letter = utf16_buffer[0]; - } else if (utf16_buffer[0] >= L'a' && utf16_buffer[0] <= L'z') { - /* Convert to uppercase. */ - drive_letter = utf16_buffer[0] - L'a' + L'A'; - } else { - /* Not valid. */ - drive_letter = 0; - } - - if (drive_letter != 0) { - /* Construct the environment variable name and set it. */ - env_var[0] = L'='; - env_var[1] = drive_letter; - env_var[2] = L':'; - env_var[3] = L'\0'; - - if (!SetEnvironmentVariableW(env_var, utf16_buffer)) { - return uv_translate_sys_error(GetLastError()); - } - } - - return 0; -} - - -void uv_loadavg(double avg[3]) { - /* Can't be implemented */ - avg[0] = avg[1] = avg[2] = 0; -} - - -uint64_t uv_get_free_memory(void) { - MEMORYSTATUSEX memory_status; - memory_status.dwLength = sizeof(memory_status); - - if (!GlobalMemoryStatusEx(&memory_status)) { - return -1; - } - - return (uint64_t)memory_status.ullAvailPhys; -} - - -uint64_t uv_get_total_memory(void) { - MEMORYSTATUSEX memory_status; - memory_status.dwLength = sizeof(memory_status); - - if (!GlobalMemoryStatusEx(&memory_status)) { - return -1; - } - - return (uint64_t)memory_status.ullTotalPhys; -} - - -int uv_parent_pid() { - int parent_pid = -1; - HANDLE handle; - PROCESSENTRY32 pe; - DWORD current_pid = GetCurrentProcessId(); - - pe.dwSize = sizeof(PROCESSENTRY32); - handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - - if (Process32First(handle, &pe)) { - do { - if (pe.th32ProcessID == current_pid) { - parent_pid = pe.th32ParentProcessID; - break; - } - } while( Process32Next(handle, &pe)); - } - - CloseHandle(handle); - return parent_pid; -} - - -char** uv_setup_args(int argc, char** argv) { - return argv; -} - - -int uv_set_process_title(const char* title) { - int err; - int length; - WCHAR* title_w = NULL; - - uv__once_init(); - - /* Find out how big the buffer for the wide-char title must be */ - length = uv_utf8_to_utf16(title, NULL, 0); - if (!length) { - err = GetLastError(); - goto done; - } - - /* Convert to wide-char string */ - title_w = (WCHAR*)malloc(sizeof(WCHAR) * length); - if (!title_w) { - uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); - } - - length = uv_utf8_to_utf16(title, title_w, length); - if (!length) { - err = GetLastError(); - goto done; - } - - /* If the title must be truncated insert a \0 terminator there */ - if (length > MAX_TITLE_LENGTH) { - title_w[MAX_TITLE_LENGTH - 1] = L'\0'; - } - - if (!SetConsoleTitleW(title_w)) { - err = GetLastError(); - goto done; - } - - EnterCriticalSection(&process_title_lock); - free(process_title); - process_title = strdup(title); - LeaveCriticalSection(&process_title_lock); - - err = 0; - -done: - free(title_w); - return uv_translate_sys_error(err); -} - - -static int uv__get_process_title() { - WCHAR title_w[MAX_TITLE_LENGTH]; - int length; - - if (!GetConsoleTitleW(title_w, sizeof(title_w) / sizeof(WCHAR))) { - return -1; - } - - /* Find out what the size of the buffer is that we need */ - length = uv_utf16_to_utf8(title_w, -1, NULL, 0); - if (!length) { - return -1; - } - - assert(!process_title); - process_title = (char*)malloc(length); - if (!process_title) { - uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); - } - - /* Do utf16 -> utf8 conversion here */ - if (!uv_utf16_to_utf8(title_w, -1, process_title, length)) { - free(process_title); - return -1; - } - - return 0; -} - - -int uv_get_process_title(char* buffer, size_t size) { - uv__once_init(); - - EnterCriticalSection(&process_title_lock); - /* - * If the process_title was never read before nor explicitly set, - * we must query it with getConsoleTitleW - */ - if (!process_title && uv__get_process_title() == -1) { - LeaveCriticalSection(&process_title_lock); - return uv_translate_sys_error(GetLastError()); - } - - assert(process_title); - strncpy(buffer, process_title, size); - LeaveCriticalSection(&process_title_lock); - - return 0; -} - - -uint64_t uv_hrtime(void) { - uv__once_init(); - return uv__hrtime(UV__NANOSEC); -} - -uint64_t uv__hrtime(double scale) { - LARGE_INTEGER counter; - - /* If the performance interval is zero, there's no support. */ - if (hrtime_interval_ == 0) { - return 0; - } - - if (!QueryPerformanceCounter(&counter)) { - return 0; - } - - /* Because we have no guarantee about the order of magnitude of the - * performance counter interval, integer math could cause this computation - * to overflow. Therefore we resort to floating point math. - */ - return (uint64_t) ((double) counter.QuadPart * hrtime_interval_ * scale); -} - - -int uv_resident_set_memory(size_t* rss) { - HANDLE current_process; - PROCESS_MEMORY_COUNTERS pmc; - - current_process = GetCurrentProcess(); - - if (!GetProcessMemoryInfo(current_process, &pmc, sizeof(pmc))) { - return uv_translate_sys_error(GetLastError()); - } - - *rss = pmc.WorkingSetSize; - - return 0; -} - - -int uv_uptime(double* uptime) { - BYTE stack_buffer[4096]; - BYTE* malloced_buffer = NULL; - BYTE* buffer = (BYTE*) stack_buffer; - size_t buffer_size = sizeof(stack_buffer); - DWORD data_size; - - PERF_DATA_BLOCK* data_block; - PERF_OBJECT_TYPE* object_type; - PERF_COUNTER_DEFINITION* counter_definition; - - DWORD i; - - for (;;) { - LONG result; - - data_size = (DWORD) buffer_size; - result = RegQueryValueExW(HKEY_PERFORMANCE_DATA, - L"2", - NULL, - NULL, - buffer, - &data_size); - if (result == ERROR_SUCCESS) { - break; - } else if (result != ERROR_MORE_DATA) { - *uptime = 0; - return uv_translate_sys_error(result); - } - - free(malloced_buffer); - - buffer_size *= 2; - /* Don't let the buffer grow infinitely. */ - if (buffer_size > 1 << 20) { - goto internalError; - } - - buffer = malloced_buffer = (BYTE*) malloc(buffer_size); - if (malloced_buffer == NULL) { - *uptime = 0; - return UV_ENOMEM; - } - } - - if (data_size < sizeof(*data_block)) - goto internalError; - - data_block = (PERF_DATA_BLOCK*) buffer; - - if (wmemcmp(data_block->Signature, L"PERF", 4) != 0) - goto internalError; - - if (data_size < data_block->HeaderLength + sizeof(*object_type)) - goto internalError; - - object_type = (PERF_OBJECT_TYPE*) (buffer + data_block->HeaderLength); - - if (object_type->NumInstances != PERF_NO_INSTANCES) - goto internalError; - - counter_definition = (PERF_COUNTER_DEFINITION*) (buffer + - data_block->HeaderLength + object_type->HeaderLength); - for (i = 0; i < object_type->NumCounters; i++) { - if ((BYTE*) counter_definition + sizeof(*counter_definition) > - buffer + data_size) { - break; - } - - if (counter_definition->CounterNameTitleIndex == 674 && - counter_definition->CounterSize == sizeof(uint64_t)) { - if (counter_definition->CounterOffset + sizeof(uint64_t) > data_size || - !(counter_definition->CounterType & PERF_OBJECT_TIMER)) { - goto internalError; - } else { - BYTE* address = (BYTE*) object_type + object_type->DefinitionLength + - counter_definition->CounterOffset; - uint64_t value = *((uint64_t*) address); - *uptime = (double) (object_type->PerfTime.QuadPart - value) / - (double) object_type->PerfFreq.QuadPart; - free(malloced_buffer); - return 0; - } - } - - counter_definition = (PERF_COUNTER_DEFINITION*) - ((BYTE*) counter_definition + counter_definition->ByteLength); - } - - /* If we get here, the uptime value was not found. */ - free(malloced_buffer); - *uptime = 0; - return UV_ENOSYS; - - internalError: - free(malloced_buffer); - *uptime = 0; - return UV_EIO; -} - - -int uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) { - uv_cpu_info_t* cpu_infos; - SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* sppi; - DWORD sppi_size; - SYSTEM_INFO system_info; - DWORD cpu_count, r, i; - NTSTATUS status; - ULONG result_size; - int err; - uv_cpu_info_t* cpu_info; - - cpu_infos = NULL; - cpu_count = 0; - sppi = NULL; - - uv__once_init(); - - GetSystemInfo(&system_info); - cpu_count = system_info.dwNumberOfProcessors; - - cpu_infos = calloc(cpu_count, sizeof *cpu_infos); - if (cpu_infos == NULL) { - err = ERROR_OUTOFMEMORY; - goto error; - } - - sppi_size = cpu_count * sizeof(*sppi); - sppi = malloc(sppi_size); - if (sppi == NULL) { - err = ERROR_OUTOFMEMORY; - goto error; - } - - status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, - sppi, - sppi_size, - &result_size); - if (!NT_SUCCESS(status)) { - err = pRtlNtStatusToDosError(status); - goto error; - } - - assert(result_size == sppi_size); - - for (i = 0; i < cpu_count; i++) { - WCHAR key_name[128]; - HKEY processor_key; - DWORD cpu_speed; - DWORD cpu_speed_size = sizeof(cpu_speed); - WCHAR cpu_brand[256]; - DWORD cpu_brand_size = sizeof(cpu_brand); - size_t len; - - len = _snwprintf(key_name, - ARRAY_SIZE(key_name), - L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\%d", - i); - - assert(len > 0 && len < ARRAY_SIZE(key_name)); - - r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, - key_name, - 0, - KEY_QUERY_VALUE, - &processor_key); - if (r != ERROR_SUCCESS) { - err = GetLastError(); - goto error; - } - - if (RegQueryValueExW(processor_key, - L"~MHz", - NULL, - NULL, - (BYTE*) &cpu_speed, - &cpu_speed_size) != ERROR_SUCCESS) { - err = GetLastError(); - RegCloseKey(processor_key); - goto error; - } - - if (RegQueryValueExW(processor_key, - L"ProcessorNameString", - NULL, - NULL, - (BYTE*) &cpu_brand, - &cpu_brand_size) != ERROR_SUCCESS) { - err = GetLastError(); - RegCloseKey(processor_key); - goto error; - } - - RegCloseKey(processor_key); - - cpu_info = &cpu_infos[i]; - cpu_info->speed = cpu_speed; - cpu_info->cpu_times.user = sppi[i].UserTime.QuadPart / 10000; - cpu_info->cpu_times.sys = (sppi[i].KernelTime.QuadPart - - sppi[i].IdleTime.QuadPart) / 10000; - cpu_info->cpu_times.idle = sppi[i].IdleTime.QuadPart / 10000; - cpu_info->cpu_times.irq = sppi[i].InterruptTime.QuadPart / 10000; - cpu_info->cpu_times.nice = 0; - - - len = WideCharToMultiByte(CP_UTF8, - 0, - cpu_brand, - cpu_brand_size / sizeof(WCHAR), - NULL, - 0, - NULL, - NULL); - if (len == 0) { - err = GetLastError(); - goto error; - } - - assert(len > 0); - - /* Allocate 1 extra byte for the null terminator. */ - cpu_info->model = malloc(len + 1); - if (cpu_info->model == NULL) { - err = ERROR_OUTOFMEMORY; - goto error; - } - - if (WideCharToMultiByte(CP_UTF8, - 0, - cpu_brand, - cpu_brand_size / sizeof(WCHAR), - cpu_info->model, - len, - NULL, - NULL) == 0) { - err = GetLastError(); - goto error; - } - - /* Ensure that cpu_info->model is null terminated. */ - cpu_info->model[len] = '\0'; - } - - free(sppi); - - *cpu_count_ptr = cpu_count; - *cpu_infos_ptr = cpu_infos; - - return 0; - - error: - /* This is safe because the cpu_infos array is zeroed on allocation. */ - for (i = 0; i < cpu_count; i++) - free(cpu_infos[i].model); - - free(cpu_infos); - free(sppi); - - return uv_translate_sys_error(err); -} - - -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - int i; - - for (i = 0; i < count; i++) { - free(cpu_infos[i].model); - } - - free(cpu_infos); -} - - -static int is_windows_version_or_greater(DWORD os_major, - DWORD os_minor, - WORD service_pack_major, - WORD service_pack_minor) { - OSVERSIONINFOEX osvi; - DWORDLONG condition_mask = 0; - int op = VER_GREATER_EQUAL; - - /* Initialize the OSVERSIONINFOEX structure. */ - ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - osvi.dwMajorVersion = os_major; - osvi.dwMinorVersion = os_minor; - osvi.wServicePackMajor = service_pack_major; - osvi.wServicePackMinor = service_pack_minor; - - /* Initialize the condition mask. */ - VER_SET_CONDITION(condition_mask, VER_MAJORVERSION, op); - VER_SET_CONDITION(condition_mask, VER_MINORVERSION, op); - VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMAJOR, op); - VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMINOR, op); - - /* Perform the test. */ - return (int) VerifyVersionInfo( - &osvi, - VER_MAJORVERSION | VER_MINORVERSION | - VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR, - condition_mask); -} - - -static int address_prefix_match(int family, - struct sockaddr* address, - struct sockaddr* prefix_address, - int prefix_len) { - uint8_t* address_data; - uint8_t* prefix_address_data; - int i; - - assert(address->sa_family == family); - assert(prefix_address->sa_family == family); - - if (family == AF_INET6) { - address_data = (uint8_t*) &(((struct sockaddr_in6 *) address)->sin6_addr); - prefix_address_data = - (uint8_t*) &(((struct sockaddr_in6 *) prefix_address)->sin6_addr); - } else { - address_data = (uint8_t*) &(((struct sockaddr_in *) address)->sin_addr); - prefix_address_data = - (uint8_t*) &(((struct sockaddr_in *) prefix_address)->sin_addr); - } - - for (i = 0; i < prefix_len >> 3; i++) { - if (address_data[i] != prefix_address_data[i]) - return 0; - } - - if (prefix_len % 8) - return prefix_address_data[i] == - (address_data[i] & (0xff << (8 - prefix_len % 8))); - - return 1; -} - - -int uv_interface_addresses(uv_interface_address_t** addresses_ptr, - int* count_ptr) { - IP_ADAPTER_ADDRESSES* win_address_buf; - ULONG win_address_buf_size; - IP_ADAPTER_ADDRESSES* adapter; - - uv_interface_address_t* uv_address_buf; - char* name_buf; - size_t uv_address_buf_size; - uv_interface_address_t* uv_address; - - int count; - - int is_vista_or_greater; - ULONG flags; - - is_vista_or_greater = is_windows_version_or_greater(6, 0, 0, 0); - if (is_vista_or_greater) { - flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | - GAA_FLAG_SKIP_DNS_SERVER; - } else { - /* We need at least XP SP1. */ - if (!is_windows_version_or_greater(5, 1, 1, 0)) - return UV_ENOTSUP; - - flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | - GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_PREFIX; - } - - - /* Fetch the size of the adapters reported by windows, and then get the */ - /* list itself. */ - win_address_buf_size = 0; - win_address_buf = NULL; - - for (;;) { - ULONG r; - - /* If win_address_buf is 0, then GetAdaptersAddresses will fail with */ - /* ERROR_BUFFER_OVERFLOW, and the required buffer size will be stored in */ - /* win_address_buf_size. */ - r = GetAdaptersAddresses(AF_UNSPEC, - flags, - NULL, - win_address_buf, - &win_address_buf_size); - - if (r == ERROR_SUCCESS) - break; - - free(win_address_buf); - - switch (r) { - case ERROR_BUFFER_OVERFLOW: - /* This happens when win_address_buf is NULL or too small to hold */ - /* all adapters. */ - win_address_buf = malloc(win_address_buf_size); - if (win_address_buf == NULL) - return UV_ENOMEM; - - continue; - - case ERROR_NO_DATA: { - /* No adapters were found. */ - uv_address_buf = malloc(1); - if (uv_address_buf == NULL) - return UV_ENOMEM; - - *count_ptr = 0; - *addresses_ptr = uv_address_buf; - - return 0; - } - - case ERROR_ADDRESS_NOT_ASSOCIATED: - return UV_EAGAIN; - - case ERROR_INVALID_PARAMETER: - /* MSDN says: - * "This error is returned for any of the following conditions: the - * SizePointer parameter is NULL, the Address parameter is not - * AF_INET, AF_INET6, or AF_UNSPEC, or the address information for - * the parameters requested is greater than ULONG_MAX." - * Since the first two conditions are not met, it must be that the - * adapter data is too big. - */ - return UV_ENOBUFS; - - default: - /* Other (unspecified) errors can happen, but we don't have any */ - /* special meaning for them. */ - assert(r != ERROR_SUCCESS); - return uv_translate_sys_error(r); - } - } - - /* Count the number of enabled interfaces and compute how much space is */ - /* needed to store their info. */ - count = 0; - uv_address_buf_size = 0; - - for (adapter = win_address_buf; - adapter != NULL; - adapter = adapter->Next) { - IP_ADAPTER_UNICAST_ADDRESS* unicast_address; - int name_size; - - /* Interfaces that are not 'up' should not be reported. Also skip */ - /* interfaces that have no associated unicast address, as to avoid */ - /* allocating space for the name for this interface. */ - if (adapter->OperStatus != IfOperStatusUp || - adapter->FirstUnicastAddress == NULL) - continue; - - /* Compute the size of the interface name. */ - name_size = WideCharToMultiByte(CP_UTF8, - 0, - adapter->FriendlyName, - -1, - NULL, - 0, - NULL, - FALSE); - if (name_size <= 0) { - free(win_address_buf); - return uv_translate_sys_error(GetLastError()); - } - uv_address_buf_size += name_size; - - /* Count the number of addresses associated with this interface, and */ - /* compute the size. */ - for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS*) - adapter->FirstUnicastAddress; - unicast_address != NULL; - unicast_address = unicast_address->Next) { - count++; - uv_address_buf_size += sizeof(uv_interface_address_t); - } - } - - /* Allocate space to store interface data plus adapter names. */ - uv_address_buf = malloc(uv_address_buf_size); - if (uv_address_buf == NULL) { - free(win_address_buf); - return UV_ENOMEM; - } - - /* Compute the start of the uv_interface_address_t array, and the place in */ - /* the buffer where the interface names will be stored. */ - uv_address = uv_address_buf; - name_buf = (char*) (uv_address_buf + count); - - /* Fill out the output buffer. */ - for (adapter = win_address_buf; - adapter != NULL; - adapter = adapter->Next) { - IP_ADAPTER_UNICAST_ADDRESS* unicast_address; - int name_size; - size_t max_name_size; - - if (adapter->OperStatus != IfOperStatusUp || - adapter->FirstUnicastAddress == NULL) - continue; - - /* Convert the interface name to UTF8. */ - max_name_size = (char*) uv_address_buf + uv_address_buf_size - name_buf; - if (max_name_size > (size_t) INT_MAX) - max_name_size = INT_MAX; - name_size = WideCharToMultiByte(CP_UTF8, - 0, - adapter->FriendlyName, - -1, - name_buf, - (int) max_name_size, - NULL, - FALSE); - if (name_size <= 0) { - free(win_address_buf); - free(uv_address_buf); - return uv_translate_sys_error(GetLastError()); - } - - /* Add an uv_interface_address_t element for every unicast address. */ - for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS*) - adapter->FirstUnicastAddress; - unicast_address != NULL; - unicast_address = unicast_address->Next) { - struct sockaddr* sa; - ULONG prefix_len; - - sa = unicast_address->Address.lpSockaddr; - - /* XP has no OnLinkPrefixLength field. */ - if (is_vista_or_greater) { - prefix_len = - ((IP_ADAPTER_UNICAST_ADDRESS_LH*) unicast_address)->OnLinkPrefixLength; - } else { - /* Prior to Windows Vista the FirstPrefix pointed to the list with - * single prefix for each IP address assigned to the adapter. - * Order of FirstPrefix does not match order of FirstUnicastAddress, - * so we need to find corresponding prefix. - */ - IP_ADAPTER_PREFIX* prefix; - prefix_len = 0; - - for (prefix = adapter->FirstPrefix; prefix; prefix = prefix->Next) { - /* We want the longest matching prefix. */ - if (prefix->Address.lpSockaddr->sa_family != sa->sa_family || - prefix->PrefixLength <= prefix_len) - continue; - - if (address_prefix_match(sa->sa_family, sa, - prefix->Address.lpSockaddr, prefix->PrefixLength)) { - prefix_len = prefix->PrefixLength; - } - } - - /* If there is no matching prefix information, return a single-host - * subnet mask (e.g. 255.255.255.255 for IPv4). - */ - if (!prefix_len) - prefix_len = (sa->sa_family == AF_INET6) ? 128 : 32; - } - - memset(uv_address, 0, sizeof *uv_address); - - uv_address->name = name_buf; - - if (adapter->PhysicalAddressLength == sizeof(uv_address->phys_addr)) { - memcpy(uv_address->phys_addr, - adapter->PhysicalAddress, - sizeof(uv_address->phys_addr)); - } - - uv_address->is_internal = - (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK); - - if (sa->sa_family == AF_INET6) { - uv_address->address.address6 = *((struct sockaddr_in6 *) sa); - - uv_address->netmask.netmask6.sin6_family = AF_INET6; - memset(uv_address->netmask.netmask6.sin6_addr.s6_addr, 0xff, prefix_len >> 3); - /* This check ensures that we don't write past the size of the data. */ - if (prefix_len % 8) { - uv_address->netmask.netmask6.sin6_addr.s6_addr[prefix_len >> 3] = - 0xff << (8 - prefix_len % 8); - } - - } else { - uv_address->address.address4 = *((struct sockaddr_in *) sa); - - uv_address->netmask.netmask4.sin_family = AF_INET; - uv_address->netmask.netmask4.sin_addr.s_addr = (prefix_len > 0) ? - htonl(0xffffffff << (32 - prefix_len)) : 0; - } - - uv_address++; - } - - name_buf += name_size; - } - - free(win_address_buf); - - *addresses_ptr = uv_address_buf; - *count_ptr = count; - - return 0; -} - - -void uv_free_interface_addresses(uv_interface_address_t* addresses, - int count) { - free(addresses); -} - - -int uv_getrusage(uv_rusage_t *uv_rusage) { - FILETIME createTime, exitTime, kernelTime, userTime; - SYSTEMTIME kernelSystemTime, userSystemTime; - int ret; - - ret = GetProcessTimes(GetCurrentProcess(), &createTime, &exitTime, &kernelTime, &userTime); - if (ret == 0) { - return uv_translate_sys_error(GetLastError()); - } - - ret = FileTimeToSystemTime(&kernelTime, &kernelSystemTime); - if (ret == 0) { - return uv_translate_sys_error(GetLastError()); - } - - ret = FileTimeToSystemTime(&userTime, &userSystemTime); - if (ret == 0) { - return uv_translate_sys_error(GetLastError()); - } - - memset(uv_rusage, 0, sizeof(*uv_rusage)); - - uv_rusage->ru_utime.tv_sec = userSystemTime.wHour * 3600 + - userSystemTime.wMinute * 60 + - userSystemTime.wSecond; - uv_rusage->ru_utime.tv_usec = userSystemTime.wMilliseconds * 1000; - - uv_rusage->ru_stime.tv_sec = kernelSystemTime.wHour * 3600 + - kernelSystemTime.wMinute * 60 + - kernelSystemTime.wSecond; - uv_rusage->ru_stime.tv_usec = kernelSystemTime.wMilliseconds * 1000; - - return 0; -} diff --git a/libuv/src/win/winapi.c b/libuv/src/win/winapi.c deleted file mode 100644 index f3f27f7..0000000 --- a/libuv/src/win/winapi.c +++ /dev/null @@ -1,170 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include - -#include "uv.h" -#include "internal.h" - - -/* Ntdll function pointers */ -sRtlNtStatusToDosError pRtlNtStatusToDosError; -sNtDeviceIoControlFile pNtDeviceIoControlFile; -sNtQueryInformationFile pNtQueryInformationFile; -sNtSetInformationFile pNtSetInformationFile; -sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile; -sNtQueryDirectoryFile pNtQueryDirectoryFile; -sNtQuerySystemInformation pNtQuerySystemInformation; - - -/* Kernel32 function pointers */ -sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx; -sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes; -sCreateSymbolicLinkW pCreateSymbolicLinkW; -sCancelIoEx pCancelIoEx; -sInitializeSRWLock pInitializeSRWLock; -sAcquireSRWLockShared pAcquireSRWLockShared; -sAcquireSRWLockExclusive pAcquireSRWLockExclusive; -sTryAcquireSRWLockShared pTryAcquireSRWLockShared; -sTryAcquireSRWLockExclusive pTryAcquireSRWLockExclusive; -sReleaseSRWLockShared pReleaseSRWLockShared; -sReleaseSRWLockExclusive pReleaseSRWLockExclusive; -sInitializeConditionVariable pInitializeConditionVariable; -sSleepConditionVariableCS pSleepConditionVariableCS; -sSleepConditionVariableSRW pSleepConditionVariableSRW; -sWakeAllConditionVariable pWakeAllConditionVariable; -sWakeConditionVariable pWakeConditionVariable; -sCancelSynchronousIo pCancelSynchronousIo; - - -void uv_winapi_init() { - HMODULE ntdll_module; - HMODULE kernel32_module; - - ntdll_module = GetModuleHandleA("ntdll.dll"); - if (ntdll_module == NULL) { - uv_fatal_error(GetLastError(), "GetModuleHandleA"); - } - - pRtlNtStatusToDosError = (sRtlNtStatusToDosError) GetProcAddress( - ntdll_module, - "RtlNtStatusToDosError"); - if (pRtlNtStatusToDosError == NULL) { - uv_fatal_error(GetLastError(), "GetProcAddress"); - } - - pNtDeviceIoControlFile = (sNtDeviceIoControlFile) GetProcAddress( - ntdll_module, - "NtDeviceIoControlFile"); - if (pNtDeviceIoControlFile == NULL) { - uv_fatal_error(GetLastError(), "GetProcAddress"); - } - - pNtQueryInformationFile = (sNtQueryInformationFile) GetProcAddress( - ntdll_module, - "NtQueryInformationFile"); - if (pNtQueryInformationFile == NULL) { - uv_fatal_error(GetLastError(), "GetProcAddress"); - } - - pNtSetInformationFile = (sNtSetInformationFile) GetProcAddress( - ntdll_module, - "NtSetInformationFile"); - if (pNtSetInformationFile == NULL) { - uv_fatal_error(GetLastError(), "GetProcAddress"); - } - - pNtQueryVolumeInformationFile = (sNtQueryVolumeInformationFile) - GetProcAddress(ntdll_module, "NtQueryVolumeInformationFile"); - if (pNtQueryVolumeInformationFile == NULL) { - uv_fatal_error(GetLastError(), "GetProcAddress"); - } - - pNtQueryDirectoryFile = (sNtQueryDirectoryFile) - GetProcAddress(ntdll_module, "NtQueryDirectoryFile"); - if (pNtQueryVolumeInformationFile == NULL) { - uv_fatal_error(GetLastError(), "GetProcAddress"); - } - - pNtQuerySystemInformation = (sNtQuerySystemInformation) GetProcAddress( - ntdll_module, - "NtQuerySystemInformation"); - if (pNtQuerySystemInformation == NULL) { - uv_fatal_error(GetLastError(), "GetProcAddress"); - } - - kernel32_module = GetModuleHandleA("kernel32.dll"); - if (kernel32_module == NULL) { - uv_fatal_error(GetLastError(), "GetModuleHandleA"); - } - - pGetQueuedCompletionStatusEx = (sGetQueuedCompletionStatusEx) GetProcAddress( - kernel32_module, - "GetQueuedCompletionStatusEx"); - - pSetFileCompletionNotificationModes = (sSetFileCompletionNotificationModes) - GetProcAddress(kernel32_module, "SetFileCompletionNotificationModes"); - - pCreateSymbolicLinkW = (sCreateSymbolicLinkW) - GetProcAddress(kernel32_module, "CreateSymbolicLinkW"); - - pCancelIoEx = (sCancelIoEx) - GetProcAddress(kernel32_module, "CancelIoEx"); - - pInitializeSRWLock = (sInitializeSRWLock) - GetProcAddress(kernel32_module, "InitializeSRWLock"); - - pAcquireSRWLockShared = (sAcquireSRWLockShared) - GetProcAddress(kernel32_module, "AcquireSRWLockShared"); - - pAcquireSRWLockExclusive = (sAcquireSRWLockExclusive) - GetProcAddress(kernel32_module, "AcquireSRWLockExclusive"); - - pTryAcquireSRWLockShared = (sTryAcquireSRWLockShared) - GetProcAddress(kernel32_module, "TryAcquireSRWLockShared"); - - pTryAcquireSRWLockExclusive = (sTryAcquireSRWLockExclusive) - GetProcAddress(kernel32_module, "TryAcquireSRWLockExclusive"); - - pReleaseSRWLockShared = (sReleaseSRWLockShared) - GetProcAddress(kernel32_module, "ReleaseSRWLockShared"); - - pReleaseSRWLockExclusive = (sReleaseSRWLockExclusive) - GetProcAddress(kernel32_module, "ReleaseSRWLockExclusive"); - - pInitializeConditionVariable = (sInitializeConditionVariable) - GetProcAddress(kernel32_module, "InitializeConditionVariable"); - - pSleepConditionVariableCS = (sSleepConditionVariableCS) - GetProcAddress(kernel32_module, "SleepConditionVariableCS"); - - pSleepConditionVariableSRW = (sSleepConditionVariableSRW) - GetProcAddress(kernel32_module, "SleepConditionVariableSRW"); - - pWakeAllConditionVariable = (sWakeAllConditionVariable) - GetProcAddress(kernel32_module, "WakeAllConditionVariable"); - - pWakeConditionVariable = (sWakeConditionVariable) - GetProcAddress(kernel32_module, "WakeConditionVariable"); - - pCancelSynchronousIo = (sCancelSynchronousIo) - GetProcAddress(kernel32_module, "CancelSynchronousIo"); -} diff --git a/libuv/src/win/winapi.h b/libuv/src/win/winapi.h deleted file mode 100644 index f4f9145..0000000 --- a/libuv/src/win/winapi.h +++ /dev/null @@ -1,4731 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_WIN_WINAPI_H_ -#define UV_WIN_WINAPI_H_ - -#include - - -/* - * Ntdll headers - */ -#ifndef STATUS_SEVERITY_SUCCESS -# define STATUS_SEVERITY_SUCCESS 0x0 -#endif - -#ifndef STATUS_SEVERITY_INFORMATIONAL -# define STATUS_SEVERITY_INFORMATIONAL 0x1 -#endif - -#ifndef STATUS_SEVERITY_WARNING -# define STATUS_SEVERITY_WARNING 0x2 -#endif - -#ifndef STATUS_SEVERITY_ERROR -# define STATUS_SEVERITY_ERROR 0x3 -#endif - -#ifndef FACILITY_NTWIN32 -# define FACILITY_NTWIN32 0x7 -#endif - -#ifndef NT_SUCCESS -# define NT_SUCCESS(status) (((NTSTATUS) (status)) >= 0) -#endif - -#ifndef NT_INFORMATION -# define NT_INFORMATION(status) ((((ULONG) (status)) >> 30) == 1) -#endif - -#ifndef NT_WARNING -# define NT_WARNING(status) ((((ULONG) (status)) >> 30) == 2) -#endif - -#ifndef NT_ERROR -# define NT_ERROR(status) ((((ULONG) (status)) >> 30) == 3) -#endif - -#ifndef STATUS_SUCCESS -# define STATUS_SUCCESS ((NTSTATUS) 0x00000000L) -#endif - -#ifndef STATUS_WAIT_0 -# define STATUS_WAIT_0 ((NTSTATUS) 0x00000000L) -#endif - -#ifndef STATUS_WAIT_1 -# define STATUS_WAIT_1 ((NTSTATUS) 0x00000001L) -#endif - -#ifndef STATUS_WAIT_2 -# define STATUS_WAIT_2 ((NTSTATUS) 0x00000002L) -#endif - -#ifndef STATUS_WAIT_3 -# define STATUS_WAIT_3 ((NTSTATUS) 0x00000003L) -#endif - -#ifndef STATUS_WAIT_63 -# define STATUS_WAIT_63 ((NTSTATUS) 0x0000003FL) -#endif - -#ifndef STATUS_ABANDONED -# define STATUS_ABANDONED ((NTSTATUS) 0x00000080L) -#endif - -#ifndef STATUS_ABANDONED_WAIT_0 -# define STATUS_ABANDONED_WAIT_0 ((NTSTATUS) 0x00000080L) -#endif - -#ifndef STATUS_ABANDONED_WAIT_63 -# define STATUS_ABANDONED_WAIT_63 ((NTSTATUS) 0x000000BFL) -#endif - -#ifndef STATUS_USER_APC -# define STATUS_USER_APC ((NTSTATUS) 0x000000C0L) -#endif - -#ifndef STATUS_KERNEL_APC -# define STATUS_KERNEL_APC ((NTSTATUS) 0x00000100L) -#endif - -#ifndef STATUS_ALERTED -# define STATUS_ALERTED ((NTSTATUS) 0x00000101L) -#endif - -#ifndef STATUS_TIMEOUT -# define STATUS_TIMEOUT ((NTSTATUS) 0x00000102L) -#endif - -#ifndef STATUS_PENDING -# define STATUS_PENDING ((NTSTATUS) 0x00000103L) -#endif - -#ifndef STATUS_REPARSE -# define STATUS_REPARSE ((NTSTATUS) 0x00000104L) -#endif - -#ifndef STATUS_MORE_ENTRIES -# define STATUS_MORE_ENTRIES ((NTSTATUS) 0x00000105L) -#endif - -#ifndef STATUS_NOT_ALL_ASSIGNED -# define STATUS_NOT_ALL_ASSIGNED ((NTSTATUS) 0x00000106L) -#endif - -#ifndef STATUS_SOME_NOT_MAPPED -# define STATUS_SOME_NOT_MAPPED ((NTSTATUS) 0x00000107L) -#endif - -#ifndef STATUS_OPLOCK_BREAK_IN_PROGRESS -# define STATUS_OPLOCK_BREAK_IN_PROGRESS ((NTSTATUS) 0x00000108L) -#endif - -#ifndef STATUS_VOLUME_MOUNTED -# define STATUS_VOLUME_MOUNTED ((NTSTATUS) 0x00000109L) -#endif - -#ifndef STATUS_RXACT_COMMITTED -# define STATUS_RXACT_COMMITTED ((NTSTATUS) 0x0000010AL) -#endif - -#ifndef STATUS_NOTIFY_CLEANUP -# define STATUS_NOTIFY_CLEANUP ((NTSTATUS) 0x0000010BL) -#endif - -#ifndef STATUS_NOTIFY_ENUM_DIR -# define STATUS_NOTIFY_ENUM_DIR ((NTSTATUS) 0x0000010CL) -#endif - -#ifndef STATUS_NO_QUOTAS_FOR_ACCOUNT -# define STATUS_NO_QUOTAS_FOR_ACCOUNT ((NTSTATUS) 0x0000010DL) -#endif - -#ifndef STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED -# define STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED ((NTSTATUS) 0x0000010EL) -#endif - -#ifndef STATUS_PAGE_FAULT_TRANSITION -# define STATUS_PAGE_FAULT_TRANSITION ((NTSTATUS) 0x00000110L) -#endif - -#ifndef STATUS_PAGE_FAULT_DEMAND_ZERO -# define STATUS_PAGE_FAULT_DEMAND_ZERO ((NTSTATUS) 0x00000111L) -#endif - -#ifndef STATUS_PAGE_FAULT_COPY_ON_WRITE -# define STATUS_PAGE_FAULT_COPY_ON_WRITE ((NTSTATUS) 0x00000112L) -#endif - -#ifndef STATUS_PAGE_FAULT_GUARD_PAGE -# define STATUS_PAGE_FAULT_GUARD_PAGE ((NTSTATUS) 0x00000113L) -#endif - -#ifndef STATUS_PAGE_FAULT_PAGING_FILE -# define STATUS_PAGE_FAULT_PAGING_FILE ((NTSTATUS) 0x00000114L) -#endif - -#ifndef STATUS_CACHE_PAGE_LOCKED -# define STATUS_CACHE_PAGE_LOCKED ((NTSTATUS) 0x00000115L) -#endif - -#ifndef STATUS_CRASH_DUMP -# define STATUS_CRASH_DUMP ((NTSTATUS) 0x00000116L) -#endif - -#ifndef STATUS_BUFFER_ALL_ZEROS -# define STATUS_BUFFER_ALL_ZEROS ((NTSTATUS) 0x00000117L) -#endif - -#ifndef STATUS_REPARSE_OBJECT -# define STATUS_REPARSE_OBJECT ((NTSTATUS) 0x00000118L) -#endif - -#ifndef STATUS_RESOURCE_REQUIREMENTS_CHANGED -# define STATUS_RESOURCE_REQUIREMENTS_CHANGED ((NTSTATUS) 0x00000119L) -#endif - -#ifndef STATUS_TRANSLATION_COMPLETE -# define STATUS_TRANSLATION_COMPLETE ((NTSTATUS) 0x00000120L) -#endif - -#ifndef STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY -# define STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY ((NTSTATUS) 0x00000121L) -#endif - -#ifndef STATUS_NOTHING_TO_TERMINATE -# define STATUS_NOTHING_TO_TERMINATE ((NTSTATUS) 0x00000122L) -#endif - -#ifndef STATUS_PROCESS_NOT_IN_JOB -# define STATUS_PROCESS_NOT_IN_JOB ((NTSTATUS) 0x00000123L) -#endif - -#ifndef STATUS_PROCESS_IN_JOB -# define STATUS_PROCESS_IN_JOB ((NTSTATUS) 0x00000124L) -#endif - -#ifndef STATUS_VOLSNAP_HIBERNATE_READY -# define STATUS_VOLSNAP_HIBERNATE_READY ((NTSTATUS) 0x00000125L) -#endif - -#ifndef STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY -# define STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY ((NTSTATUS) 0x00000126L) -#endif - -#ifndef STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED -# define STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED ((NTSTATUS) 0x00000127L) -#endif - -#ifndef STATUS_INTERRUPT_STILL_CONNECTED -# define STATUS_INTERRUPT_STILL_CONNECTED ((NTSTATUS) 0x00000128L) -#endif - -#ifndef STATUS_PROCESS_CLONED -# define STATUS_PROCESS_CLONED ((NTSTATUS) 0x00000129L) -#endif - -#ifndef STATUS_FILE_LOCKED_WITH_ONLY_READERS -# define STATUS_FILE_LOCKED_WITH_ONLY_READERS ((NTSTATUS) 0x0000012AL) -#endif - -#ifndef STATUS_FILE_LOCKED_WITH_WRITERS -# define STATUS_FILE_LOCKED_WITH_WRITERS ((NTSTATUS) 0x0000012BL) -#endif - -#ifndef STATUS_RESOURCEMANAGER_READ_ONLY -# define STATUS_RESOURCEMANAGER_READ_ONLY ((NTSTATUS) 0x00000202L) -#endif - -#ifndef STATUS_RING_PREVIOUSLY_EMPTY -# define STATUS_RING_PREVIOUSLY_EMPTY ((NTSTATUS) 0x00000210L) -#endif - -#ifndef STATUS_RING_PREVIOUSLY_FULL -# define STATUS_RING_PREVIOUSLY_FULL ((NTSTATUS) 0x00000211L) -#endif - -#ifndef STATUS_RING_PREVIOUSLY_ABOVE_QUOTA -# define STATUS_RING_PREVIOUSLY_ABOVE_QUOTA ((NTSTATUS) 0x00000212L) -#endif - -#ifndef STATUS_RING_NEWLY_EMPTY -# define STATUS_RING_NEWLY_EMPTY ((NTSTATUS) 0x00000213L) -#endif - -#ifndef STATUS_RING_SIGNAL_OPPOSITE_ENDPOINT -# define STATUS_RING_SIGNAL_OPPOSITE_ENDPOINT ((NTSTATUS) 0x00000214L) -#endif - -#ifndef STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE -# define STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE ((NTSTATUS) 0x00000215L) -#endif - -#ifndef STATUS_OPLOCK_HANDLE_CLOSED -# define STATUS_OPLOCK_HANDLE_CLOSED ((NTSTATUS) 0x00000216L) -#endif - -#ifndef STATUS_WAIT_FOR_OPLOCK -# define STATUS_WAIT_FOR_OPLOCK ((NTSTATUS) 0x00000367L) -#endif - -#ifndef STATUS_OBJECT_NAME_EXISTS -# define STATUS_OBJECT_NAME_EXISTS ((NTSTATUS) 0x40000000L) -#endif - -#ifndef STATUS_THREAD_WAS_SUSPENDED -# define STATUS_THREAD_WAS_SUSPENDED ((NTSTATUS) 0x40000001L) -#endif - -#ifndef STATUS_WORKING_SET_LIMIT_RANGE -# define STATUS_WORKING_SET_LIMIT_RANGE ((NTSTATUS) 0x40000002L) -#endif - -#ifndef STATUS_IMAGE_NOT_AT_BASE -# define STATUS_IMAGE_NOT_AT_BASE ((NTSTATUS) 0x40000003L) -#endif - -#ifndef STATUS_RXACT_STATE_CREATED -# define STATUS_RXACT_STATE_CREATED ((NTSTATUS) 0x40000004L) -#endif - -#ifndef STATUS_SEGMENT_NOTIFICATION -# define STATUS_SEGMENT_NOTIFICATION ((NTSTATUS) 0x40000005L) -#endif - -#ifndef STATUS_LOCAL_USER_SESSION_KEY -# define STATUS_LOCAL_USER_SESSION_KEY ((NTSTATUS) 0x40000006L) -#endif - -#ifndef STATUS_BAD_CURRENT_DIRECTORY -# define STATUS_BAD_CURRENT_DIRECTORY ((NTSTATUS) 0x40000007L) -#endif - -#ifndef STATUS_SERIAL_MORE_WRITES -# define STATUS_SERIAL_MORE_WRITES ((NTSTATUS) 0x40000008L) -#endif - -#ifndef STATUS_REGISTRY_RECOVERED -# define STATUS_REGISTRY_RECOVERED ((NTSTATUS) 0x40000009L) -#endif - -#ifndef STATUS_FT_READ_RECOVERY_FROM_BACKUP -# define STATUS_FT_READ_RECOVERY_FROM_BACKUP ((NTSTATUS) 0x4000000AL) -#endif - -#ifndef STATUS_FT_WRITE_RECOVERY -# define STATUS_FT_WRITE_RECOVERY ((NTSTATUS) 0x4000000BL) -#endif - -#ifndef STATUS_SERIAL_COUNTER_TIMEOUT -# define STATUS_SERIAL_COUNTER_TIMEOUT ((NTSTATUS) 0x4000000CL) -#endif - -#ifndef STATUS_NULL_LM_PASSWORD -# define STATUS_NULL_LM_PASSWORD ((NTSTATUS) 0x4000000DL) -#endif - -#ifndef STATUS_IMAGE_MACHINE_TYPE_MISMATCH -# define STATUS_IMAGE_MACHINE_TYPE_MISMATCH ((NTSTATUS) 0x4000000EL) -#endif - -#ifndef STATUS_RECEIVE_PARTIAL -# define STATUS_RECEIVE_PARTIAL ((NTSTATUS) 0x4000000FL) -#endif - -#ifndef STATUS_RECEIVE_EXPEDITED -# define STATUS_RECEIVE_EXPEDITED ((NTSTATUS) 0x40000010L) -#endif - -#ifndef STATUS_RECEIVE_PARTIAL_EXPEDITED -# define STATUS_RECEIVE_PARTIAL_EXPEDITED ((NTSTATUS) 0x40000011L) -#endif - -#ifndef STATUS_EVENT_DONE -# define STATUS_EVENT_DONE ((NTSTATUS) 0x40000012L) -#endif - -#ifndef STATUS_EVENT_PENDING -# define STATUS_EVENT_PENDING ((NTSTATUS) 0x40000013L) -#endif - -#ifndef STATUS_CHECKING_FILE_SYSTEM -# define STATUS_CHECKING_FILE_SYSTEM ((NTSTATUS) 0x40000014L) -#endif - -#ifndef STATUS_FATAL_APP_EXIT -# define STATUS_FATAL_APP_EXIT ((NTSTATUS) 0x40000015L) -#endif - -#ifndef STATUS_PREDEFINED_HANDLE -# define STATUS_PREDEFINED_HANDLE ((NTSTATUS) 0x40000016L) -#endif - -#ifndef STATUS_WAS_UNLOCKED -# define STATUS_WAS_UNLOCKED ((NTSTATUS) 0x40000017L) -#endif - -#ifndef STATUS_SERVICE_NOTIFICATION -# define STATUS_SERVICE_NOTIFICATION ((NTSTATUS) 0x40000018L) -#endif - -#ifndef STATUS_WAS_LOCKED -# define STATUS_WAS_LOCKED ((NTSTATUS) 0x40000019L) -#endif - -#ifndef STATUS_LOG_HARD_ERROR -# define STATUS_LOG_HARD_ERROR ((NTSTATUS) 0x4000001AL) -#endif - -#ifndef STATUS_ALREADY_WIN32 -# define STATUS_ALREADY_WIN32 ((NTSTATUS) 0x4000001BL) -#endif - -#ifndef STATUS_WX86_UNSIMULATE -# define STATUS_WX86_UNSIMULATE ((NTSTATUS) 0x4000001CL) -#endif - -#ifndef STATUS_WX86_CONTINUE -# define STATUS_WX86_CONTINUE ((NTSTATUS) 0x4000001DL) -#endif - -#ifndef STATUS_WX86_SINGLE_STEP -# define STATUS_WX86_SINGLE_STEP ((NTSTATUS) 0x4000001EL) -#endif - -#ifndef STATUS_WX86_BREAKPOINT -# define STATUS_WX86_BREAKPOINT ((NTSTATUS) 0x4000001FL) -#endif - -#ifndef STATUS_WX86_EXCEPTION_CONTINUE -# define STATUS_WX86_EXCEPTION_CONTINUE ((NTSTATUS) 0x40000020L) -#endif - -#ifndef STATUS_WX86_EXCEPTION_LASTCHANCE -# define STATUS_WX86_EXCEPTION_LASTCHANCE ((NTSTATUS) 0x40000021L) -#endif - -#ifndef STATUS_WX86_EXCEPTION_CHAIN -# define STATUS_WX86_EXCEPTION_CHAIN ((NTSTATUS) 0x40000022L) -#endif - -#ifndef STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE -# define STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE ((NTSTATUS) 0x40000023L) -#endif - -#ifndef STATUS_NO_YIELD_PERFORMED -# define STATUS_NO_YIELD_PERFORMED ((NTSTATUS) 0x40000024L) -#endif - -#ifndef STATUS_TIMER_RESUME_IGNORED -# define STATUS_TIMER_RESUME_IGNORED ((NTSTATUS) 0x40000025L) -#endif - -#ifndef STATUS_ARBITRATION_UNHANDLED -# define STATUS_ARBITRATION_UNHANDLED ((NTSTATUS) 0x40000026L) -#endif - -#ifndef STATUS_CARDBUS_NOT_SUPPORTED -# define STATUS_CARDBUS_NOT_SUPPORTED ((NTSTATUS) 0x40000027L) -#endif - -#ifndef STATUS_WX86_CREATEWX86TIB -# define STATUS_WX86_CREATEWX86TIB ((NTSTATUS) 0x40000028L) -#endif - -#ifndef STATUS_MP_PROCESSOR_MISMATCH -# define STATUS_MP_PROCESSOR_MISMATCH ((NTSTATUS) 0x40000029L) -#endif - -#ifndef STATUS_HIBERNATED -# define STATUS_HIBERNATED ((NTSTATUS) 0x4000002AL) -#endif - -#ifndef STATUS_RESUME_HIBERNATION -# define STATUS_RESUME_HIBERNATION ((NTSTATUS) 0x4000002BL) -#endif - -#ifndef STATUS_FIRMWARE_UPDATED -# define STATUS_FIRMWARE_UPDATED ((NTSTATUS) 0x4000002CL) -#endif - -#ifndef STATUS_DRIVERS_LEAKING_LOCKED_PAGES -# define STATUS_DRIVERS_LEAKING_LOCKED_PAGES ((NTSTATUS) 0x4000002DL) -#endif - -#ifndef STATUS_MESSAGE_RETRIEVED -# define STATUS_MESSAGE_RETRIEVED ((NTSTATUS) 0x4000002EL) -#endif - -#ifndef STATUS_SYSTEM_POWERSTATE_TRANSITION -# define STATUS_SYSTEM_POWERSTATE_TRANSITION ((NTSTATUS) 0x4000002FL) -#endif - -#ifndef STATUS_ALPC_CHECK_COMPLETION_LIST -# define STATUS_ALPC_CHECK_COMPLETION_LIST ((NTSTATUS) 0x40000030L) -#endif - -#ifndef STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION -# define STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION ((NTSTATUS) 0x40000031L) -#endif - -#ifndef STATUS_ACCESS_AUDIT_BY_POLICY -# define STATUS_ACCESS_AUDIT_BY_POLICY ((NTSTATUS) 0x40000032L) -#endif - -#ifndef STATUS_ABANDON_HIBERFILE -# define STATUS_ABANDON_HIBERFILE ((NTSTATUS) 0x40000033L) -#endif - -#ifndef STATUS_BIZRULES_NOT_ENABLED -# define STATUS_BIZRULES_NOT_ENABLED ((NTSTATUS) 0x40000034L) -#endif - -#ifndef STATUS_GUARD_PAGE_VIOLATION -# define STATUS_GUARD_PAGE_VIOLATION ((NTSTATUS) 0x80000001L) -#endif - -#ifndef STATUS_DATATYPE_MISALIGNMENT -# define STATUS_DATATYPE_MISALIGNMENT ((NTSTATUS) 0x80000002L) -#endif - -#ifndef STATUS_BREAKPOINT -# define STATUS_BREAKPOINT ((NTSTATUS) 0x80000003L) -#endif - -#ifndef STATUS_SINGLE_STEP -# define STATUS_SINGLE_STEP ((NTSTATUS) 0x80000004L) -#endif - -#ifndef STATUS_BUFFER_OVERFLOW -# define STATUS_BUFFER_OVERFLOW ((NTSTATUS) 0x80000005L) -#endif - -#ifndef STATUS_NO_MORE_FILES -# define STATUS_NO_MORE_FILES ((NTSTATUS) 0x80000006L) -#endif - -#ifndef STATUS_WAKE_SYSTEM_DEBUGGER -# define STATUS_WAKE_SYSTEM_DEBUGGER ((NTSTATUS) 0x80000007L) -#endif - -#ifndef STATUS_HANDLES_CLOSED -# define STATUS_HANDLES_CLOSED ((NTSTATUS) 0x8000000AL) -#endif - -#ifndef STATUS_NO_INHERITANCE -# define STATUS_NO_INHERITANCE ((NTSTATUS) 0x8000000BL) -#endif - -#ifndef STATUS_GUID_SUBSTITUTION_MADE -# define STATUS_GUID_SUBSTITUTION_MADE ((NTSTATUS) 0x8000000CL) -#endif - -#ifndef STATUS_PARTIAL_COPY -# define STATUS_PARTIAL_COPY ((NTSTATUS) 0x8000000DL) -#endif - -#ifndef STATUS_DEVICE_PAPER_EMPTY -# define STATUS_DEVICE_PAPER_EMPTY ((NTSTATUS) 0x8000000EL) -#endif - -#ifndef STATUS_DEVICE_POWERED_OFF -# define STATUS_DEVICE_POWERED_OFF ((NTSTATUS) 0x8000000FL) -#endif - -#ifndef STATUS_DEVICE_OFF_LINE -# define STATUS_DEVICE_OFF_LINE ((NTSTATUS) 0x80000010L) -#endif - -#ifndef STATUS_DEVICE_BUSY -# define STATUS_DEVICE_BUSY ((NTSTATUS) 0x80000011L) -#endif - -#ifndef STATUS_NO_MORE_EAS -# define STATUS_NO_MORE_EAS ((NTSTATUS) 0x80000012L) -#endif - -#ifndef STATUS_INVALID_EA_NAME -# define STATUS_INVALID_EA_NAME ((NTSTATUS) 0x80000013L) -#endif - -#ifndef STATUS_EA_LIST_INCONSISTENT -# define STATUS_EA_LIST_INCONSISTENT ((NTSTATUS) 0x80000014L) -#endif - -#ifndef STATUS_INVALID_EA_FLAG -# define STATUS_INVALID_EA_FLAG ((NTSTATUS) 0x80000015L) -#endif - -#ifndef STATUS_VERIFY_REQUIRED -# define STATUS_VERIFY_REQUIRED ((NTSTATUS) 0x80000016L) -#endif - -#ifndef STATUS_EXTRANEOUS_INFORMATION -# define STATUS_EXTRANEOUS_INFORMATION ((NTSTATUS) 0x80000017L) -#endif - -#ifndef STATUS_RXACT_COMMIT_NECESSARY -# define STATUS_RXACT_COMMIT_NECESSARY ((NTSTATUS) 0x80000018L) -#endif - -#ifndef STATUS_NO_MORE_ENTRIES -# define STATUS_NO_MORE_ENTRIES ((NTSTATUS) 0x8000001AL) -#endif - -#ifndef STATUS_FILEMARK_DETECTED -# define STATUS_FILEMARK_DETECTED ((NTSTATUS) 0x8000001BL) -#endif - -#ifndef STATUS_MEDIA_CHANGED -# define STATUS_MEDIA_CHANGED ((NTSTATUS) 0x8000001CL) -#endif - -#ifndef STATUS_BUS_RESET -# define STATUS_BUS_RESET ((NTSTATUS) 0x8000001DL) -#endif - -#ifndef STATUS_END_OF_MEDIA -# define STATUS_END_OF_MEDIA ((NTSTATUS) 0x8000001EL) -#endif - -#ifndef STATUS_BEGINNING_OF_MEDIA -# define STATUS_BEGINNING_OF_MEDIA ((NTSTATUS) 0x8000001FL) -#endif - -#ifndef STATUS_MEDIA_CHECK -# define STATUS_MEDIA_CHECK ((NTSTATUS) 0x80000020L) -#endif - -#ifndef STATUS_SETMARK_DETECTED -# define STATUS_SETMARK_DETECTED ((NTSTATUS) 0x80000021L) -#endif - -#ifndef STATUS_NO_DATA_DETECTED -# define STATUS_NO_DATA_DETECTED ((NTSTATUS) 0x80000022L) -#endif - -#ifndef STATUS_REDIRECTOR_HAS_OPEN_HANDLES -# define STATUS_REDIRECTOR_HAS_OPEN_HANDLES ((NTSTATUS) 0x80000023L) -#endif - -#ifndef STATUS_SERVER_HAS_OPEN_HANDLES -# define STATUS_SERVER_HAS_OPEN_HANDLES ((NTSTATUS) 0x80000024L) -#endif - -#ifndef STATUS_ALREADY_DISCONNECTED -# define STATUS_ALREADY_DISCONNECTED ((NTSTATUS) 0x80000025L) -#endif - -#ifndef STATUS_LONGJUMP -# define STATUS_LONGJUMP ((NTSTATUS) 0x80000026L) -#endif - -#ifndef STATUS_CLEANER_CARTRIDGE_INSTALLED -# define STATUS_CLEANER_CARTRIDGE_INSTALLED ((NTSTATUS) 0x80000027L) -#endif - -#ifndef STATUS_PLUGPLAY_QUERY_VETOED -# define STATUS_PLUGPLAY_QUERY_VETOED ((NTSTATUS) 0x80000028L) -#endif - -#ifndef STATUS_UNWIND_CONSOLIDATE -# define STATUS_UNWIND_CONSOLIDATE ((NTSTATUS) 0x80000029L) -#endif - -#ifndef STATUS_REGISTRY_HIVE_RECOVERED -# define STATUS_REGISTRY_HIVE_RECOVERED ((NTSTATUS) 0x8000002AL) -#endif - -#ifndef STATUS_DLL_MIGHT_BE_INSECURE -# define STATUS_DLL_MIGHT_BE_INSECURE ((NTSTATUS) 0x8000002BL) -#endif - -#ifndef STATUS_DLL_MIGHT_BE_INCOMPATIBLE -# define STATUS_DLL_MIGHT_BE_INCOMPATIBLE ((NTSTATUS) 0x8000002CL) -#endif - -#ifndef STATUS_STOPPED_ON_SYMLINK -# define STATUS_STOPPED_ON_SYMLINK ((NTSTATUS) 0x8000002DL) -#endif - -#ifndef STATUS_CANNOT_GRANT_REQUESTED_OPLOCK -# define STATUS_CANNOT_GRANT_REQUESTED_OPLOCK ((NTSTATUS) 0x8000002EL) -#endif - -#ifndef STATUS_NO_ACE_CONDITION -# define STATUS_NO_ACE_CONDITION ((NTSTATUS) 0x8000002FL) -#endif - -#ifndef STATUS_UNSUCCESSFUL -# define STATUS_UNSUCCESSFUL ((NTSTATUS) 0xC0000001L) -#endif - -#ifndef STATUS_NOT_IMPLEMENTED -# define STATUS_NOT_IMPLEMENTED ((NTSTATUS) 0xC0000002L) -#endif - -#ifndef STATUS_INVALID_INFO_CLASS -# define STATUS_INVALID_INFO_CLASS ((NTSTATUS) 0xC0000003L) -#endif - -#ifndef STATUS_INFO_LENGTH_MISMATCH -# define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xC0000004L) -#endif - -#ifndef STATUS_ACCESS_VIOLATION -# define STATUS_ACCESS_VIOLATION ((NTSTATUS) 0xC0000005L) -#endif - -#ifndef STATUS_IN_PAGE_ERROR -# define STATUS_IN_PAGE_ERROR ((NTSTATUS) 0xC0000006L) -#endif - -#ifndef STATUS_PAGEFILE_QUOTA -# define STATUS_PAGEFILE_QUOTA ((NTSTATUS) 0xC0000007L) -#endif - -#ifndef STATUS_INVALID_HANDLE -# define STATUS_INVALID_HANDLE ((NTSTATUS) 0xC0000008L) -#endif - -#ifndef STATUS_BAD_INITIAL_STACK -# define STATUS_BAD_INITIAL_STACK ((NTSTATUS) 0xC0000009L) -#endif - -#ifndef STATUS_BAD_INITIAL_PC -# define STATUS_BAD_INITIAL_PC ((NTSTATUS) 0xC000000AL) -#endif - -#ifndef STATUS_INVALID_CID -# define STATUS_INVALID_CID ((NTSTATUS) 0xC000000BL) -#endif - -#ifndef STATUS_TIMER_NOT_CANCELED -# define STATUS_TIMER_NOT_CANCELED ((NTSTATUS) 0xC000000CL) -#endif - -#ifndef STATUS_INVALID_PARAMETER -# define STATUS_INVALID_PARAMETER ((NTSTATUS) 0xC000000DL) -#endif - -#ifndef STATUS_NO_SUCH_DEVICE -# define STATUS_NO_SUCH_DEVICE ((NTSTATUS) 0xC000000EL) -#endif - -#ifndef STATUS_NO_SUCH_FILE -# define STATUS_NO_SUCH_FILE ((NTSTATUS) 0xC000000FL) -#endif - -#ifndef STATUS_INVALID_DEVICE_REQUEST -# define STATUS_INVALID_DEVICE_REQUEST ((NTSTATUS) 0xC0000010L) -#endif - -#ifndef STATUS_END_OF_FILE -# define STATUS_END_OF_FILE ((NTSTATUS) 0xC0000011L) -#endif - -#ifndef STATUS_WRONG_VOLUME -# define STATUS_WRONG_VOLUME ((NTSTATUS) 0xC0000012L) -#endif - -#ifndef STATUS_NO_MEDIA_IN_DEVICE -# define STATUS_NO_MEDIA_IN_DEVICE ((NTSTATUS) 0xC0000013L) -#endif - -#ifndef STATUS_UNRECOGNIZED_MEDIA -# define STATUS_UNRECOGNIZED_MEDIA ((NTSTATUS) 0xC0000014L) -#endif - -#ifndef STATUS_NONEXISTENT_SECTOR -# define STATUS_NONEXISTENT_SECTOR ((NTSTATUS) 0xC0000015L) -#endif - -#ifndef STATUS_MORE_PROCESSING_REQUIRED -# define STATUS_MORE_PROCESSING_REQUIRED ((NTSTATUS) 0xC0000016L) -#endif - -#ifndef STATUS_NO_MEMORY -# define STATUS_NO_MEMORY ((NTSTATUS) 0xC0000017L) -#endif - -#ifndef STATUS_CONFLICTING_ADDRESSES -# define STATUS_CONFLICTING_ADDRESSES ((NTSTATUS) 0xC0000018L) -#endif - -#ifndef STATUS_NOT_MAPPED_VIEW -# define STATUS_NOT_MAPPED_VIEW ((NTSTATUS) 0xC0000019L) -#endif - -#ifndef STATUS_UNABLE_TO_FREE_VM -# define STATUS_UNABLE_TO_FREE_VM ((NTSTATUS) 0xC000001AL) -#endif - -#ifndef STATUS_UNABLE_TO_DELETE_SECTION -# define STATUS_UNABLE_TO_DELETE_SECTION ((NTSTATUS) 0xC000001BL) -#endif - -#ifndef STATUS_INVALID_SYSTEM_SERVICE -# define STATUS_INVALID_SYSTEM_SERVICE ((NTSTATUS) 0xC000001CL) -#endif - -#ifndef STATUS_ILLEGAL_INSTRUCTION -# define STATUS_ILLEGAL_INSTRUCTION ((NTSTATUS) 0xC000001DL) -#endif - -#ifndef STATUS_INVALID_LOCK_SEQUENCE -# define STATUS_INVALID_LOCK_SEQUENCE ((NTSTATUS) 0xC000001EL) -#endif - -#ifndef STATUS_INVALID_VIEW_SIZE -# define STATUS_INVALID_VIEW_SIZE ((NTSTATUS) 0xC000001FL) -#endif - -#ifndef STATUS_INVALID_FILE_FOR_SECTION -# define STATUS_INVALID_FILE_FOR_SECTION ((NTSTATUS) 0xC0000020L) -#endif - -#ifndef STATUS_ALREADY_COMMITTED -# define STATUS_ALREADY_COMMITTED ((NTSTATUS) 0xC0000021L) -#endif - -#ifndef STATUS_ACCESS_DENIED -# define STATUS_ACCESS_DENIED ((NTSTATUS) 0xC0000022L) -#endif - -#ifndef STATUS_BUFFER_TOO_SMALL -# define STATUS_BUFFER_TOO_SMALL ((NTSTATUS) 0xC0000023L) -#endif - -#ifndef STATUS_OBJECT_TYPE_MISMATCH -# define STATUS_OBJECT_TYPE_MISMATCH ((NTSTATUS) 0xC0000024L) -#endif - -#ifndef STATUS_NONCONTINUABLE_EXCEPTION -# define STATUS_NONCONTINUABLE_EXCEPTION ((NTSTATUS) 0xC0000025L) -#endif - -#ifndef STATUS_INVALID_DISPOSITION -# define STATUS_INVALID_DISPOSITION ((NTSTATUS) 0xC0000026L) -#endif - -#ifndef STATUS_UNWIND -# define STATUS_UNWIND ((NTSTATUS) 0xC0000027L) -#endif - -#ifndef STATUS_BAD_STACK -# define STATUS_BAD_STACK ((NTSTATUS) 0xC0000028L) -#endif - -#ifndef STATUS_INVALID_UNWIND_TARGET -# define STATUS_INVALID_UNWIND_TARGET ((NTSTATUS) 0xC0000029L) -#endif - -#ifndef STATUS_NOT_LOCKED -# define STATUS_NOT_LOCKED ((NTSTATUS) 0xC000002AL) -#endif - -#ifndef STATUS_PARITY_ERROR -# define STATUS_PARITY_ERROR ((NTSTATUS) 0xC000002BL) -#endif - -#ifndef STATUS_UNABLE_TO_DECOMMIT_VM -# define STATUS_UNABLE_TO_DECOMMIT_VM ((NTSTATUS) 0xC000002CL) -#endif - -#ifndef STATUS_NOT_COMMITTED -# define STATUS_NOT_COMMITTED ((NTSTATUS) 0xC000002DL) -#endif - -#ifndef STATUS_INVALID_PORT_ATTRIBUTES -# define STATUS_INVALID_PORT_ATTRIBUTES ((NTSTATUS) 0xC000002EL) -#endif - -#ifndef STATUS_PORT_MESSAGE_TOO_LONG -# define STATUS_PORT_MESSAGE_TOO_LONG ((NTSTATUS) 0xC000002FL) -#endif - -#ifndef STATUS_INVALID_PARAMETER_MIX -# define STATUS_INVALID_PARAMETER_MIX ((NTSTATUS) 0xC0000030L) -#endif - -#ifndef STATUS_INVALID_QUOTA_LOWER -# define STATUS_INVALID_QUOTA_LOWER ((NTSTATUS) 0xC0000031L) -#endif - -#ifndef STATUS_DISK_CORRUPT_ERROR -# define STATUS_DISK_CORRUPT_ERROR ((NTSTATUS) 0xC0000032L) -#endif - -#ifndef STATUS_OBJECT_NAME_INVALID -# define STATUS_OBJECT_NAME_INVALID ((NTSTATUS) 0xC0000033L) -#endif - -#ifndef STATUS_OBJECT_NAME_NOT_FOUND -# define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS) 0xC0000034L) -#endif - -#ifndef STATUS_OBJECT_NAME_COLLISION -# define STATUS_OBJECT_NAME_COLLISION ((NTSTATUS) 0xC0000035L) -#endif - -#ifndef STATUS_PORT_DISCONNECTED -# define STATUS_PORT_DISCONNECTED ((NTSTATUS) 0xC0000037L) -#endif - -#ifndef STATUS_DEVICE_ALREADY_ATTACHED -# define STATUS_DEVICE_ALREADY_ATTACHED ((NTSTATUS) 0xC0000038L) -#endif - -#ifndef STATUS_OBJECT_PATH_INVALID -# define STATUS_OBJECT_PATH_INVALID ((NTSTATUS) 0xC0000039L) -#endif - -#ifndef STATUS_OBJECT_PATH_NOT_FOUND -# define STATUS_OBJECT_PATH_NOT_FOUND ((NTSTATUS) 0xC000003AL) -#endif - -#ifndef STATUS_OBJECT_PATH_SYNTAX_BAD -# define STATUS_OBJECT_PATH_SYNTAX_BAD ((NTSTATUS) 0xC000003BL) -#endif - -#ifndef STATUS_DATA_OVERRUN -# define STATUS_DATA_OVERRUN ((NTSTATUS) 0xC000003CL) -#endif - -#ifndef STATUS_DATA_LATE_ERROR -# define STATUS_DATA_LATE_ERROR ((NTSTATUS) 0xC000003DL) -#endif - -#ifndef STATUS_DATA_ERROR -# define STATUS_DATA_ERROR ((NTSTATUS) 0xC000003EL) -#endif - -#ifndef STATUS_CRC_ERROR -# define STATUS_CRC_ERROR ((NTSTATUS) 0xC000003FL) -#endif - -#ifndef STATUS_SECTION_TOO_BIG -# define STATUS_SECTION_TOO_BIG ((NTSTATUS) 0xC0000040L) -#endif - -#ifndef STATUS_PORT_CONNECTION_REFUSED -# define STATUS_PORT_CONNECTION_REFUSED ((NTSTATUS) 0xC0000041L) -#endif - -#ifndef STATUS_INVALID_PORT_HANDLE -# define STATUS_INVALID_PORT_HANDLE ((NTSTATUS) 0xC0000042L) -#endif - -#ifndef STATUS_SHARING_VIOLATION -# define STATUS_SHARING_VIOLATION ((NTSTATUS) 0xC0000043L) -#endif - -#ifndef STATUS_QUOTA_EXCEEDED -# define STATUS_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000044L) -#endif - -#ifndef STATUS_INVALID_PAGE_PROTECTION -# define STATUS_INVALID_PAGE_PROTECTION ((NTSTATUS) 0xC0000045L) -#endif - -#ifndef STATUS_MUTANT_NOT_OWNED -# define STATUS_MUTANT_NOT_OWNED ((NTSTATUS) 0xC0000046L) -#endif - -#ifndef STATUS_SEMAPHORE_LIMIT_EXCEEDED -# define STATUS_SEMAPHORE_LIMIT_EXCEEDED ((NTSTATUS) 0xC0000047L) -#endif - -#ifndef STATUS_PORT_ALREADY_SET -# define STATUS_PORT_ALREADY_SET ((NTSTATUS) 0xC0000048L) -#endif - -#ifndef STATUS_SECTION_NOT_IMAGE -# define STATUS_SECTION_NOT_IMAGE ((NTSTATUS) 0xC0000049L) -#endif - -#ifndef STATUS_SUSPEND_COUNT_EXCEEDED -# define STATUS_SUSPEND_COUNT_EXCEEDED ((NTSTATUS) 0xC000004AL) -#endif - -#ifndef STATUS_THREAD_IS_TERMINATING -# define STATUS_THREAD_IS_TERMINATING ((NTSTATUS) 0xC000004BL) -#endif - -#ifndef STATUS_BAD_WORKING_SET_LIMIT -# define STATUS_BAD_WORKING_SET_LIMIT ((NTSTATUS) 0xC000004CL) -#endif - -#ifndef STATUS_INCOMPATIBLE_FILE_MAP -# define STATUS_INCOMPATIBLE_FILE_MAP ((NTSTATUS) 0xC000004DL) -#endif - -#ifndef STATUS_SECTION_PROTECTION -# define STATUS_SECTION_PROTECTION ((NTSTATUS) 0xC000004EL) -#endif - -#ifndef STATUS_EAS_NOT_SUPPORTED -# define STATUS_EAS_NOT_SUPPORTED ((NTSTATUS) 0xC000004FL) -#endif - -#ifndef STATUS_EA_TOO_LARGE -# define STATUS_EA_TOO_LARGE ((NTSTATUS) 0xC0000050L) -#endif - -#ifndef STATUS_NONEXISTENT_EA_ENTRY -# define STATUS_NONEXISTENT_EA_ENTRY ((NTSTATUS) 0xC0000051L) -#endif - -#ifndef STATUS_NO_EAS_ON_FILE -# define STATUS_NO_EAS_ON_FILE ((NTSTATUS) 0xC0000052L) -#endif - -#ifndef STATUS_EA_CORRUPT_ERROR -# define STATUS_EA_CORRUPT_ERROR ((NTSTATUS) 0xC0000053L) -#endif - -#ifndef STATUS_FILE_LOCK_CONFLICT -# define STATUS_FILE_LOCK_CONFLICT ((NTSTATUS) 0xC0000054L) -#endif - -#ifndef STATUS_LOCK_NOT_GRANTED -# define STATUS_LOCK_NOT_GRANTED ((NTSTATUS) 0xC0000055L) -#endif - -#ifndef STATUS_DELETE_PENDING -# define STATUS_DELETE_PENDING ((NTSTATUS) 0xC0000056L) -#endif - -#ifndef STATUS_CTL_FILE_NOT_SUPPORTED -# define STATUS_CTL_FILE_NOT_SUPPORTED ((NTSTATUS) 0xC0000057L) -#endif - -#ifndef STATUS_UNKNOWN_REVISION -# define STATUS_UNKNOWN_REVISION ((NTSTATUS) 0xC0000058L) -#endif - -#ifndef STATUS_REVISION_MISMATCH -# define STATUS_REVISION_MISMATCH ((NTSTATUS) 0xC0000059L) -#endif - -#ifndef STATUS_INVALID_OWNER -# define STATUS_INVALID_OWNER ((NTSTATUS) 0xC000005AL) -#endif - -#ifndef STATUS_INVALID_PRIMARY_GROUP -# define STATUS_INVALID_PRIMARY_GROUP ((NTSTATUS) 0xC000005BL) -#endif - -#ifndef STATUS_NO_IMPERSONATION_TOKEN -# define STATUS_NO_IMPERSONATION_TOKEN ((NTSTATUS) 0xC000005CL) -#endif - -#ifndef STATUS_CANT_DISABLE_MANDATORY -# define STATUS_CANT_DISABLE_MANDATORY ((NTSTATUS) 0xC000005DL) -#endif - -#ifndef STATUS_NO_LOGON_SERVERS -# define STATUS_NO_LOGON_SERVERS ((NTSTATUS) 0xC000005EL) -#endif - -#ifndef STATUS_NO_SUCH_LOGON_SESSION -# define STATUS_NO_SUCH_LOGON_SESSION ((NTSTATUS) 0xC000005FL) -#endif - -#ifndef STATUS_NO_SUCH_PRIVILEGE -# define STATUS_NO_SUCH_PRIVILEGE ((NTSTATUS) 0xC0000060L) -#endif - -#ifndef STATUS_PRIVILEGE_NOT_HELD -# define STATUS_PRIVILEGE_NOT_HELD ((NTSTATUS) 0xC0000061L) -#endif - -#ifndef STATUS_INVALID_ACCOUNT_NAME -# define STATUS_INVALID_ACCOUNT_NAME ((NTSTATUS) 0xC0000062L) -#endif - -#ifndef STATUS_USER_EXISTS -# define STATUS_USER_EXISTS ((NTSTATUS) 0xC0000063L) -#endif - -#ifndef STATUS_NO_SUCH_USER -# define STATUS_NO_SUCH_USER ((NTSTATUS) 0xC0000064L) -#endif - -#ifndef STATUS_GROUP_EXISTS -# define STATUS_GROUP_EXISTS ((NTSTATUS) 0xC0000065L) -#endif - -#ifndef STATUS_NO_SUCH_GROUP -# define STATUS_NO_SUCH_GROUP ((NTSTATUS) 0xC0000066L) -#endif - -#ifndef STATUS_MEMBER_IN_GROUP -# define STATUS_MEMBER_IN_GROUP ((NTSTATUS) 0xC0000067L) -#endif - -#ifndef STATUS_MEMBER_NOT_IN_GROUP -# define STATUS_MEMBER_NOT_IN_GROUP ((NTSTATUS) 0xC0000068L) -#endif - -#ifndef STATUS_LAST_ADMIN -# define STATUS_LAST_ADMIN ((NTSTATUS) 0xC0000069L) -#endif - -#ifndef STATUS_WRONG_PASSWORD -# define STATUS_WRONG_PASSWORD ((NTSTATUS) 0xC000006AL) -#endif - -#ifndef STATUS_ILL_FORMED_PASSWORD -# define STATUS_ILL_FORMED_PASSWORD ((NTSTATUS) 0xC000006BL) -#endif - -#ifndef STATUS_PASSWORD_RESTRICTION -# define STATUS_PASSWORD_RESTRICTION ((NTSTATUS) 0xC000006CL) -#endif - -#ifndef STATUS_LOGON_FAILURE -# define STATUS_LOGON_FAILURE ((NTSTATUS) 0xC000006DL) -#endif - -#ifndef STATUS_ACCOUNT_RESTRICTION -# define STATUS_ACCOUNT_RESTRICTION ((NTSTATUS) 0xC000006EL) -#endif - -#ifndef STATUS_INVALID_LOGON_HOURS -# define STATUS_INVALID_LOGON_HOURS ((NTSTATUS) 0xC000006FL) -#endif - -#ifndef STATUS_INVALID_WORKSTATION -# define STATUS_INVALID_WORKSTATION ((NTSTATUS) 0xC0000070L) -#endif - -#ifndef STATUS_PASSWORD_EXPIRED -# define STATUS_PASSWORD_EXPIRED ((NTSTATUS) 0xC0000071L) -#endif - -#ifndef STATUS_ACCOUNT_DISABLED -# define STATUS_ACCOUNT_DISABLED ((NTSTATUS) 0xC0000072L) -#endif - -#ifndef STATUS_NONE_MAPPED -# define STATUS_NONE_MAPPED ((NTSTATUS) 0xC0000073L) -#endif - -#ifndef STATUS_TOO_MANY_LUIDS_REQUESTED -# define STATUS_TOO_MANY_LUIDS_REQUESTED ((NTSTATUS) 0xC0000074L) -#endif - -#ifndef STATUS_LUIDS_EXHAUSTED -# define STATUS_LUIDS_EXHAUSTED ((NTSTATUS) 0xC0000075L) -#endif - -#ifndef STATUS_INVALID_SUB_AUTHORITY -# define STATUS_INVALID_SUB_AUTHORITY ((NTSTATUS) 0xC0000076L) -#endif - -#ifndef STATUS_INVALID_ACL -# define STATUS_INVALID_ACL ((NTSTATUS) 0xC0000077L) -#endif - -#ifndef STATUS_INVALID_SID -# define STATUS_INVALID_SID ((NTSTATUS) 0xC0000078L) -#endif - -#ifndef STATUS_INVALID_SECURITY_DESCR -# define STATUS_INVALID_SECURITY_DESCR ((NTSTATUS) 0xC0000079L) -#endif - -#ifndef STATUS_PROCEDURE_NOT_FOUND -# define STATUS_PROCEDURE_NOT_FOUND ((NTSTATUS) 0xC000007AL) -#endif - -#ifndef STATUS_INVALID_IMAGE_FORMAT -# define STATUS_INVALID_IMAGE_FORMAT ((NTSTATUS) 0xC000007BL) -#endif - -#ifndef STATUS_NO_TOKEN -# define STATUS_NO_TOKEN ((NTSTATUS) 0xC000007CL) -#endif - -#ifndef STATUS_BAD_INHERITANCE_ACL -# define STATUS_BAD_INHERITANCE_ACL ((NTSTATUS) 0xC000007DL) -#endif - -#ifndef STATUS_RANGE_NOT_LOCKED -# define STATUS_RANGE_NOT_LOCKED ((NTSTATUS) 0xC000007EL) -#endif - -#ifndef STATUS_DISK_FULL -# define STATUS_DISK_FULL ((NTSTATUS) 0xC000007FL) -#endif - -#ifndef STATUS_SERVER_DISABLED -# define STATUS_SERVER_DISABLED ((NTSTATUS) 0xC0000080L) -#endif - -#ifndef STATUS_SERVER_NOT_DISABLED -# define STATUS_SERVER_NOT_DISABLED ((NTSTATUS) 0xC0000081L) -#endif - -#ifndef STATUS_TOO_MANY_GUIDS_REQUESTED -# define STATUS_TOO_MANY_GUIDS_REQUESTED ((NTSTATUS) 0xC0000082L) -#endif - -#ifndef STATUS_GUIDS_EXHAUSTED -# define STATUS_GUIDS_EXHAUSTED ((NTSTATUS) 0xC0000083L) -#endif - -#ifndef STATUS_INVALID_ID_AUTHORITY -# define STATUS_INVALID_ID_AUTHORITY ((NTSTATUS) 0xC0000084L) -#endif - -#ifndef STATUS_AGENTS_EXHAUSTED -# define STATUS_AGENTS_EXHAUSTED ((NTSTATUS) 0xC0000085L) -#endif - -#ifndef STATUS_INVALID_VOLUME_LABEL -# define STATUS_INVALID_VOLUME_LABEL ((NTSTATUS) 0xC0000086L) -#endif - -#ifndef STATUS_SECTION_NOT_EXTENDED -# define STATUS_SECTION_NOT_EXTENDED ((NTSTATUS) 0xC0000087L) -#endif - -#ifndef STATUS_NOT_MAPPED_DATA -# define STATUS_NOT_MAPPED_DATA ((NTSTATUS) 0xC0000088L) -#endif - -#ifndef STATUS_RESOURCE_DATA_NOT_FOUND -# define STATUS_RESOURCE_DATA_NOT_FOUND ((NTSTATUS) 0xC0000089L) -#endif - -#ifndef STATUS_RESOURCE_TYPE_NOT_FOUND -# define STATUS_RESOURCE_TYPE_NOT_FOUND ((NTSTATUS) 0xC000008AL) -#endif - -#ifndef STATUS_RESOURCE_NAME_NOT_FOUND -# define STATUS_RESOURCE_NAME_NOT_FOUND ((NTSTATUS) 0xC000008BL) -#endif - -#ifndef STATUS_ARRAY_BOUNDS_EXCEEDED -# define STATUS_ARRAY_BOUNDS_EXCEEDED ((NTSTATUS) 0xC000008CL) -#endif - -#ifndef STATUS_FLOAT_DENORMAL_OPERAND -# define STATUS_FLOAT_DENORMAL_OPERAND ((NTSTATUS) 0xC000008DL) -#endif - -#ifndef STATUS_FLOAT_DIVIDE_BY_ZERO -# define STATUS_FLOAT_DIVIDE_BY_ZERO ((NTSTATUS) 0xC000008EL) -#endif - -#ifndef STATUS_FLOAT_INEXACT_RESULT -# define STATUS_FLOAT_INEXACT_RESULT ((NTSTATUS) 0xC000008FL) -#endif - -#ifndef STATUS_FLOAT_INVALID_OPERATION -# define STATUS_FLOAT_INVALID_OPERATION ((NTSTATUS) 0xC0000090L) -#endif - -#ifndef STATUS_FLOAT_OVERFLOW -# define STATUS_FLOAT_OVERFLOW ((NTSTATUS) 0xC0000091L) -#endif - -#ifndef STATUS_FLOAT_STACK_CHECK -# define STATUS_FLOAT_STACK_CHECK ((NTSTATUS) 0xC0000092L) -#endif - -#ifndef STATUS_FLOAT_UNDERFLOW -# define STATUS_FLOAT_UNDERFLOW ((NTSTATUS) 0xC0000093L) -#endif - -#ifndef STATUS_INTEGER_DIVIDE_BY_ZERO -# define STATUS_INTEGER_DIVIDE_BY_ZERO ((NTSTATUS) 0xC0000094L) -#endif - -#ifndef STATUS_INTEGER_OVERFLOW -# define STATUS_INTEGER_OVERFLOW ((NTSTATUS) 0xC0000095L) -#endif - -#ifndef STATUS_PRIVILEGED_INSTRUCTION -# define STATUS_PRIVILEGED_INSTRUCTION ((NTSTATUS) 0xC0000096L) -#endif - -#ifndef STATUS_TOO_MANY_PAGING_FILES -# define STATUS_TOO_MANY_PAGING_FILES ((NTSTATUS) 0xC0000097L) -#endif - -#ifndef STATUS_FILE_INVALID -# define STATUS_FILE_INVALID ((NTSTATUS) 0xC0000098L) -#endif - -#ifndef STATUS_ALLOTTED_SPACE_EXCEEDED -# define STATUS_ALLOTTED_SPACE_EXCEEDED ((NTSTATUS) 0xC0000099L) -#endif - -#ifndef STATUS_INSUFFICIENT_RESOURCES -# define STATUS_INSUFFICIENT_RESOURCES ((NTSTATUS) 0xC000009AL) -#endif - -#ifndef STATUS_DFS_EXIT_PATH_FOUND -# define STATUS_DFS_EXIT_PATH_FOUND ((NTSTATUS) 0xC000009BL) -#endif - -#ifndef STATUS_DEVICE_DATA_ERROR -# define STATUS_DEVICE_DATA_ERROR ((NTSTATUS) 0xC000009CL) -#endif - -#ifndef STATUS_DEVICE_NOT_CONNECTED -# define STATUS_DEVICE_NOT_CONNECTED ((NTSTATUS) 0xC000009DL) -#endif - -#ifndef STATUS_DEVICE_POWER_FAILURE -# define STATUS_DEVICE_POWER_FAILURE ((NTSTATUS) 0xC000009EL) -#endif - -#ifndef STATUS_FREE_VM_NOT_AT_BASE -# define STATUS_FREE_VM_NOT_AT_BASE ((NTSTATUS) 0xC000009FL) -#endif - -#ifndef STATUS_MEMORY_NOT_ALLOCATED -# define STATUS_MEMORY_NOT_ALLOCATED ((NTSTATUS) 0xC00000A0L) -#endif - -#ifndef STATUS_WORKING_SET_QUOTA -# define STATUS_WORKING_SET_QUOTA ((NTSTATUS) 0xC00000A1L) -#endif - -#ifndef STATUS_MEDIA_WRITE_PROTECTED -# define STATUS_MEDIA_WRITE_PROTECTED ((NTSTATUS) 0xC00000A2L) -#endif - -#ifndef STATUS_DEVICE_NOT_READY -# define STATUS_DEVICE_NOT_READY ((NTSTATUS) 0xC00000A3L) -#endif - -#ifndef STATUS_INVALID_GROUP_ATTRIBUTES -# define STATUS_INVALID_GROUP_ATTRIBUTES ((NTSTATUS) 0xC00000A4L) -#endif - -#ifndef STATUS_BAD_IMPERSONATION_LEVEL -# define STATUS_BAD_IMPERSONATION_LEVEL ((NTSTATUS) 0xC00000A5L) -#endif - -#ifndef STATUS_CANT_OPEN_ANONYMOUS -# define STATUS_CANT_OPEN_ANONYMOUS ((NTSTATUS) 0xC00000A6L) -#endif - -#ifndef STATUS_BAD_VALIDATION_CLASS -# define STATUS_BAD_VALIDATION_CLASS ((NTSTATUS) 0xC00000A7L) -#endif - -#ifndef STATUS_BAD_TOKEN_TYPE -# define STATUS_BAD_TOKEN_TYPE ((NTSTATUS) 0xC00000A8L) -#endif - -#ifndef STATUS_BAD_MASTER_BOOT_RECORD -# define STATUS_BAD_MASTER_BOOT_RECORD ((NTSTATUS) 0xC00000A9L) -#endif - -#ifndef STATUS_INSTRUCTION_MISALIGNMENT -# define STATUS_INSTRUCTION_MISALIGNMENT ((NTSTATUS) 0xC00000AAL) -#endif - -#ifndef STATUS_INSTANCE_NOT_AVAILABLE -# define STATUS_INSTANCE_NOT_AVAILABLE ((NTSTATUS) 0xC00000ABL) -#endif - -#ifndef STATUS_PIPE_NOT_AVAILABLE -# define STATUS_PIPE_NOT_AVAILABLE ((NTSTATUS) 0xC00000ACL) -#endif - -#ifndef STATUS_INVALID_PIPE_STATE -# define STATUS_INVALID_PIPE_STATE ((NTSTATUS) 0xC00000ADL) -#endif - -#ifndef STATUS_PIPE_BUSY -# define STATUS_PIPE_BUSY ((NTSTATUS) 0xC00000AEL) -#endif - -#ifndef STATUS_ILLEGAL_FUNCTION -# define STATUS_ILLEGAL_FUNCTION ((NTSTATUS) 0xC00000AFL) -#endif - -#ifndef STATUS_PIPE_DISCONNECTED -# define STATUS_PIPE_DISCONNECTED ((NTSTATUS) 0xC00000B0L) -#endif - -#ifndef STATUS_PIPE_CLOSING -# define STATUS_PIPE_CLOSING ((NTSTATUS) 0xC00000B1L) -#endif - -#ifndef STATUS_PIPE_CONNECTED -# define STATUS_PIPE_CONNECTED ((NTSTATUS) 0xC00000B2L) -#endif - -#ifndef STATUS_PIPE_LISTENING -# define STATUS_PIPE_LISTENING ((NTSTATUS) 0xC00000B3L) -#endif - -#ifndef STATUS_INVALID_READ_MODE -# define STATUS_INVALID_READ_MODE ((NTSTATUS) 0xC00000B4L) -#endif - -#ifndef STATUS_IO_TIMEOUT -# define STATUS_IO_TIMEOUT ((NTSTATUS) 0xC00000B5L) -#endif - -#ifndef STATUS_FILE_FORCED_CLOSED -# define STATUS_FILE_FORCED_CLOSED ((NTSTATUS) 0xC00000B6L) -#endif - -#ifndef STATUS_PROFILING_NOT_STARTED -# define STATUS_PROFILING_NOT_STARTED ((NTSTATUS) 0xC00000B7L) -#endif - -#ifndef STATUS_PROFILING_NOT_STOPPED -# define STATUS_PROFILING_NOT_STOPPED ((NTSTATUS) 0xC00000B8L) -#endif - -#ifndef STATUS_COULD_NOT_INTERPRET -# define STATUS_COULD_NOT_INTERPRET ((NTSTATUS) 0xC00000B9L) -#endif - -#ifndef STATUS_FILE_IS_A_DIRECTORY -# define STATUS_FILE_IS_A_DIRECTORY ((NTSTATUS) 0xC00000BAL) -#endif - -#ifndef STATUS_NOT_SUPPORTED -# define STATUS_NOT_SUPPORTED ((NTSTATUS) 0xC00000BBL) -#endif - -#ifndef STATUS_REMOTE_NOT_LISTENING -# define STATUS_REMOTE_NOT_LISTENING ((NTSTATUS) 0xC00000BCL) -#endif - -#ifndef STATUS_DUPLICATE_NAME -# define STATUS_DUPLICATE_NAME ((NTSTATUS) 0xC00000BDL) -#endif - -#ifndef STATUS_BAD_NETWORK_PATH -# define STATUS_BAD_NETWORK_PATH ((NTSTATUS) 0xC00000BEL) -#endif - -#ifndef STATUS_NETWORK_BUSY -# define STATUS_NETWORK_BUSY ((NTSTATUS) 0xC00000BFL) -#endif - -#ifndef STATUS_DEVICE_DOES_NOT_EXIST -# define STATUS_DEVICE_DOES_NOT_EXIST ((NTSTATUS) 0xC00000C0L) -#endif - -#ifndef STATUS_TOO_MANY_COMMANDS -# define STATUS_TOO_MANY_COMMANDS ((NTSTATUS) 0xC00000C1L) -#endif - -#ifndef STATUS_ADAPTER_HARDWARE_ERROR -# define STATUS_ADAPTER_HARDWARE_ERROR ((NTSTATUS) 0xC00000C2L) -#endif - -#ifndef STATUS_INVALID_NETWORK_RESPONSE -# define STATUS_INVALID_NETWORK_RESPONSE ((NTSTATUS) 0xC00000C3L) -#endif - -#ifndef STATUS_UNEXPECTED_NETWORK_ERROR -# define STATUS_UNEXPECTED_NETWORK_ERROR ((NTSTATUS) 0xC00000C4L) -#endif - -#ifndef STATUS_BAD_REMOTE_ADAPTER -# define STATUS_BAD_REMOTE_ADAPTER ((NTSTATUS) 0xC00000C5L) -#endif - -#ifndef STATUS_PRINT_QUEUE_FULL -# define STATUS_PRINT_QUEUE_FULL ((NTSTATUS) 0xC00000C6L) -#endif - -#ifndef STATUS_NO_SPOOL_SPACE -# define STATUS_NO_SPOOL_SPACE ((NTSTATUS) 0xC00000C7L) -#endif - -#ifndef STATUS_PRINT_CANCELLED -# define STATUS_PRINT_CANCELLED ((NTSTATUS) 0xC00000C8L) -#endif - -#ifndef STATUS_NETWORK_NAME_DELETED -# define STATUS_NETWORK_NAME_DELETED ((NTSTATUS) 0xC00000C9L) -#endif - -#ifndef STATUS_NETWORK_ACCESS_DENIED -# define STATUS_NETWORK_ACCESS_DENIED ((NTSTATUS) 0xC00000CAL) -#endif - -#ifndef STATUS_BAD_DEVICE_TYPE -# define STATUS_BAD_DEVICE_TYPE ((NTSTATUS) 0xC00000CBL) -#endif - -#ifndef STATUS_BAD_NETWORK_NAME -# define STATUS_BAD_NETWORK_NAME ((NTSTATUS) 0xC00000CCL) -#endif - -#ifndef STATUS_TOO_MANY_NAMES -# define STATUS_TOO_MANY_NAMES ((NTSTATUS) 0xC00000CDL) -#endif - -#ifndef STATUS_TOO_MANY_SESSIONS -# define STATUS_TOO_MANY_SESSIONS ((NTSTATUS) 0xC00000CEL) -#endif - -#ifndef STATUS_SHARING_PAUSED -# define STATUS_SHARING_PAUSED ((NTSTATUS) 0xC00000CFL) -#endif - -#ifndef STATUS_REQUEST_NOT_ACCEPTED -# define STATUS_REQUEST_NOT_ACCEPTED ((NTSTATUS) 0xC00000D0L) -#endif - -#ifndef STATUS_REDIRECTOR_PAUSED -# define STATUS_REDIRECTOR_PAUSED ((NTSTATUS) 0xC00000D1L) -#endif - -#ifndef STATUS_NET_WRITE_FAULT -# define STATUS_NET_WRITE_FAULT ((NTSTATUS) 0xC00000D2L) -#endif - -#ifndef STATUS_PROFILING_AT_LIMIT -# define STATUS_PROFILING_AT_LIMIT ((NTSTATUS) 0xC00000D3L) -#endif - -#ifndef STATUS_NOT_SAME_DEVICE -# define STATUS_NOT_SAME_DEVICE ((NTSTATUS) 0xC00000D4L) -#endif - -#ifndef STATUS_FILE_RENAMED -# define STATUS_FILE_RENAMED ((NTSTATUS) 0xC00000D5L) -#endif - -#ifndef STATUS_VIRTUAL_CIRCUIT_CLOSED -# define STATUS_VIRTUAL_CIRCUIT_CLOSED ((NTSTATUS) 0xC00000D6L) -#endif - -#ifndef STATUS_NO_SECURITY_ON_OBJECT -# define STATUS_NO_SECURITY_ON_OBJECT ((NTSTATUS) 0xC00000D7L) -#endif - -#ifndef STATUS_CANT_WAIT -# define STATUS_CANT_WAIT ((NTSTATUS) 0xC00000D8L) -#endif - -#ifndef STATUS_PIPE_EMPTY -# define STATUS_PIPE_EMPTY ((NTSTATUS) 0xC00000D9L) -#endif - -#ifndef STATUS_CANT_ACCESS_DOMAIN_INFO -# define STATUS_CANT_ACCESS_DOMAIN_INFO ((NTSTATUS) 0xC00000DAL) -#endif - -#ifndef STATUS_CANT_TERMINATE_SELF -# define STATUS_CANT_TERMINATE_SELF ((NTSTATUS) 0xC00000DBL) -#endif - -#ifndef STATUS_INVALID_SERVER_STATE -# define STATUS_INVALID_SERVER_STATE ((NTSTATUS) 0xC00000DCL) -#endif - -#ifndef STATUS_INVALID_DOMAIN_STATE -# define STATUS_INVALID_DOMAIN_STATE ((NTSTATUS) 0xC00000DDL) -#endif - -#ifndef STATUS_INVALID_DOMAIN_ROLE -# define STATUS_INVALID_DOMAIN_ROLE ((NTSTATUS) 0xC00000DEL) -#endif - -#ifndef STATUS_NO_SUCH_DOMAIN -# define STATUS_NO_SUCH_DOMAIN ((NTSTATUS) 0xC00000DFL) -#endif - -#ifndef STATUS_DOMAIN_EXISTS -# define STATUS_DOMAIN_EXISTS ((NTSTATUS) 0xC00000E0L) -#endif - -#ifndef STATUS_DOMAIN_LIMIT_EXCEEDED -# define STATUS_DOMAIN_LIMIT_EXCEEDED ((NTSTATUS) 0xC00000E1L) -#endif - -#ifndef STATUS_OPLOCK_NOT_GRANTED -# define STATUS_OPLOCK_NOT_GRANTED ((NTSTATUS) 0xC00000E2L) -#endif - -#ifndef STATUS_INVALID_OPLOCK_PROTOCOL -# define STATUS_INVALID_OPLOCK_PROTOCOL ((NTSTATUS) 0xC00000E3L) -#endif - -#ifndef STATUS_INTERNAL_DB_CORRUPTION -# define STATUS_INTERNAL_DB_CORRUPTION ((NTSTATUS) 0xC00000E4L) -#endif - -#ifndef STATUS_INTERNAL_ERROR -# define STATUS_INTERNAL_ERROR ((NTSTATUS) 0xC00000E5L) -#endif - -#ifndef STATUS_GENERIC_NOT_MAPPED -# define STATUS_GENERIC_NOT_MAPPED ((NTSTATUS) 0xC00000E6L) -#endif - -#ifndef STATUS_BAD_DESCRIPTOR_FORMAT -# define STATUS_BAD_DESCRIPTOR_FORMAT ((NTSTATUS) 0xC00000E7L) -#endif - -#ifndef STATUS_INVALID_USER_BUFFER -# define STATUS_INVALID_USER_BUFFER ((NTSTATUS) 0xC00000E8L) -#endif - -#ifndef STATUS_UNEXPECTED_IO_ERROR -# define STATUS_UNEXPECTED_IO_ERROR ((NTSTATUS) 0xC00000E9L) -#endif - -#ifndef STATUS_UNEXPECTED_MM_CREATE_ERR -# define STATUS_UNEXPECTED_MM_CREATE_ERR ((NTSTATUS) 0xC00000EAL) -#endif - -#ifndef STATUS_UNEXPECTED_MM_MAP_ERROR -# define STATUS_UNEXPECTED_MM_MAP_ERROR ((NTSTATUS) 0xC00000EBL) -#endif - -#ifndef STATUS_UNEXPECTED_MM_EXTEND_ERR -# define STATUS_UNEXPECTED_MM_EXTEND_ERR ((NTSTATUS) 0xC00000ECL) -#endif - -#ifndef STATUS_NOT_LOGON_PROCESS -# define STATUS_NOT_LOGON_PROCESS ((NTSTATUS) 0xC00000EDL) -#endif - -#ifndef STATUS_LOGON_SESSION_EXISTS -# define STATUS_LOGON_SESSION_EXISTS ((NTSTATUS) 0xC00000EEL) -#endif - -#ifndef STATUS_INVALID_PARAMETER_1 -# define STATUS_INVALID_PARAMETER_1 ((NTSTATUS) 0xC00000EFL) -#endif - -#ifndef STATUS_INVALID_PARAMETER_2 -# define STATUS_INVALID_PARAMETER_2 ((NTSTATUS) 0xC00000F0L) -#endif - -#ifndef STATUS_INVALID_PARAMETER_3 -# define STATUS_INVALID_PARAMETER_3 ((NTSTATUS) 0xC00000F1L) -#endif - -#ifndef STATUS_INVALID_PARAMETER_4 -# define STATUS_INVALID_PARAMETER_4 ((NTSTATUS) 0xC00000F2L) -#endif - -#ifndef STATUS_INVALID_PARAMETER_5 -# define STATUS_INVALID_PARAMETER_5 ((NTSTATUS) 0xC00000F3L) -#endif - -#ifndef STATUS_INVALID_PARAMETER_6 -# define STATUS_INVALID_PARAMETER_6 ((NTSTATUS) 0xC00000F4L) -#endif - -#ifndef STATUS_INVALID_PARAMETER_7 -# define STATUS_INVALID_PARAMETER_7 ((NTSTATUS) 0xC00000F5L) -#endif - -#ifndef STATUS_INVALID_PARAMETER_8 -# define STATUS_INVALID_PARAMETER_8 ((NTSTATUS) 0xC00000F6L) -#endif - -#ifndef STATUS_INVALID_PARAMETER_9 -# define STATUS_INVALID_PARAMETER_9 ((NTSTATUS) 0xC00000F7L) -#endif - -#ifndef STATUS_INVALID_PARAMETER_10 -# define STATUS_INVALID_PARAMETER_10 ((NTSTATUS) 0xC00000F8L) -#endif - -#ifndef STATUS_INVALID_PARAMETER_11 -# define STATUS_INVALID_PARAMETER_11 ((NTSTATUS) 0xC00000F9L) -#endif - -#ifndef STATUS_INVALID_PARAMETER_12 -# define STATUS_INVALID_PARAMETER_12 ((NTSTATUS) 0xC00000FAL) -#endif - -#ifndef STATUS_REDIRECTOR_NOT_STARTED -# define STATUS_REDIRECTOR_NOT_STARTED ((NTSTATUS) 0xC00000FBL) -#endif - -#ifndef STATUS_REDIRECTOR_STARTED -# define STATUS_REDIRECTOR_STARTED ((NTSTATUS) 0xC00000FCL) -#endif - -#ifndef STATUS_STACK_OVERFLOW -# define STATUS_STACK_OVERFLOW ((NTSTATUS) 0xC00000FDL) -#endif - -#ifndef STATUS_NO_SUCH_PACKAGE -# define STATUS_NO_SUCH_PACKAGE ((NTSTATUS) 0xC00000FEL) -#endif - -#ifndef STATUS_BAD_FUNCTION_TABLE -# define STATUS_BAD_FUNCTION_TABLE ((NTSTATUS) 0xC00000FFL) -#endif - -#ifndef STATUS_VARIABLE_NOT_FOUND -# define STATUS_VARIABLE_NOT_FOUND ((NTSTATUS) 0xC0000100L) -#endif - -#ifndef STATUS_DIRECTORY_NOT_EMPTY -# define STATUS_DIRECTORY_NOT_EMPTY ((NTSTATUS) 0xC0000101L) -#endif - -#ifndef STATUS_FILE_CORRUPT_ERROR -# define STATUS_FILE_CORRUPT_ERROR ((NTSTATUS) 0xC0000102L) -#endif - -#ifndef STATUS_NOT_A_DIRECTORY -# define STATUS_NOT_A_DIRECTORY ((NTSTATUS) 0xC0000103L) -#endif - -#ifndef STATUS_BAD_LOGON_SESSION_STATE -# define STATUS_BAD_LOGON_SESSION_STATE ((NTSTATUS) 0xC0000104L) -#endif - -#ifndef STATUS_LOGON_SESSION_COLLISION -# define STATUS_LOGON_SESSION_COLLISION ((NTSTATUS) 0xC0000105L) -#endif - -#ifndef STATUS_NAME_TOO_LONG -# define STATUS_NAME_TOO_LONG ((NTSTATUS) 0xC0000106L) -#endif - -#ifndef STATUS_FILES_OPEN -# define STATUS_FILES_OPEN ((NTSTATUS) 0xC0000107L) -#endif - -#ifndef STATUS_CONNECTION_IN_USE -# define STATUS_CONNECTION_IN_USE ((NTSTATUS) 0xC0000108L) -#endif - -#ifndef STATUS_MESSAGE_NOT_FOUND -# define STATUS_MESSAGE_NOT_FOUND ((NTSTATUS) 0xC0000109L) -#endif - -#ifndef STATUS_PROCESS_IS_TERMINATING -# define STATUS_PROCESS_IS_TERMINATING ((NTSTATUS) 0xC000010AL) -#endif - -#ifndef STATUS_INVALID_LOGON_TYPE -# define STATUS_INVALID_LOGON_TYPE ((NTSTATUS) 0xC000010BL) -#endif - -#ifndef STATUS_NO_GUID_TRANSLATION -# define STATUS_NO_GUID_TRANSLATION ((NTSTATUS) 0xC000010CL) -#endif - -#ifndef STATUS_CANNOT_IMPERSONATE -# define STATUS_CANNOT_IMPERSONATE ((NTSTATUS) 0xC000010DL) -#endif - -#ifndef STATUS_IMAGE_ALREADY_LOADED -# define STATUS_IMAGE_ALREADY_LOADED ((NTSTATUS) 0xC000010EL) -#endif - -#ifndef STATUS_ABIOS_NOT_PRESENT -# define STATUS_ABIOS_NOT_PRESENT ((NTSTATUS) 0xC000010FL) -#endif - -#ifndef STATUS_ABIOS_LID_NOT_EXIST -# define STATUS_ABIOS_LID_NOT_EXIST ((NTSTATUS) 0xC0000110L) -#endif - -#ifndef STATUS_ABIOS_LID_ALREADY_OWNED -# define STATUS_ABIOS_LID_ALREADY_OWNED ((NTSTATUS) 0xC0000111L) -#endif - -#ifndef STATUS_ABIOS_NOT_LID_OWNER -# define STATUS_ABIOS_NOT_LID_OWNER ((NTSTATUS) 0xC0000112L) -#endif - -#ifndef STATUS_ABIOS_INVALID_COMMAND -# define STATUS_ABIOS_INVALID_COMMAND ((NTSTATUS) 0xC0000113L) -#endif - -#ifndef STATUS_ABIOS_INVALID_LID -# define STATUS_ABIOS_INVALID_LID ((NTSTATUS) 0xC0000114L) -#endif - -#ifndef STATUS_ABIOS_SELECTOR_NOT_AVAILABLE -# define STATUS_ABIOS_SELECTOR_NOT_AVAILABLE ((NTSTATUS) 0xC0000115L) -#endif - -#ifndef STATUS_ABIOS_INVALID_SELECTOR -# define STATUS_ABIOS_INVALID_SELECTOR ((NTSTATUS) 0xC0000116L) -#endif - -#ifndef STATUS_NO_LDT -# define STATUS_NO_LDT ((NTSTATUS) 0xC0000117L) -#endif - -#ifndef STATUS_INVALID_LDT_SIZE -# define STATUS_INVALID_LDT_SIZE ((NTSTATUS) 0xC0000118L) -#endif - -#ifndef STATUS_INVALID_LDT_OFFSET -# define STATUS_INVALID_LDT_OFFSET ((NTSTATUS) 0xC0000119L) -#endif - -#ifndef STATUS_INVALID_LDT_DESCRIPTOR -# define STATUS_INVALID_LDT_DESCRIPTOR ((NTSTATUS) 0xC000011AL) -#endif - -#ifndef STATUS_INVALID_IMAGE_NE_FORMAT -# define STATUS_INVALID_IMAGE_NE_FORMAT ((NTSTATUS) 0xC000011BL) -#endif - -#ifndef STATUS_RXACT_INVALID_STATE -# define STATUS_RXACT_INVALID_STATE ((NTSTATUS) 0xC000011CL) -#endif - -#ifndef STATUS_RXACT_COMMIT_FAILURE -# define STATUS_RXACT_COMMIT_FAILURE ((NTSTATUS) 0xC000011DL) -#endif - -#ifndef STATUS_MAPPED_FILE_SIZE_ZERO -# define STATUS_MAPPED_FILE_SIZE_ZERO ((NTSTATUS) 0xC000011EL) -#endif - -#ifndef STATUS_TOO_MANY_OPENED_FILES -# define STATUS_TOO_MANY_OPENED_FILES ((NTSTATUS) 0xC000011FL) -#endif - -#ifndef STATUS_CANCELLED -# define STATUS_CANCELLED ((NTSTATUS) 0xC0000120L) -#endif - -#ifndef STATUS_CANNOT_DELETE -# define STATUS_CANNOT_DELETE ((NTSTATUS) 0xC0000121L) -#endif - -#ifndef STATUS_INVALID_COMPUTER_NAME -# define STATUS_INVALID_COMPUTER_NAME ((NTSTATUS) 0xC0000122L) -#endif - -#ifndef STATUS_FILE_DELETED -# define STATUS_FILE_DELETED ((NTSTATUS) 0xC0000123L) -#endif - -#ifndef STATUS_SPECIAL_ACCOUNT -# define STATUS_SPECIAL_ACCOUNT ((NTSTATUS) 0xC0000124L) -#endif - -#ifndef STATUS_SPECIAL_GROUP -# define STATUS_SPECIAL_GROUP ((NTSTATUS) 0xC0000125L) -#endif - -#ifndef STATUS_SPECIAL_USER -# define STATUS_SPECIAL_USER ((NTSTATUS) 0xC0000126L) -#endif - -#ifndef STATUS_MEMBERS_PRIMARY_GROUP -# define STATUS_MEMBERS_PRIMARY_GROUP ((NTSTATUS) 0xC0000127L) -#endif - -#ifndef STATUS_FILE_CLOSED -# define STATUS_FILE_CLOSED ((NTSTATUS) 0xC0000128L) -#endif - -#ifndef STATUS_TOO_MANY_THREADS -# define STATUS_TOO_MANY_THREADS ((NTSTATUS) 0xC0000129L) -#endif - -#ifndef STATUS_THREAD_NOT_IN_PROCESS -# define STATUS_THREAD_NOT_IN_PROCESS ((NTSTATUS) 0xC000012AL) -#endif - -#ifndef STATUS_TOKEN_ALREADY_IN_USE -# define STATUS_TOKEN_ALREADY_IN_USE ((NTSTATUS) 0xC000012BL) -#endif - -#ifndef STATUS_PAGEFILE_QUOTA_EXCEEDED -# define STATUS_PAGEFILE_QUOTA_EXCEEDED ((NTSTATUS) 0xC000012CL) -#endif - -#ifndef STATUS_COMMITMENT_LIMIT -# define STATUS_COMMITMENT_LIMIT ((NTSTATUS) 0xC000012DL) -#endif - -#ifndef STATUS_INVALID_IMAGE_LE_FORMAT -# define STATUS_INVALID_IMAGE_LE_FORMAT ((NTSTATUS) 0xC000012EL) -#endif - -#ifndef STATUS_INVALID_IMAGE_NOT_MZ -# define STATUS_INVALID_IMAGE_NOT_MZ ((NTSTATUS) 0xC000012FL) -#endif - -#ifndef STATUS_INVALID_IMAGE_PROTECT -# define STATUS_INVALID_IMAGE_PROTECT ((NTSTATUS) 0xC0000130L) -#endif - -#ifndef STATUS_INVALID_IMAGE_WIN_16 -# define STATUS_INVALID_IMAGE_WIN_16 ((NTSTATUS) 0xC0000131L) -#endif - -#ifndef STATUS_LOGON_SERVER_CONFLICT -# define STATUS_LOGON_SERVER_CONFLICT ((NTSTATUS) 0xC0000132L) -#endif - -#ifndef STATUS_TIME_DIFFERENCE_AT_DC -# define STATUS_TIME_DIFFERENCE_AT_DC ((NTSTATUS) 0xC0000133L) -#endif - -#ifndef STATUS_SYNCHRONIZATION_REQUIRED -# define STATUS_SYNCHRONIZATION_REQUIRED ((NTSTATUS) 0xC0000134L) -#endif - -#ifndef STATUS_DLL_NOT_FOUND -# define STATUS_DLL_NOT_FOUND ((NTSTATUS) 0xC0000135L) -#endif - -#ifndef STATUS_OPEN_FAILED -# define STATUS_OPEN_FAILED ((NTSTATUS) 0xC0000136L) -#endif - -#ifndef STATUS_IO_PRIVILEGE_FAILED -# define STATUS_IO_PRIVILEGE_FAILED ((NTSTATUS) 0xC0000137L) -#endif - -#ifndef STATUS_ORDINAL_NOT_FOUND -# define STATUS_ORDINAL_NOT_FOUND ((NTSTATUS) 0xC0000138L) -#endif - -#ifndef STATUS_ENTRYPOINT_NOT_FOUND -# define STATUS_ENTRYPOINT_NOT_FOUND ((NTSTATUS) 0xC0000139L) -#endif - -#ifndef STATUS_CONTROL_C_EXIT -# define STATUS_CONTROL_C_EXIT ((NTSTATUS) 0xC000013AL) -#endif - -#ifndef STATUS_LOCAL_DISCONNECT -# define STATUS_LOCAL_DISCONNECT ((NTSTATUS) 0xC000013BL) -#endif - -#ifndef STATUS_REMOTE_DISCONNECT -# define STATUS_REMOTE_DISCONNECT ((NTSTATUS) 0xC000013CL) -#endif - -#ifndef STATUS_REMOTE_RESOURCES -# define STATUS_REMOTE_RESOURCES ((NTSTATUS) 0xC000013DL) -#endif - -#ifndef STATUS_LINK_FAILED -# define STATUS_LINK_FAILED ((NTSTATUS) 0xC000013EL) -#endif - -#ifndef STATUS_LINK_TIMEOUT -# define STATUS_LINK_TIMEOUT ((NTSTATUS) 0xC000013FL) -#endif - -#ifndef STATUS_INVALID_CONNECTION -# define STATUS_INVALID_CONNECTION ((NTSTATUS) 0xC0000140L) -#endif - -#ifndef STATUS_INVALID_ADDRESS -# define STATUS_INVALID_ADDRESS ((NTSTATUS) 0xC0000141L) -#endif - -#ifndef STATUS_DLL_INIT_FAILED -# define STATUS_DLL_INIT_FAILED ((NTSTATUS) 0xC0000142L) -#endif - -#ifndef STATUS_MISSING_SYSTEMFILE -# define STATUS_MISSING_SYSTEMFILE ((NTSTATUS) 0xC0000143L) -#endif - -#ifndef STATUS_UNHANDLED_EXCEPTION -# define STATUS_UNHANDLED_EXCEPTION ((NTSTATUS) 0xC0000144L) -#endif - -#ifndef STATUS_APP_INIT_FAILURE -# define STATUS_APP_INIT_FAILURE ((NTSTATUS) 0xC0000145L) -#endif - -#ifndef STATUS_PAGEFILE_CREATE_FAILED -# define STATUS_PAGEFILE_CREATE_FAILED ((NTSTATUS) 0xC0000146L) -#endif - -#ifndef STATUS_NO_PAGEFILE -# define STATUS_NO_PAGEFILE ((NTSTATUS) 0xC0000147L) -#endif - -#ifndef STATUS_INVALID_LEVEL -# define STATUS_INVALID_LEVEL ((NTSTATUS) 0xC0000148L) -#endif - -#ifndef STATUS_WRONG_PASSWORD_CORE -# define STATUS_WRONG_PASSWORD_CORE ((NTSTATUS) 0xC0000149L) -#endif - -#ifndef STATUS_ILLEGAL_FLOAT_CONTEXT -# define STATUS_ILLEGAL_FLOAT_CONTEXT ((NTSTATUS) 0xC000014AL) -#endif - -#ifndef STATUS_PIPE_BROKEN -# define STATUS_PIPE_BROKEN ((NTSTATUS) 0xC000014BL) -#endif - -#ifndef STATUS_REGISTRY_CORRUPT -# define STATUS_REGISTRY_CORRUPT ((NTSTATUS) 0xC000014CL) -#endif - -#ifndef STATUS_REGISTRY_IO_FAILED -# define STATUS_REGISTRY_IO_FAILED ((NTSTATUS) 0xC000014DL) -#endif - -#ifndef STATUS_NO_EVENT_PAIR -# define STATUS_NO_EVENT_PAIR ((NTSTATUS) 0xC000014EL) -#endif - -#ifndef STATUS_UNRECOGNIZED_VOLUME -# define STATUS_UNRECOGNIZED_VOLUME ((NTSTATUS) 0xC000014FL) -#endif - -#ifndef STATUS_SERIAL_NO_DEVICE_INITED -# define STATUS_SERIAL_NO_DEVICE_INITED ((NTSTATUS) 0xC0000150L) -#endif - -#ifndef STATUS_NO_SUCH_ALIAS -# define STATUS_NO_SUCH_ALIAS ((NTSTATUS) 0xC0000151L) -#endif - -#ifndef STATUS_MEMBER_NOT_IN_ALIAS -# define STATUS_MEMBER_NOT_IN_ALIAS ((NTSTATUS) 0xC0000152L) -#endif - -#ifndef STATUS_MEMBER_IN_ALIAS -# define STATUS_MEMBER_IN_ALIAS ((NTSTATUS) 0xC0000153L) -#endif - -#ifndef STATUS_ALIAS_EXISTS -# define STATUS_ALIAS_EXISTS ((NTSTATUS) 0xC0000154L) -#endif - -#ifndef STATUS_LOGON_NOT_GRANTED -# define STATUS_LOGON_NOT_GRANTED ((NTSTATUS) 0xC0000155L) -#endif - -#ifndef STATUS_TOO_MANY_SECRETS -# define STATUS_TOO_MANY_SECRETS ((NTSTATUS) 0xC0000156L) -#endif - -#ifndef STATUS_SECRET_TOO_LONG -# define STATUS_SECRET_TOO_LONG ((NTSTATUS) 0xC0000157L) -#endif - -#ifndef STATUS_INTERNAL_DB_ERROR -# define STATUS_INTERNAL_DB_ERROR ((NTSTATUS) 0xC0000158L) -#endif - -#ifndef STATUS_FULLSCREEN_MODE -# define STATUS_FULLSCREEN_MODE ((NTSTATUS) 0xC0000159L) -#endif - -#ifndef STATUS_TOO_MANY_CONTEXT_IDS -# define STATUS_TOO_MANY_CONTEXT_IDS ((NTSTATUS) 0xC000015AL) -#endif - -#ifndef STATUS_LOGON_TYPE_NOT_GRANTED -# define STATUS_LOGON_TYPE_NOT_GRANTED ((NTSTATUS) 0xC000015BL) -#endif - -#ifndef STATUS_NOT_REGISTRY_FILE -# define STATUS_NOT_REGISTRY_FILE ((NTSTATUS) 0xC000015CL) -#endif - -#ifndef STATUS_NT_CROSS_ENCRYPTION_REQUIRED -# define STATUS_NT_CROSS_ENCRYPTION_REQUIRED ((NTSTATUS) 0xC000015DL) -#endif - -#ifndef STATUS_DOMAIN_CTRLR_CONFIG_ERROR -# define STATUS_DOMAIN_CTRLR_CONFIG_ERROR ((NTSTATUS) 0xC000015EL) -#endif - -#ifndef STATUS_FT_MISSING_MEMBER -# define STATUS_FT_MISSING_MEMBER ((NTSTATUS) 0xC000015FL) -#endif - -#ifndef STATUS_ILL_FORMED_SERVICE_ENTRY -# define STATUS_ILL_FORMED_SERVICE_ENTRY ((NTSTATUS) 0xC0000160L) -#endif - -#ifndef STATUS_ILLEGAL_CHARACTER -# define STATUS_ILLEGAL_CHARACTER ((NTSTATUS) 0xC0000161L) -#endif - -#ifndef STATUS_UNMAPPABLE_CHARACTER -# define STATUS_UNMAPPABLE_CHARACTER ((NTSTATUS) 0xC0000162L) -#endif - -#ifndef STATUS_UNDEFINED_CHARACTER -# define STATUS_UNDEFINED_CHARACTER ((NTSTATUS) 0xC0000163L) -#endif - -#ifndef STATUS_FLOPPY_VOLUME -# define STATUS_FLOPPY_VOLUME ((NTSTATUS) 0xC0000164L) -#endif - -#ifndef STATUS_FLOPPY_ID_MARK_NOT_FOUND -# define STATUS_FLOPPY_ID_MARK_NOT_FOUND ((NTSTATUS) 0xC0000165L) -#endif - -#ifndef STATUS_FLOPPY_WRONG_CYLINDER -# define STATUS_FLOPPY_WRONG_CYLINDER ((NTSTATUS) 0xC0000166L) -#endif - -#ifndef STATUS_FLOPPY_UNKNOWN_ERROR -# define STATUS_FLOPPY_UNKNOWN_ERROR ((NTSTATUS) 0xC0000167L) -#endif - -#ifndef STATUS_FLOPPY_BAD_REGISTERS -# define STATUS_FLOPPY_BAD_REGISTERS ((NTSTATUS) 0xC0000168L) -#endif - -#ifndef STATUS_DISK_RECALIBRATE_FAILED -# define STATUS_DISK_RECALIBRATE_FAILED ((NTSTATUS) 0xC0000169L) -#endif - -#ifndef STATUS_DISK_OPERATION_FAILED -# define STATUS_DISK_OPERATION_FAILED ((NTSTATUS) 0xC000016AL) -#endif - -#ifndef STATUS_DISK_RESET_FAILED -# define STATUS_DISK_RESET_FAILED ((NTSTATUS) 0xC000016BL) -#endif - -#ifndef STATUS_SHARED_IRQ_BUSY -# define STATUS_SHARED_IRQ_BUSY ((NTSTATUS) 0xC000016CL) -#endif - -#ifndef STATUS_FT_ORPHANING -# define STATUS_FT_ORPHANING ((NTSTATUS) 0xC000016DL) -#endif - -#ifndef STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT -# define STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT ((NTSTATUS) 0xC000016EL) -#endif - -#ifndef STATUS_PARTITION_FAILURE -# define STATUS_PARTITION_FAILURE ((NTSTATUS) 0xC0000172L) -#endif - -#ifndef STATUS_INVALID_BLOCK_LENGTH -# define STATUS_INVALID_BLOCK_LENGTH ((NTSTATUS) 0xC0000173L) -#endif - -#ifndef STATUS_DEVICE_NOT_PARTITIONED -# define STATUS_DEVICE_NOT_PARTITIONED ((NTSTATUS) 0xC0000174L) -#endif - -#ifndef STATUS_UNABLE_TO_LOCK_MEDIA -# define STATUS_UNABLE_TO_LOCK_MEDIA ((NTSTATUS) 0xC0000175L) -#endif - -#ifndef STATUS_UNABLE_TO_UNLOAD_MEDIA -# define STATUS_UNABLE_TO_UNLOAD_MEDIA ((NTSTATUS) 0xC0000176L) -#endif - -#ifndef STATUS_EOM_OVERFLOW -# define STATUS_EOM_OVERFLOW ((NTSTATUS) 0xC0000177L) -#endif - -#ifndef STATUS_NO_MEDIA -# define STATUS_NO_MEDIA ((NTSTATUS) 0xC0000178L) -#endif - -#ifndef STATUS_NO_SUCH_MEMBER -# define STATUS_NO_SUCH_MEMBER ((NTSTATUS) 0xC000017AL) -#endif - -#ifndef STATUS_INVALID_MEMBER -# define STATUS_INVALID_MEMBER ((NTSTATUS) 0xC000017BL) -#endif - -#ifndef STATUS_KEY_DELETED -# define STATUS_KEY_DELETED ((NTSTATUS) 0xC000017CL) -#endif - -#ifndef STATUS_NO_LOG_SPACE -# define STATUS_NO_LOG_SPACE ((NTSTATUS) 0xC000017DL) -#endif - -#ifndef STATUS_TOO_MANY_SIDS -# define STATUS_TOO_MANY_SIDS ((NTSTATUS) 0xC000017EL) -#endif - -#ifndef STATUS_LM_CROSS_ENCRYPTION_REQUIRED -# define STATUS_LM_CROSS_ENCRYPTION_REQUIRED ((NTSTATUS) 0xC000017FL) -#endif - -#ifndef STATUS_KEY_HAS_CHILDREN -# define STATUS_KEY_HAS_CHILDREN ((NTSTATUS) 0xC0000180L) -#endif - -#ifndef STATUS_CHILD_MUST_BE_VOLATILE -# define STATUS_CHILD_MUST_BE_VOLATILE ((NTSTATUS) 0xC0000181L) -#endif - -#ifndef STATUS_DEVICE_CONFIGURATION_ERROR -# define STATUS_DEVICE_CONFIGURATION_ERROR ((NTSTATUS) 0xC0000182L) -#endif - -#ifndef STATUS_DRIVER_INTERNAL_ERROR -# define STATUS_DRIVER_INTERNAL_ERROR ((NTSTATUS) 0xC0000183L) -#endif - -#ifndef STATUS_INVALID_DEVICE_STATE -# define STATUS_INVALID_DEVICE_STATE ((NTSTATUS) 0xC0000184L) -#endif - -#ifndef STATUS_IO_DEVICE_ERROR -# define STATUS_IO_DEVICE_ERROR ((NTSTATUS) 0xC0000185L) -#endif - -#ifndef STATUS_DEVICE_PROTOCOL_ERROR -# define STATUS_DEVICE_PROTOCOL_ERROR ((NTSTATUS) 0xC0000186L) -#endif - -#ifndef STATUS_BACKUP_CONTROLLER -# define STATUS_BACKUP_CONTROLLER ((NTSTATUS) 0xC0000187L) -#endif - -#ifndef STATUS_LOG_FILE_FULL -# define STATUS_LOG_FILE_FULL ((NTSTATUS) 0xC0000188L) -#endif - -#ifndef STATUS_TOO_LATE -# define STATUS_TOO_LATE ((NTSTATUS) 0xC0000189L) -#endif - -#ifndef STATUS_NO_TRUST_LSA_SECRET -# define STATUS_NO_TRUST_LSA_SECRET ((NTSTATUS) 0xC000018AL) -#endif - -#ifndef STATUS_NO_TRUST_SAM_ACCOUNT -# define STATUS_NO_TRUST_SAM_ACCOUNT ((NTSTATUS) 0xC000018BL) -#endif - -#ifndef STATUS_TRUSTED_DOMAIN_FAILURE -# define STATUS_TRUSTED_DOMAIN_FAILURE ((NTSTATUS) 0xC000018CL) -#endif - -#ifndef STATUS_TRUSTED_RELATIONSHIP_FAILURE -# define STATUS_TRUSTED_RELATIONSHIP_FAILURE ((NTSTATUS) 0xC000018DL) -#endif - -#ifndef STATUS_EVENTLOG_FILE_CORRUPT -# define STATUS_EVENTLOG_FILE_CORRUPT ((NTSTATUS) 0xC000018EL) -#endif - -#ifndef STATUS_EVENTLOG_CANT_START -# define STATUS_EVENTLOG_CANT_START ((NTSTATUS) 0xC000018FL) -#endif - -#ifndef STATUS_TRUST_FAILURE -# define STATUS_TRUST_FAILURE ((NTSTATUS) 0xC0000190L) -#endif - -#ifndef STATUS_MUTANT_LIMIT_EXCEEDED -# define STATUS_MUTANT_LIMIT_EXCEEDED ((NTSTATUS) 0xC0000191L) -#endif - -#ifndef STATUS_NETLOGON_NOT_STARTED -# define STATUS_NETLOGON_NOT_STARTED ((NTSTATUS) 0xC0000192L) -#endif - -#ifndef STATUS_ACCOUNT_EXPIRED -# define STATUS_ACCOUNT_EXPIRED ((NTSTATUS) 0xC0000193L) -#endif - -#ifndef STATUS_POSSIBLE_DEADLOCK -# define STATUS_POSSIBLE_DEADLOCK ((NTSTATUS) 0xC0000194L) -#endif - -#ifndef STATUS_NETWORK_CREDENTIAL_CONFLICT -# define STATUS_NETWORK_CREDENTIAL_CONFLICT ((NTSTATUS) 0xC0000195L) -#endif - -#ifndef STATUS_REMOTE_SESSION_LIMIT -# define STATUS_REMOTE_SESSION_LIMIT ((NTSTATUS) 0xC0000196L) -#endif - -#ifndef STATUS_EVENTLOG_FILE_CHANGED -# define STATUS_EVENTLOG_FILE_CHANGED ((NTSTATUS) 0xC0000197L) -#endif - -#ifndef STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT -# define STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT ((NTSTATUS) 0xC0000198L) -#endif - -#ifndef STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT -# define STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT ((NTSTATUS) 0xC0000199L) -#endif - -#ifndef STATUS_NOLOGON_SERVER_TRUST_ACCOUNT -# define STATUS_NOLOGON_SERVER_TRUST_ACCOUNT ((NTSTATUS) 0xC000019AL) -#endif - -#ifndef STATUS_DOMAIN_TRUST_INCONSISTENT -# define STATUS_DOMAIN_TRUST_INCONSISTENT ((NTSTATUS) 0xC000019BL) -#endif - -#ifndef STATUS_FS_DRIVER_REQUIRED -# define STATUS_FS_DRIVER_REQUIRED ((NTSTATUS) 0xC000019CL) -#endif - -#ifndef STATUS_IMAGE_ALREADY_LOADED_AS_DLL -# define STATUS_IMAGE_ALREADY_LOADED_AS_DLL ((NTSTATUS) 0xC000019DL) -#endif - -#ifndef STATUS_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING -# define STATUS_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING ((NTSTATUS) 0xC000019EL) -#endif - -#ifndef STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME -# define STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME ((NTSTATUS) 0xC000019FL) -#endif - -#ifndef STATUS_SECURITY_STREAM_IS_INCONSISTENT -# define STATUS_SECURITY_STREAM_IS_INCONSISTENT ((NTSTATUS) 0xC00001A0L) -#endif - -#ifndef STATUS_INVALID_LOCK_RANGE -# define STATUS_INVALID_LOCK_RANGE ((NTSTATUS) 0xC00001A1L) -#endif - -#ifndef STATUS_INVALID_ACE_CONDITION -# define STATUS_INVALID_ACE_CONDITION ((NTSTATUS) 0xC00001A2L) -#endif - -#ifndef STATUS_IMAGE_SUBSYSTEM_NOT_PRESENT -# define STATUS_IMAGE_SUBSYSTEM_NOT_PRESENT ((NTSTATUS) 0xC00001A3L) -#endif - -#ifndef STATUS_NOTIFICATION_GUID_ALREADY_DEFINED -# define STATUS_NOTIFICATION_GUID_ALREADY_DEFINED ((NTSTATUS) 0xC00001A4L) -#endif - -#ifndef STATUS_NETWORK_OPEN_RESTRICTION -# define STATUS_NETWORK_OPEN_RESTRICTION ((NTSTATUS) 0xC0000201L) -#endif - -#ifndef STATUS_NO_USER_SESSION_KEY -# define STATUS_NO_USER_SESSION_KEY ((NTSTATUS) 0xC0000202L) -#endif - -#ifndef STATUS_USER_SESSION_DELETED -# define STATUS_USER_SESSION_DELETED ((NTSTATUS) 0xC0000203L) -#endif - -#ifndef STATUS_RESOURCE_LANG_NOT_FOUND -# define STATUS_RESOURCE_LANG_NOT_FOUND ((NTSTATUS) 0xC0000204L) -#endif - -#ifndef STATUS_INSUFF_SERVER_RESOURCES -# define STATUS_INSUFF_SERVER_RESOURCES ((NTSTATUS) 0xC0000205L) -#endif - -#ifndef STATUS_INVALID_BUFFER_SIZE -# define STATUS_INVALID_BUFFER_SIZE ((NTSTATUS) 0xC0000206L) -#endif - -#ifndef STATUS_INVALID_ADDRESS_COMPONENT -# define STATUS_INVALID_ADDRESS_COMPONENT ((NTSTATUS) 0xC0000207L) -#endif - -#ifndef STATUS_INVALID_ADDRESS_WILDCARD -# define STATUS_INVALID_ADDRESS_WILDCARD ((NTSTATUS) 0xC0000208L) -#endif - -#ifndef STATUS_TOO_MANY_ADDRESSES -# define STATUS_TOO_MANY_ADDRESSES ((NTSTATUS) 0xC0000209L) -#endif - -#ifndef STATUS_ADDRESS_ALREADY_EXISTS -# define STATUS_ADDRESS_ALREADY_EXISTS ((NTSTATUS) 0xC000020AL) -#endif - -#ifndef STATUS_ADDRESS_CLOSED -# define STATUS_ADDRESS_CLOSED ((NTSTATUS) 0xC000020BL) -#endif - -#ifndef STATUS_CONNECTION_DISCONNECTED -# define STATUS_CONNECTION_DISCONNECTED ((NTSTATUS) 0xC000020CL) -#endif - -#ifndef STATUS_CONNECTION_RESET -# define STATUS_CONNECTION_RESET ((NTSTATUS) 0xC000020DL) -#endif - -#ifndef STATUS_TOO_MANY_NODES -# define STATUS_TOO_MANY_NODES ((NTSTATUS) 0xC000020EL) -#endif - -#ifndef STATUS_TRANSACTION_ABORTED -# define STATUS_TRANSACTION_ABORTED ((NTSTATUS) 0xC000020FL) -#endif - -#ifndef STATUS_TRANSACTION_TIMED_OUT -# define STATUS_TRANSACTION_TIMED_OUT ((NTSTATUS) 0xC0000210L) -#endif - -#ifndef STATUS_TRANSACTION_NO_RELEASE -# define STATUS_TRANSACTION_NO_RELEASE ((NTSTATUS) 0xC0000211L) -#endif - -#ifndef STATUS_TRANSACTION_NO_MATCH -# define STATUS_TRANSACTION_NO_MATCH ((NTSTATUS) 0xC0000212L) -#endif - -#ifndef STATUS_TRANSACTION_RESPONDED -# define STATUS_TRANSACTION_RESPONDED ((NTSTATUS) 0xC0000213L) -#endif - -#ifndef STATUS_TRANSACTION_INVALID_ID -# define STATUS_TRANSACTION_INVALID_ID ((NTSTATUS) 0xC0000214L) -#endif - -#ifndef STATUS_TRANSACTION_INVALID_TYPE -# define STATUS_TRANSACTION_INVALID_TYPE ((NTSTATUS) 0xC0000215L) -#endif - -#ifndef STATUS_NOT_SERVER_SESSION -# define STATUS_NOT_SERVER_SESSION ((NTSTATUS) 0xC0000216L) -#endif - -#ifndef STATUS_NOT_CLIENT_SESSION -# define STATUS_NOT_CLIENT_SESSION ((NTSTATUS) 0xC0000217L) -#endif - -#ifndef STATUS_CANNOT_LOAD_REGISTRY_FILE -# define STATUS_CANNOT_LOAD_REGISTRY_FILE ((NTSTATUS) 0xC0000218L) -#endif - -#ifndef STATUS_DEBUG_ATTACH_FAILED -# define STATUS_DEBUG_ATTACH_FAILED ((NTSTATUS) 0xC0000219L) -#endif - -#ifndef STATUS_SYSTEM_PROCESS_TERMINATED -# define STATUS_SYSTEM_PROCESS_TERMINATED ((NTSTATUS) 0xC000021AL) -#endif - -#ifndef STATUS_DATA_NOT_ACCEPTED -# define STATUS_DATA_NOT_ACCEPTED ((NTSTATUS) 0xC000021BL) -#endif - -#ifndef STATUS_NO_BROWSER_SERVERS_FOUND -# define STATUS_NO_BROWSER_SERVERS_FOUND ((NTSTATUS) 0xC000021CL) -#endif - -#ifndef STATUS_VDM_HARD_ERROR -# define STATUS_VDM_HARD_ERROR ((NTSTATUS) 0xC000021DL) -#endif - -#ifndef STATUS_DRIVER_CANCEL_TIMEOUT -# define STATUS_DRIVER_CANCEL_TIMEOUT ((NTSTATUS) 0xC000021EL) -#endif - -#ifndef STATUS_REPLY_MESSAGE_MISMATCH -# define STATUS_REPLY_MESSAGE_MISMATCH ((NTSTATUS) 0xC000021FL) -#endif - -#ifndef STATUS_MAPPED_ALIGNMENT -# define STATUS_MAPPED_ALIGNMENT ((NTSTATUS) 0xC0000220L) -#endif - -#ifndef STATUS_IMAGE_CHECKSUM_MISMATCH -# define STATUS_IMAGE_CHECKSUM_MISMATCH ((NTSTATUS) 0xC0000221L) -#endif - -#ifndef STATUS_LOST_WRITEBEHIND_DATA -# define STATUS_LOST_WRITEBEHIND_DATA ((NTSTATUS) 0xC0000222L) -#endif - -#ifndef STATUS_CLIENT_SERVER_PARAMETERS_INVALID -# define STATUS_CLIENT_SERVER_PARAMETERS_INVALID ((NTSTATUS) 0xC0000223L) -#endif - -#ifndef STATUS_PASSWORD_MUST_CHANGE -# define STATUS_PASSWORD_MUST_CHANGE ((NTSTATUS) 0xC0000224L) -#endif - -#ifndef STATUS_NOT_FOUND -# define STATUS_NOT_FOUND ((NTSTATUS) 0xC0000225L) -#endif - -#ifndef STATUS_NOT_TINY_STREAM -# define STATUS_NOT_TINY_STREAM ((NTSTATUS) 0xC0000226L) -#endif - -#ifndef STATUS_RECOVERY_FAILURE -# define STATUS_RECOVERY_FAILURE ((NTSTATUS) 0xC0000227L) -#endif - -#ifndef STATUS_STACK_OVERFLOW_READ -# define STATUS_STACK_OVERFLOW_READ ((NTSTATUS) 0xC0000228L) -#endif - -#ifndef STATUS_FAIL_CHECK -# define STATUS_FAIL_CHECK ((NTSTATUS) 0xC0000229L) -#endif - -#ifndef STATUS_DUPLICATE_OBJECTID -# define STATUS_DUPLICATE_OBJECTID ((NTSTATUS) 0xC000022AL) -#endif - -#ifndef STATUS_OBJECTID_EXISTS -# define STATUS_OBJECTID_EXISTS ((NTSTATUS) 0xC000022BL) -#endif - -#ifndef STATUS_CONVERT_TO_LARGE -# define STATUS_CONVERT_TO_LARGE ((NTSTATUS) 0xC000022CL) -#endif - -#ifndef STATUS_RETRY -# define STATUS_RETRY ((NTSTATUS) 0xC000022DL) -#endif - -#ifndef STATUS_FOUND_OUT_OF_SCOPE -# define STATUS_FOUND_OUT_OF_SCOPE ((NTSTATUS) 0xC000022EL) -#endif - -#ifndef STATUS_ALLOCATE_BUCKET -# define STATUS_ALLOCATE_BUCKET ((NTSTATUS) 0xC000022FL) -#endif - -#ifndef STATUS_PROPSET_NOT_FOUND -# define STATUS_PROPSET_NOT_FOUND ((NTSTATUS) 0xC0000230L) -#endif - -#ifndef STATUS_MARSHALL_OVERFLOW -# define STATUS_MARSHALL_OVERFLOW ((NTSTATUS) 0xC0000231L) -#endif - -#ifndef STATUS_INVALID_VARIANT -# define STATUS_INVALID_VARIANT ((NTSTATUS) 0xC0000232L) -#endif - -#ifndef STATUS_DOMAIN_CONTROLLER_NOT_FOUND -# define STATUS_DOMAIN_CONTROLLER_NOT_FOUND ((NTSTATUS) 0xC0000233L) -#endif - -#ifndef STATUS_ACCOUNT_LOCKED_OUT -# define STATUS_ACCOUNT_LOCKED_OUT ((NTSTATUS) 0xC0000234L) -#endif - -#ifndef STATUS_HANDLE_NOT_CLOSABLE -# define STATUS_HANDLE_NOT_CLOSABLE ((NTSTATUS) 0xC0000235L) -#endif - -#ifndef STATUS_CONNECTION_REFUSED -# define STATUS_CONNECTION_REFUSED ((NTSTATUS) 0xC0000236L) -#endif - -#ifndef STATUS_GRACEFUL_DISCONNECT -# define STATUS_GRACEFUL_DISCONNECT ((NTSTATUS) 0xC0000237L) -#endif - -#ifndef STATUS_ADDRESS_ALREADY_ASSOCIATED -# define STATUS_ADDRESS_ALREADY_ASSOCIATED ((NTSTATUS) 0xC0000238L) -#endif - -#ifndef STATUS_ADDRESS_NOT_ASSOCIATED -# define STATUS_ADDRESS_NOT_ASSOCIATED ((NTSTATUS) 0xC0000239L) -#endif - -#ifndef STATUS_CONNECTION_INVALID -# define STATUS_CONNECTION_INVALID ((NTSTATUS) 0xC000023AL) -#endif - -#ifndef STATUS_CONNECTION_ACTIVE -# define STATUS_CONNECTION_ACTIVE ((NTSTATUS) 0xC000023BL) -#endif - -#ifndef STATUS_NETWORK_UNREACHABLE -# define STATUS_NETWORK_UNREACHABLE ((NTSTATUS) 0xC000023CL) -#endif - -#ifndef STATUS_HOST_UNREACHABLE -# define STATUS_HOST_UNREACHABLE ((NTSTATUS) 0xC000023DL) -#endif - -#ifndef STATUS_PROTOCOL_UNREACHABLE -# define STATUS_PROTOCOL_UNREACHABLE ((NTSTATUS) 0xC000023EL) -#endif - -#ifndef STATUS_PORT_UNREACHABLE -# define STATUS_PORT_UNREACHABLE ((NTSTATUS) 0xC000023FL) -#endif - -#ifndef STATUS_REQUEST_ABORTED -# define STATUS_REQUEST_ABORTED ((NTSTATUS) 0xC0000240L) -#endif - -#ifndef STATUS_CONNECTION_ABORTED -# define STATUS_CONNECTION_ABORTED ((NTSTATUS) 0xC0000241L) -#endif - -#ifndef STATUS_BAD_COMPRESSION_BUFFER -# define STATUS_BAD_COMPRESSION_BUFFER ((NTSTATUS) 0xC0000242L) -#endif - -#ifndef STATUS_USER_MAPPED_FILE -# define STATUS_USER_MAPPED_FILE ((NTSTATUS) 0xC0000243L) -#endif - -#ifndef STATUS_AUDIT_FAILED -# define STATUS_AUDIT_FAILED ((NTSTATUS) 0xC0000244L) -#endif - -#ifndef STATUS_TIMER_RESOLUTION_NOT_SET -# define STATUS_TIMER_RESOLUTION_NOT_SET ((NTSTATUS) 0xC0000245L) -#endif - -#ifndef STATUS_CONNECTION_COUNT_LIMIT -# define STATUS_CONNECTION_COUNT_LIMIT ((NTSTATUS) 0xC0000246L) -#endif - -#ifndef STATUS_LOGIN_TIME_RESTRICTION -# define STATUS_LOGIN_TIME_RESTRICTION ((NTSTATUS) 0xC0000247L) -#endif - -#ifndef STATUS_LOGIN_WKSTA_RESTRICTION -# define STATUS_LOGIN_WKSTA_RESTRICTION ((NTSTATUS) 0xC0000248L) -#endif - -#ifndef STATUS_IMAGE_MP_UP_MISMATCH -# define STATUS_IMAGE_MP_UP_MISMATCH ((NTSTATUS) 0xC0000249L) -#endif - -#ifndef STATUS_INSUFFICIENT_LOGON_INFO -# define STATUS_INSUFFICIENT_LOGON_INFO ((NTSTATUS) 0xC0000250L) -#endif - -#ifndef STATUS_BAD_DLL_ENTRYPOINT -# define STATUS_BAD_DLL_ENTRYPOINT ((NTSTATUS) 0xC0000251L) -#endif - -#ifndef STATUS_BAD_SERVICE_ENTRYPOINT -# define STATUS_BAD_SERVICE_ENTRYPOINT ((NTSTATUS) 0xC0000252L) -#endif - -#ifndef STATUS_LPC_REPLY_LOST -# define STATUS_LPC_REPLY_LOST ((NTSTATUS) 0xC0000253L) -#endif - -#ifndef STATUS_IP_ADDRESS_CONFLICT1 -# define STATUS_IP_ADDRESS_CONFLICT1 ((NTSTATUS) 0xC0000254L) -#endif - -#ifndef STATUS_IP_ADDRESS_CONFLICT2 -# define STATUS_IP_ADDRESS_CONFLICT2 ((NTSTATUS) 0xC0000255L) -#endif - -#ifndef STATUS_REGISTRY_QUOTA_LIMIT -# define STATUS_REGISTRY_QUOTA_LIMIT ((NTSTATUS) 0xC0000256L) -#endif - -#ifndef STATUS_PATH_NOT_COVERED -# define STATUS_PATH_NOT_COVERED ((NTSTATUS) 0xC0000257L) -#endif - -#ifndef STATUS_NO_CALLBACK_ACTIVE -# define STATUS_NO_CALLBACK_ACTIVE ((NTSTATUS) 0xC0000258L) -#endif - -#ifndef STATUS_LICENSE_QUOTA_EXCEEDED -# define STATUS_LICENSE_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000259L) -#endif - -#ifndef STATUS_PWD_TOO_SHORT -# define STATUS_PWD_TOO_SHORT ((NTSTATUS) 0xC000025AL) -#endif - -#ifndef STATUS_PWD_TOO_RECENT -# define STATUS_PWD_TOO_RECENT ((NTSTATUS) 0xC000025BL) -#endif - -#ifndef STATUS_PWD_HISTORY_CONFLICT -# define STATUS_PWD_HISTORY_CONFLICT ((NTSTATUS) 0xC000025CL) -#endif - -#ifndef STATUS_PLUGPLAY_NO_DEVICE -# define STATUS_PLUGPLAY_NO_DEVICE ((NTSTATUS) 0xC000025EL) -#endif - -#ifndef STATUS_UNSUPPORTED_COMPRESSION -# define STATUS_UNSUPPORTED_COMPRESSION ((NTSTATUS) 0xC000025FL) -#endif - -#ifndef STATUS_INVALID_HW_PROFILE -# define STATUS_INVALID_HW_PROFILE ((NTSTATUS) 0xC0000260L) -#endif - -#ifndef STATUS_INVALID_PLUGPLAY_DEVICE_PATH -# define STATUS_INVALID_PLUGPLAY_DEVICE_PATH ((NTSTATUS) 0xC0000261L) -#endif - -#ifndef STATUS_DRIVER_ORDINAL_NOT_FOUND -# define STATUS_DRIVER_ORDINAL_NOT_FOUND ((NTSTATUS) 0xC0000262L) -#endif - -#ifndef STATUS_DRIVER_ENTRYPOINT_NOT_FOUND -# define STATUS_DRIVER_ENTRYPOINT_NOT_FOUND ((NTSTATUS) 0xC0000263L) -#endif - -#ifndef STATUS_RESOURCE_NOT_OWNED -# define STATUS_RESOURCE_NOT_OWNED ((NTSTATUS) 0xC0000264L) -#endif - -#ifndef STATUS_TOO_MANY_LINKS -# define STATUS_TOO_MANY_LINKS ((NTSTATUS) 0xC0000265L) -#endif - -#ifndef STATUS_QUOTA_LIST_INCONSISTENT -# define STATUS_QUOTA_LIST_INCONSISTENT ((NTSTATUS) 0xC0000266L) -#endif - -#ifndef STATUS_FILE_IS_OFFLINE -# define STATUS_FILE_IS_OFFLINE ((NTSTATUS) 0xC0000267L) -#endif - -#ifndef STATUS_EVALUATION_EXPIRATION -# define STATUS_EVALUATION_EXPIRATION ((NTSTATUS) 0xC0000268L) -#endif - -#ifndef STATUS_ILLEGAL_DLL_RELOCATION -# define STATUS_ILLEGAL_DLL_RELOCATION ((NTSTATUS) 0xC0000269L) -#endif - -#ifndef STATUS_LICENSE_VIOLATION -# define STATUS_LICENSE_VIOLATION ((NTSTATUS) 0xC000026AL) -#endif - -#ifndef STATUS_DLL_INIT_FAILED_LOGOFF -# define STATUS_DLL_INIT_FAILED_LOGOFF ((NTSTATUS) 0xC000026BL) -#endif - -#ifndef STATUS_DRIVER_UNABLE_TO_LOAD -# define STATUS_DRIVER_UNABLE_TO_LOAD ((NTSTATUS) 0xC000026CL) -#endif - -#ifndef STATUS_DFS_UNAVAILABLE -# define STATUS_DFS_UNAVAILABLE ((NTSTATUS) 0xC000026DL) -#endif - -#ifndef STATUS_VOLUME_DISMOUNTED -# define STATUS_VOLUME_DISMOUNTED ((NTSTATUS) 0xC000026EL) -#endif - -#ifndef STATUS_WX86_INTERNAL_ERROR -# define STATUS_WX86_INTERNAL_ERROR ((NTSTATUS) 0xC000026FL) -#endif - -#ifndef STATUS_WX86_FLOAT_STACK_CHECK -# define STATUS_WX86_FLOAT_STACK_CHECK ((NTSTATUS) 0xC0000270L) -#endif - -#ifndef STATUS_VALIDATE_CONTINUE -# define STATUS_VALIDATE_CONTINUE ((NTSTATUS) 0xC0000271L) -#endif - -#ifndef STATUS_NO_MATCH -# define STATUS_NO_MATCH ((NTSTATUS) 0xC0000272L) -#endif - -#ifndef STATUS_NO_MORE_MATCHES -# define STATUS_NO_MORE_MATCHES ((NTSTATUS) 0xC0000273L) -#endif - -#ifndef STATUS_NOT_A_REPARSE_POINT -# define STATUS_NOT_A_REPARSE_POINT ((NTSTATUS) 0xC0000275L) -#endif - -#ifndef STATUS_IO_REPARSE_TAG_INVALID -# define STATUS_IO_REPARSE_TAG_INVALID ((NTSTATUS) 0xC0000276L) -#endif - -#ifndef STATUS_IO_REPARSE_TAG_MISMATCH -# define STATUS_IO_REPARSE_TAG_MISMATCH ((NTSTATUS) 0xC0000277L) -#endif - -#ifndef STATUS_IO_REPARSE_DATA_INVALID -# define STATUS_IO_REPARSE_DATA_INVALID ((NTSTATUS) 0xC0000278L) -#endif - -#ifndef STATUS_IO_REPARSE_TAG_NOT_HANDLED -# define STATUS_IO_REPARSE_TAG_NOT_HANDLED ((NTSTATUS) 0xC0000279L) -#endif - -#ifndef STATUS_REPARSE_POINT_NOT_RESOLVED -# define STATUS_REPARSE_POINT_NOT_RESOLVED ((NTSTATUS) 0xC0000280L) -#endif - -#ifndef STATUS_DIRECTORY_IS_A_REPARSE_POINT -# define STATUS_DIRECTORY_IS_A_REPARSE_POINT ((NTSTATUS) 0xC0000281L) -#endif - -#ifndef STATUS_RANGE_LIST_CONFLICT -# define STATUS_RANGE_LIST_CONFLICT ((NTSTATUS) 0xC0000282L) -#endif - -#ifndef STATUS_SOURCE_ELEMENT_EMPTY -# define STATUS_SOURCE_ELEMENT_EMPTY ((NTSTATUS) 0xC0000283L) -#endif - -#ifndef STATUS_DESTINATION_ELEMENT_FULL -# define STATUS_DESTINATION_ELEMENT_FULL ((NTSTATUS) 0xC0000284L) -#endif - -#ifndef STATUS_ILLEGAL_ELEMENT_ADDRESS -# define STATUS_ILLEGAL_ELEMENT_ADDRESS ((NTSTATUS) 0xC0000285L) -#endif - -#ifndef STATUS_MAGAZINE_NOT_PRESENT -# define STATUS_MAGAZINE_NOT_PRESENT ((NTSTATUS) 0xC0000286L) -#endif - -#ifndef STATUS_REINITIALIZATION_NEEDED -# define STATUS_REINITIALIZATION_NEEDED ((NTSTATUS) 0xC0000287L) -#endif - -#ifndef STATUS_DEVICE_REQUIRES_CLEANING -# define STATUS_DEVICE_REQUIRES_CLEANING ((NTSTATUS) 0x80000288L) -#endif - -#ifndef STATUS_DEVICE_DOOR_OPEN -# define STATUS_DEVICE_DOOR_OPEN ((NTSTATUS) 0x80000289L) -#endif - -#ifndef STATUS_ENCRYPTION_FAILED -# define STATUS_ENCRYPTION_FAILED ((NTSTATUS) 0xC000028AL) -#endif - -#ifndef STATUS_DECRYPTION_FAILED -# define STATUS_DECRYPTION_FAILED ((NTSTATUS) 0xC000028BL) -#endif - -#ifndef STATUS_RANGE_NOT_FOUND -# define STATUS_RANGE_NOT_FOUND ((NTSTATUS) 0xC000028CL) -#endif - -#ifndef STATUS_NO_RECOVERY_POLICY -# define STATUS_NO_RECOVERY_POLICY ((NTSTATUS) 0xC000028DL) -#endif - -#ifndef STATUS_NO_EFS -# define STATUS_NO_EFS ((NTSTATUS) 0xC000028EL) -#endif - -#ifndef STATUS_WRONG_EFS -# define STATUS_WRONG_EFS ((NTSTATUS) 0xC000028FL) -#endif - -#ifndef STATUS_NO_USER_KEYS -# define STATUS_NO_USER_KEYS ((NTSTATUS) 0xC0000290L) -#endif - -#ifndef STATUS_FILE_NOT_ENCRYPTED -# define STATUS_FILE_NOT_ENCRYPTED ((NTSTATUS) 0xC0000291L) -#endif - -#ifndef STATUS_NOT_EXPORT_FORMAT -# define STATUS_NOT_EXPORT_FORMAT ((NTSTATUS) 0xC0000292L) -#endif - -#ifndef STATUS_FILE_ENCRYPTED -# define STATUS_FILE_ENCRYPTED ((NTSTATUS) 0xC0000293L) -#endif - -#ifndef STATUS_WAKE_SYSTEM -# define STATUS_WAKE_SYSTEM ((NTSTATUS) 0x40000294L) -#endif - -#ifndef STATUS_WMI_GUID_NOT_FOUND -# define STATUS_WMI_GUID_NOT_FOUND ((NTSTATUS) 0xC0000295L) -#endif - -#ifndef STATUS_WMI_INSTANCE_NOT_FOUND -# define STATUS_WMI_INSTANCE_NOT_FOUND ((NTSTATUS) 0xC0000296L) -#endif - -#ifndef STATUS_WMI_ITEMID_NOT_FOUND -# define STATUS_WMI_ITEMID_NOT_FOUND ((NTSTATUS) 0xC0000297L) -#endif - -#ifndef STATUS_WMI_TRY_AGAIN -# define STATUS_WMI_TRY_AGAIN ((NTSTATUS) 0xC0000298L) -#endif - -#ifndef STATUS_SHARED_POLICY -# define STATUS_SHARED_POLICY ((NTSTATUS) 0xC0000299L) -#endif - -#ifndef STATUS_POLICY_OBJECT_NOT_FOUND -# define STATUS_POLICY_OBJECT_NOT_FOUND ((NTSTATUS) 0xC000029AL) -#endif - -#ifndef STATUS_POLICY_ONLY_IN_DS -# define STATUS_POLICY_ONLY_IN_DS ((NTSTATUS) 0xC000029BL) -#endif - -#ifndef STATUS_VOLUME_NOT_UPGRADED -# define STATUS_VOLUME_NOT_UPGRADED ((NTSTATUS) 0xC000029CL) -#endif - -#ifndef STATUS_REMOTE_STORAGE_NOT_ACTIVE -# define STATUS_REMOTE_STORAGE_NOT_ACTIVE ((NTSTATUS) 0xC000029DL) -#endif - -#ifndef STATUS_REMOTE_STORAGE_MEDIA_ERROR -# define STATUS_REMOTE_STORAGE_MEDIA_ERROR ((NTSTATUS) 0xC000029EL) -#endif - -#ifndef STATUS_NO_TRACKING_SERVICE -# define STATUS_NO_TRACKING_SERVICE ((NTSTATUS) 0xC000029FL) -#endif - -#ifndef STATUS_SERVER_SID_MISMATCH -# define STATUS_SERVER_SID_MISMATCH ((NTSTATUS) 0xC00002A0L) -#endif - -#ifndef STATUS_DS_NO_ATTRIBUTE_OR_VALUE -# define STATUS_DS_NO_ATTRIBUTE_OR_VALUE ((NTSTATUS) 0xC00002A1L) -#endif - -#ifndef STATUS_DS_INVALID_ATTRIBUTE_SYNTAX -# define STATUS_DS_INVALID_ATTRIBUTE_SYNTAX ((NTSTATUS) 0xC00002A2L) -#endif - -#ifndef STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED -# define STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED ((NTSTATUS) 0xC00002A3L) -#endif - -#ifndef STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS -# define STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS ((NTSTATUS) 0xC00002A4L) -#endif - -#ifndef STATUS_DS_BUSY -# define STATUS_DS_BUSY ((NTSTATUS) 0xC00002A5L) -#endif - -#ifndef STATUS_DS_UNAVAILABLE -# define STATUS_DS_UNAVAILABLE ((NTSTATUS) 0xC00002A6L) -#endif - -#ifndef STATUS_DS_NO_RIDS_ALLOCATED -# define STATUS_DS_NO_RIDS_ALLOCATED ((NTSTATUS) 0xC00002A7L) -#endif - -#ifndef STATUS_DS_NO_MORE_RIDS -# define STATUS_DS_NO_MORE_RIDS ((NTSTATUS) 0xC00002A8L) -#endif - -#ifndef STATUS_DS_INCORRECT_ROLE_OWNER -# define STATUS_DS_INCORRECT_ROLE_OWNER ((NTSTATUS) 0xC00002A9L) -#endif - -#ifndef STATUS_DS_RIDMGR_INIT_ERROR -# define STATUS_DS_RIDMGR_INIT_ERROR ((NTSTATUS) 0xC00002AAL) -#endif - -#ifndef STATUS_DS_OBJ_CLASS_VIOLATION -# define STATUS_DS_OBJ_CLASS_VIOLATION ((NTSTATUS) 0xC00002ABL) -#endif - -#ifndef STATUS_DS_CANT_ON_NON_LEAF -# define STATUS_DS_CANT_ON_NON_LEAF ((NTSTATUS) 0xC00002ACL) -#endif - -#ifndef STATUS_DS_CANT_ON_RDN -# define STATUS_DS_CANT_ON_RDN ((NTSTATUS) 0xC00002ADL) -#endif - -#ifndef STATUS_DS_CANT_MOD_OBJ_CLASS -# define STATUS_DS_CANT_MOD_OBJ_CLASS ((NTSTATUS) 0xC00002AEL) -#endif - -#ifndef STATUS_DS_CROSS_DOM_MOVE_FAILED -# define STATUS_DS_CROSS_DOM_MOVE_FAILED ((NTSTATUS) 0xC00002AFL) -#endif - -#ifndef STATUS_DS_GC_NOT_AVAILABLE -# define STATUS_DS_GC_NOT_AVAILABLE ((NTSTATUS) 0xC00002B0L) -#endif - -#ifndef STATUS_DIRECTORY_SERVICE_REQUIRED -# define STATUS_DIRECTORY_SERVICE_REQUIRED ((NTSTATUS) 0xC00002B1L) -#endif - -#ifndef STATUS_REPARSE_ATTRIBUTE_CONFLICT -# define STATUS_REPARSE_ATTRIBUTE_CONFLICT ((NTSTATUS) 0xC00002B2L) -#endif - -#ifndef STATUS_CANT_ENABLE_DENY_ONLY -# define STATUS_CANT_ENABLE_DENY_ONLY ((NTSTATUS) 0xC00002B3L) -#endif - -#ifndef STATUS_FLOAT_MULTIPLE_FAULTS -# define STATUS_FLOAT_MULTIPLE_FAULTS ((NTSTATUS) 0xC00002B4L) -#endif - -#ifndef STATUS_FLOAT_MULTIPLE_TRAPS -# define STATUS_FLOAT_MULTIPLE_TRAPS ((NTSTATUS) 0xC00002B5L) -#endif - -#ifndef STATUS_DEVICE_REMOVED -# define STATUS_DEVICE_REMOVED ((NTSTATUS) 0xC00002B6L) -#endif - -#ifndef STATUS_JOURNAL_DELETE_IN_PROGRESS -# define STATUS_JOURNAL_DELETE_IN_PROGRESS ((NTSTATUS) 0xC00002B7L) -#endif - -#ifndef STATUS_JOURNAL_NOT_ACTIVE -# define STATUS_JOURNAL_NOT_ACTIVE ((NTSTATUS) 0xC00002B8L) -#endif - -#ifndef STATUS_NOINTERFACE -# define STATUS_NOINTERFACE ((NTSTATUS) 0xC00002B9L) -#endif - -#ifndef STATUS_DS_ADMIN_LIMIT_EXCEEDED -# define STATUS_DS_ADMIN_LIMIT_EXCEEDED ((NTSTATUS) 0xC00002C1L) -#endif - -#ifndef STATUS_DRIVER_FAILED_SLEEP -# define STATUS_DRIVER_FAILED_SLEEP ((NTSTATUS) 0xC00002C2L) -#endif - -#ifndef STATUS_MUTUAL_AUTHENTICATION_FAILED -# define STATUS_MUTUAL_AUTHENTICATION_FAILED ((NTSTATUS) 0xC00002C3L) -#endif - -#ifndef STATUS_CORRUPT_SYSTEM_FILE -# define STATUS_CORRUPT_SYSTEM_FILE ((NTSTATUS) 0xC00002C4L) -#endif - -#ifndef STATUS_DATATYPE_MISALIGNMENT_ERROR -# define STATUS_DATATYPE_MISALIGNMENT_ERROR ((NTSTATUS) 0xC00002C5L) -#endif - -#ifndef STATUS_WMI_READ_ONLY -# define STATUS_WMI_READ_ONLY ((NTSTATUS) 0xC00002C6L) -#endif - -#ifndef STATUS_WMI_SET_FAILURE -# define STATUS_WMI_SET_FAILURE ((NTSTATUS) 0xC00002C7L) -#endif - -#ifndef STATUS_COMMITMENT_MINIMUM -# define STATUS_COMMITMENT_MINIMUM ((NTSTATUS) 0xC00002C8L) -#endif - -#ifndef STATUS_REG_NAT_CONSUMPTION -# define STATUS_REG_NAT_CONSUMPTION ((NTSTATUS) 0xC00002C9L) -#endif - -#ifndef STATUS_TRANSPORT_FULL -# define STATUS_TRANSPORT_FULL ((NTSTATUS) 0xC00002CAL) -#endif - -#ifndef STATUS_DS_SAM_INIT_FAILURE -# define STATUS_DS_SAM_INIT_FAILURE ((NTSTATUS) 0xC00002CBL) -#endif - -#ifndef STATUS_ONLY_IF_CONNECTED -# define STATUS_ONLY_IF_CONNECTED ((NTSTATUS) 0xC00002CCL) -#endif - -#ifndef STATUS_DS_SENSITIVE_GROUP_VIOLATION -# define STATUS_DS_SENSITIVE_GROUP_VIOLATION ((NTSTATUS) 0xC00002CDL) -#endif - -#ifndef STATUS_PNP_RESTART_ENUMERATION -# define STATUS_PNP_RESTART_ENUMERATION ((NTSTATUS) 0xC00002CEL) -#endif - -#ifndef STATUS_JOURNAL_ENTRY_DELETED -# define STATUS_JOURNAL_ENTRY_DELETED ((NTSTATUS) 0xC00002CFL) -#endif - -#ifndef STATUS_DS_CANT_MOD_PRIMARYGROUPID -# define STATUS_DS_CANT_MOD_PRIMARYGROUPID ((NTSTATUS) 0xC00002D0L) -#endif - -#ifndef STATUS_SYSTEM_IMAGE_BAD_SIGNATURE -# define STATUS_SYSTEM_IMAGE_BAD_SIGNATURE ((NTSTATUS) 0xC00002D1L) -#endif - -#ifndef STATUS_PNP_REBOOT_REQUIRED -# define STATUS_PNP_REBOOT_REQUIRED ((NTSTATUS) 0xC00002D2L) -#endif - -#ifndef STATUS_POWER_STATE_INVALID -# define STATUS_POWER_STATE_INVALID ((NTSTATUS) 0xC00002D3L) -#endif - -#ifndef STATUS_DS_INVALID_GROUP_TYPE -# define STATUS_DS_INVALID_GROUP_TYPE ((NTSTATUS) 0xC00002D4L) -#endif - -#ifndef STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN -# define STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN ((NTSTATUS) 0xC00002D5L) -#endif - -#ifndef STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN -# define STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN ((NTSTATUS) 0xC00002D6L) -#endif - -#ifndef STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER -# define STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER ((NTSTATUS) 0xC00002D7L) -#endif - -#ifndef STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER -# define STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER ((NTSTATUS) 0xC00002D8L) -#endif - -#ifndef STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER -# define STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER ((NTSTATUS) 0xC00002D9L) -#endif - -#ifndef STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER -# define STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER ((NTSTATUS) 0xC00002DAL) -#endif - -#ifndef STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER -# define STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER ((NTSTATUS) 0xC00002DBL) -#endif - -#ifndef STATUS_DS_HAVE_PRIMARY_MEMBERS -# define STATUS_DS_HAVE_PRIMARY_MEMBERS ((NTSTATUS) 0xC00002DCL) -#endif - -#ifndef STATUS_WMI_NOT_SUPPORTED -# define STATUS_WMI_NOT_SUPPORTED ((NTSTATUS) 0xC00002DDL) -#endif - -#ifndef STATUS_INSUFFICIENT_POWER -# define STATUS_INSUFFICIENT_POWER ((NTSTATUS) 0xC00002DEL) -#endif - -#ifndef STATUS_SAM_NEED_BOOTKEY_PASSWORD -# define STATUS_SAM_NEED_BOOTKEY_PASSWORD ((NTSTATUS) 0xC00002DFL) -#endif - -#ifndef STATUS_SAM_NEED_BOOTKEY_FLOPPY -# define STATUS_SAM_NEED_BOOTKEY_FLOPPY ((NTSTATUS) 0xC00002E0L) -#endif - -#ifndef STATUS_DS_CANT_START -# define STATUS_DS_CANT_START ((NTSTATUS) 0xC00002E1L) -#endif - -#ifndef STATUS_DS_INIT_FAILURE -# define STATUS_DS_INIT_FAILURE ((NTSTATUS) 0xC00002E2L) -#endif - -#ifndef STATUS_SAM_INIT_FAILURE -# define STATUS_SAM_INIT_FAILURE ((NTSTATUS) 0xC00002E3L) -#endif - -#ifndef STATUS_DS_GC_REQUIRED -# define STATUS_DS_GC_REQUIRED ((NTSTATUS) 0xC00002E4L) -#endif - -#ifndef STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY -# define STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY ((NTSTATUS) 0xC00002E5L) -#endif - -#ifndef STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS -# define STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS ((NTSTATUS) 0xC00002E6L) -#endif - -#ifndef STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED -# define STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED ((NTSTATUS) 0xC00002E7L) -#endif - -#ifndef STATUS_MULTIPLE_FAULT_VIOLATION -# define STATUS_MULTIPLE_FAULT_VIOLATION ((NTSTATUS) 0xC00002E8L) -#endif - -#ifndef STATUS_CURRENT_DOMAIN_NOT_ALLOWED -# define STATUS_CURRENT_DOMAIN_NOT_ALLOWED ((NTSTATUS) 0xC00002E9L) -#endif - -#ifndef STATUS_CANNOT_MAKE -# define STATUS_CANNOT_MAKE ((NTSTATUS) 0xC00002EAL) -#endif - -#ifndef STATUS_SYSTEM_SHUTDOWN -# define STATUS_SYSTEM_SHUTDOWN ((NTSTATUS) 0xC00002EBL) -#endif - -#ifndef STATUS_DS_INIT_FAILURE_CONSOLE -# define STATUS_DS_INIT_FAILURE_CONSOLE ((NTSTATUS) 0xC00002ECL) -#endif - -#ifndef STATUS_DS_SAM_INIT_FAILURE_CONSOLE -# define STATUS_DS_SAM_INIT_FAILURE_CONSOLE ((NTSTATUS) 0xC00002EDL) -#endif - -#ifndef STATUS_UNFINISHED_CONTEXT_DELETED -# define STATUS_UNFINISHED_CONTEXT_DELETED ((NTSTATUS) 0xC00002EEL) -#endif - -#ifndef STATUS_NO_TGT_REPLY -# define STATUS_NO_TGT_REPLY ((NTSTATUS) 0xC00002EFL) -#endif - -#ifndef STATUS_OBJECTID_NOT_FOUND -# define STATUS_OBJECTID_NOT_FOUND ((NTSTATUS) 0xC00002F0L) -#endif - -#ifndef STATUS_NO_IP_ADDRESSES -# define STATUS_NO_IP_ADDRESSES ((NTSTATUS) 0xC00002F1L) -#endif - -#ifndef STATUS_WRONG_CREDENTIAL_HANDLE -# define STATUS_WRONG_CREDENTIAL_HANDLE ((NTSTATUS) 0xC00002F2L) -#endif - -#ifndef STATUS_CRYPTO_SYSTEM_INVALID -# define STATUS_CRYPTO_SYSTEM_INVALID ((NTSTATUS) 0xC00002F3L) -#endif - -#ifndef STATUS_MAX_REFERRALS_EXCEEDED -# define STATUS_MAX_REFERRALS_EXCEEDED ((NTSTATUS) 0xC00002F4L) -#endif - -#ifndef STATUS_MUST_BE_KDC -# define STATUS_MUST_BE_KDC ((NTSTATUS) 0xC00002F5L) -#endif - -#ifndef STATUS_STRONG_CRYPTO_NOT_SUPPORTED -# define STATUS_STRONG_CRYPTO_NOT_SUPPORTED ((NTSTATUS) 0xC00002F6L) -#endif - -#ifndef STATUS_TOO_MANY_PRINCIPALS -# define STATUS_TOO_MANY_PRINCIPALS ((NTSTATUS) 0xC00002F7L) -#endif - -#ifndef STATUS_NO_PA_DATA -# define STATUS_NO_PA_DATA ((NTSTATUS) 0xC00002F8L) -#endif - -#ifndef STATUS_PKINIT_NAME_MISMATCH -# define STATUS_PKINIT_NAME_MISMATCH ((NTSTATUS) 0xC00002F9L) -#endif - -#ifndef STATUS_SMARTCARD_LOGON_REQUIRED -# define STATUS_SMARTCARD_LOGON_REQUIRED ((NTSTATUS) 0xC00002FAL) -#endif - -#ifndef STATUS_KDC_INVALID_REQUEST -# define STATUS_KDC_INVALID_REQUEST ((NTSTATUS) 0xC00002FBL) -#endif - -#ifndef STATUS_KDC_UNABLE_TO_REFER -# define STATUS_KDC_UNABLE_TO_REFER ((NTSTATUS) 0xC00002FCL) -#endif - -#ifndef STATUS_KDC_UNKNOWN_ETYPE -# define STATUS_KDC_UNKNOWN_ETYPE ((NTSTATUS) 0xC00002FDL) -#endif - -#ifndef STATUS_SHUTDOWN_IN_PROGRESS -# define STATUS_SHUTDOWN_IN_PROGRESS ((NTSTATUS) 0xC00002FEL) -#endif - -#ifndef STATUS_SERVER_SHUTDOWN_IN_PROGRESS -# define STATUS_SERVER_SHUTDOWN_IN_PROGRESS ((NTSTATUS) 0xC00002FFL) -#endif - -#ifndef STATUS_NOT_SUPPORTED_ON_SBS -# define STATUS_NOT_SUPPORTED_ON_SBS ((NTSTATUS) 0xC0000300L) -#endif - -#ifndef STATUS_WMI_GUID_DISCONNECTED -# define STATUS_WMI_GUID_DISCONNECTED ((NTSTATUS) 0xC0000301L) -#endif - -#ifndef STATUS_WMI_ALREADY_DISABLED -# define STATUS_WMI_ALREADY_DISABLED ((NTSTATUS) 0xC0000302L) -#endif - -#ifndef STATUS_WMI_ALREADY_ENABLED -# define STATUS_WMI_ALREADY_ENABLED ((NTSTATUS) 0xC0000303L) -#endif - -#ifndef STATUS_MFT_TOO_FRAGMENTED -# define STATUS_MFT_TOO_FRAGMENTED ((NTSTATUS) 0xC0000304L) -#endif - -#ifndef STATUS_COPY_PROTECTION_FAILURE -# define STATUS_COPY_PROTECTION_FAILURE ((NTSTATUS) 0xC0000305L) -#endif - -#ifndef STATUS_CSS_AUTHENTICATION_FAILURE -# define STATUS_CSS_AUTHENTICATION_FAILURE ((NTSTATUS) 0xC0000306L) -#endif - -#ifndef STATUS_CSS_KEY_NOT_PRESENT -# define STATUS_CSS_KEY_NOT_PRESENT ((NTSTATUS) 0xC0000307L) -#endif - -#ifndef STATUS_CSS_KEY_NOT_ESTABLISHED -# define STATUS_CSS_KEY_NOT_ESTABLISHED ((NTSTATUS) 0xC0000308L) -#endif - -#ifndef STATUS_CSS_SCRAMBLED_SECTOR -# define STATUS_CSS_SCRAMBLED_SECTOR ((NTSTATUS) 0xC0000309L) -#endif - -#ifndef STATUS_CSS_REGION_MISMATCH -# define STATUS_CSS_REGION_MISMATCH ((NTSTATUS) 0xC000030AL) -#endif - -#ifndef STATUS_CSS_RESETS_EXHAUSTED -# define STATUS_CSS_RESETS_EXHAUSTED ((NTSTATUS) 0xC000030BL) -#endif - -#ifndef STATUS_PKINIT_FAILURE -# define STATUS_PKINIT_FAILURE ((NTSTATUS) 0xC0000320L) -#endif - -#ifndef STATUS_SMARTCARD_SUBSYSTEM_FAILURE -# define STATUS_SMARTCARD_SUBSYSTEM_FAILURE ((NTSTATUS) 0xC0000321L) -#endif - -#ifndef STATUS_NO_KERB_KEY -# define STATUS_NO_KERB_KEY ((NTSTATUS) 0xC0000322L) -#endif - -#ifndef STATUS_HOST_DOWN -# define STATUS_HOST_DOWN ((NTSTATUS) 0xC0000350L) -#endif - -#ifndef STATUS_UNSUPPORTED_PREAUTH -# define STATUS_UNSUPPORTED_PREAUTH ((NTSTATUS) 0xC0000351L) -#endif - -#ifndef STATUS_EFS_ALG_BLOB_TOO_BIG -# define STATUS_EFS_ALG_BLOB_TOO_BIG ((NTSTATUS) 0xC0000352L) -#endif - -#ifndef STATUS_PORT_NOT_SET -# define STATUS_PORT_NOT_SET ((NTSTATUS) 0xC0000353L) -#endif - -#ifndef STATUS_DEBUGGER_INACTIVE -# define STATUS_DEBUGGER_INACTIVE ((NTSTATUS) 0xC0000354L) -#endif - -#ifndef STATUS_DS_VERSION_CHECK_FAILURE -# define STATUS_DS_VERSION_CHECK_FAILURE ((NTSTATUS) 0xC0000355L) -#endif - -#ifndef STATUS_AUDITING_DISABLED -# define STATUS_AUDITING_DISABLED ((NTSTATUS) 0xC0000356L) -#endif - -#ifndef STATUS_PRENT4_MACHINE_ACCOUNT -# define STATUS_PRENT4_MACHINE_ACCOUNT ((NTSTATUS) 0xC0000357L) -#endif - -#ifndef STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER -# define STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER ((NTSTATUS) 0xC0000358L) -#endif - -#ifndef STATUS_INVALID_IMAGE_WIN_32 -# define STATUS_INVALID_IMAGE_WIN_32 ((NTSTATUS) 0xC0000359L) -#endif - -#ifndef STATUS_INVALID_IMAGE_WIN_64 -# define STATUS_INVALID_IMAGE_WIN_64 ((NTSTATUS) 0xC000035AL) -#endif - -#ifndef STATUS_BAD_BINDINGS -# define STATUS_BAD_BINDINGS ((NTSTATUS) 0xC000035BL) -#endif - -#ifndef STATUS_NETWORK_SESSION_EXPIRED -# define STATUS_NETWORK_SESSION_EXPIRED ((NTSTATUS) 0xC000035CL) -#endif - -#ifndef STATUS_APPHELP_BLOCK -# define STATUS_APPHELP_BLOCK ((NTSTATUS) 0xC000035DL) -#endif - -#ifndef STATUS_ALL_SIDS_FILTERED -# define STATUS_ALL_SIDS_FILTERED ((NTSTATUS) 0xC000035EL) -#endif - -#ifndef STATUS_NOT_SAFE_MODE_DRIVER -# define STATUS_NOT_SAFE_MODE_DRIVER ((NTSTATUS) 0xC000035FL) -#endif - -#ifndef STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT -# define STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT ((NTSTATUS) 0xC0000361L) -#endif - -#ifndef STATUS_ACCESS_DISABLED_BY_POLICY_PATH -# define STATUS_ACCESS_DISABLED_BY_POLICY_PATH ((NTSTATUS) 0xC0000362L) -#endif - -#ifndef STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER -# define STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER ((NTSTATUS) 0xC0000363L) -#endif - -#ifndef STATUS_ACCESS_DISABLED_BY_POLICY_OTHER -# define STATUS_ACCESS_DISABLED_BY_POLICY_OTHER ((NTSTATUS) 0xC0000364L) -#endif - -#ifndef STATUS_FAILED_DRIVER_ENTRY -# define STATUS_FAILED_DRIVER_ENTRY ((NTSTATUS) 0xC0000365L) -#endif - -#ifndef STATUS_DEVICE_ENUMERATION_ERROR -# define STATUS_DEVICE_ENUMERATION_ERROR ((NTSTATUS) 0xC0000366L) -#endif - -#ifndef STATUS_MOUNT_POINT_NOT_RESOLVED -# define STATUS_MOUNT_POINT_NOT_RESOLVED ((NTSTATUS) 0xC0000368L) -#endif - -#ifndef STATUS_INVALID_DEVICE_OBJECT_PARAMETER -# define STATUS_INVALID_DEVICE_OBJECT_PARAMETER ((NTSTATUS) 0xC0000369L) -#endif - -#ifndef STATUS_MCA_OCCURED -# define STATUS_MCA_OCCURED ((NTSTATUS) 0xC000036AL) -#endif - -#ifndef STATUS_DRIVER_BLOCKED_CRITICAL -# define STATUS_DRIVER_BLOCKED_CRITICAL ((NTSTATUS) 0xC000036BL) -#endif - -#ifndef STATUS_DRIVER_BLOCKED -# define STATUS_DRIVER_BLOCKED ((NTSTATUS) 0xC000036CL) -#endif - -#ifndef STATUS_DRIVER_DATABASE_ERROR -# define STATUS_DRIVER_DATABASE_ERROR ((NTSTATUS) 0xC000036DL) -#endif - -#ifndef STATUS_SYSTEM_HIVE_TOO_LARGE -# define STATUS_SYSTEM_HIVE_TOO_LARGE ((NTSTATUS) 0xC000036EL) -#endif - -#ifndef STATUS_INVALID_IMPORT_OF_NON_DLL -# define STATUS_INVALID_IMPORT_OF_NON_DLL ((NTSTATUS) 0xC000036FL) -#endif - -#ifndef STATUS_DS_SHUTTING_DOWN -# define STATUS_DS_SHUTTING_DOWN ((NTSTATUS) 0x40000370L) -#endif - -#ifndef STATUS_NO_SECRETS -# define STATUS_NO_SECRETS ((NTSTATUS) 0xC0000371L) -#endif - -#ifndef STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY -# define STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY ((NTSTATUS) 0xC0000372L) -#endif - -#ifndef STATUS_FAILED_STACK_SWITCH -# define STATUS_FAILED_STACK_SWITCH ((NTSTATUS) 0xC0000373L) -#endif - -#ifndef STATUS_HEAP_CORRUPTION -# define STATUS_HEAP_CORRUPTION ((NTSTATUS) 0xC0000374L) -#endif - -#ifndef STATUS_SMARTCARD_WRONG_PIN -# define STATUS_SMARTCARD_WRONG_PIN ((NTSTATUS) 0xC0000380L) -#endif - -#ifndef STATUS_SMARTCARD_CARD_BLOCKED -# define STATUS_SMARTCARD_CARD_BLOCKED ((NTSTATUS) 0xC0000381L) -#endif - -#ifndef STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED -# define STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED ((NTSTATUS) 0xC0000382L) -#endif - -#ifndef STATUS_SMARTCARD_NO_CARD -# define STATUS_SMARTCARD_NO_CARD ((NTSTATUS) 0xC0000383L) -#endif - -#ifndef STATUS_SMARTCARD_NO_KEY_CONTAINER -# define STATUS_SMARTCARD_NO_KEY_CONTAINER ((NTSTATUS) 0xC0000384L) -#endif - -#ifndef STATUS_SMARTCARD_NO_CERTIFICATE -# define STATUS_SMARTCARD_NO_CERTIFICATE ((NTSTATUS) 0xC0000385L) -#endif - -#ifndef STATUS_SMARTCARD_NO_KEYSET -# define STATUS_SMARTCARD_NO_KEYSET ((NTSTATUS) 0xC0000386L) -#endif - -#ifndef STATUS_SMARTCARD_IO_ERROR -# define STATUS_SMARTCARD_IO_ERROR ((NTSTATUS) 0xC0000387L) -#endif - -#ifndef STATUS_DOWNGRADE_DETECTED -# define STATUS_DOWNGRADE_DETECTED ((NTSTATUS) 0xC0000388L) -#endif - -#ifndef STATUS_SMARTCARD_CERT_REVOKED -# define STATUS_SMARTCARD_CERT_REVOKED ((NTSTATUS) 0xC0000389L) -#endif - -#ifndef STATUS_ISSUING_CA_UNTRUSTED -# define STATUS_ISSUING_CA_UNTRUSTED ((NTSTATUS) 0xC000038AL) -#endif - -#ifndef STATUS_REVOCATION_OFFLINE_C -# define STATUS_REVOCATION_OFFLINE_C ((NTSTATUS) 0xC000038BL) -#endif - -#ifndef STATUS_PKINIT_CLIENT_FAILURE -# define STATUS_PKINIT_CLIENT_FAILURE ((NTSTATUS) 0xC000038CL) -#endif - -#ifndef STATUS_SMARTCARD_CERT_EXPIRED -# define STATUS_SMARTCARD_CERT_EXPIRED ((NTSTATUS) 0xC000038DL) -#endif - -#ifndef STATUS_DRIVER_FAILED_PRIOR_UNLOAD -# define STATUS_DRIVER_FAILED_PRIOR_UNLOAD ((NTSTATUS) 0xC000038EL) -#endif - -#ifndef STATUS_SMARTCARD_SILENT_CONTEXT -# define STATUS_SMARTCARD_SILENT_CONTEXT ((NTSTATUS) 0xC000038FL) -#endif - -#ifndef STATUS_PER_USER_TRUST_QUOTA_EXCEEDED -# define STATUS_PER_USER_TRUST_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000401L) -#endif - -#ifndef STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED -# define STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000402L) -#endif - -#ifndef STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED -# define STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000403L) -#endif - -#ifndef STATUS_DS_NAME_NOT_UNIQUE -# define STATUS_DS_NAME_NOT_UNIQUE ((NTSTATUS) 0xC0000404L) -#endif - -#ifndef STATUS_DS_DUPLICATE_ID_FOUND -# define STATUS_DS_DUPLICATE_ID_FOUND ((NTSTATUS) 0xC0000405L) -#endif - -#ifndef STATUS_DS_GROUP_CONVERSION_ERROR -# define STATUS_DS_GROUP_CONVERSION_ERROR ((NTSTATUS) 0xC0000406L) -#endif - -#ifndef STATUS_VOLSNAP_PREPARE_HIBERNATE -# define STATUS_VOLSNAP_PREPARE_HIBERNATE ((NTSTATUS) 0xC0000407L) -#endif - -#ifndef STATUS_USER2USER_REQUIRED -# define STATUS_USER2USER_REQUIRED ((NTSTATUS) 0xC0000408L) -#endif - -#ifndef STATUS_STACK_BUFFER_OVERRUN -# define STATUS_STACK_BUFFER_OVERRUN ((NTSTATUS) 0xC0000409L) -#endif - -#ifndef STATUS_NO_S4U_PROT_SUPPORT -# define STATUS_NO_S4U_PROT_SUPPORT ((NTSTATUS) 0xC000040AL) -#endif - -#ifndef STATUS_CROSSREALM_DELEGATION_FAILURE -# define STATUS_CROSSREALM_DELEGATION_FAILURE ((NTSTATUS) 0xC000040BL) -#endif - -#ifndef STATUS_REVOCATION_OFFLINE_KDC -# define STATUS_REVOCATION_OFFLINE_KDC ((NTSTATUS) 0xC000040CL) -#endif - -#ifndef STATUS_ISSUING_CA_UNTRUSTED_KDC -# define STATUS_ISSUING_CA_UNTRUSTED_KDC ((NTSTATUS) 0xC000040DL) -#endif - -#ifndef STATUS_KDC_CERT_EXPIRED -# define STATUS_KDC_CERT_EXPIRED ((NTSTATUS) 0xC000040EL) -#endif - -#ifndef STATUS_KDC_CERT_REVOKED -# define STATUS_KDC_CERT_REVOKED ((NTSTATUS) 0xC000040FL) -#endif - -#ifndef STATUS_PARAMETER_QUOTA_EXCEEDED -# define STATUS_PARAMETER_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000410L) -#endif - -#ifndef STATUS_HIBERNATION_FAILURE -# define STATUS_HIBERNATION_FAILURE ((NTSTATUS) 0xC0000411L) -#endif - -#ifndef STATUS_DELAY_LOAD_FAILED -# define STATUS_DELAY_LOAD_FAILED ((NTSTATUS) 0xC0000412L) -#endif - -#ifndef STATUS_AUTHENTICATION_FIREWALL_FAILED -# define STATUS_AUTHENTICATION_FIREWALL_FAILED ((NTSTATUS) 0xC0000413L) -#endif - -#ifndef STATUS_VDM_DISALLOWED -# define STATUS_VDM_DISALLOWED ((NTSTATUS) 0xC0000414L) -#endif - -#ifndef STATUS_HUNG_DISPLAY_DRIVER_THREAD -# define STATUS_HUNG_DISPLAY_DRIVER_THREAD ((NTSTATUS) 0xC0000415L) -#endif - -#ifndef STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE -# define STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE ((NTSTATUS) 0xC0000416L) -#endif - -#ifndef STATUS_INVALID_CRUNTIME_PARAMETER -# define STATUS_INVALID_CRUNTIME_PARAMETER ((NTSTATUS) 0xC0000417L) -#endif - -#ifndef STATUS_NTLM_BLOCKED -# define STATUS_NTLM_BLOCKED ((NTSTATUS) 0xC0000418L) -#endif - -#ifndef STATUS_DS_SRC_SID_EXISTS_IN_FOREST -# define STATUS_DS_SRC_SID_EXISTS_IN_FOREST ((NTSTATUS) 0xC0000419L) -#endif - -#ifndef STATUS_DS_DOMAIN_NAME_EXISTS_IN_FOREST -# define STATUS_DS_DOMAIN_NAME_EXISTS_IN_FOREST ((NTSTATUS) 0xC000041AL) -#endif - -#ifndef STATUS_DS_FLAT_NAME_EXISTS_IN_FOREST -# define STATUS_DS_FLAT_NAME_EXISTS_IN_FOREST ((NTSTATUS) 0xC000041BL) -#endif - -#ifndef STATUS_INVALID_USER_PRINCIPAL_NAME -# define STATUS_INVALID_USER_PRINCIPAL_NAME ((NTSTATUS) 0xC000041CL) -#endif - -#ifndef STATUS_FATAL_USER_CALLBACK_EXCEPTION -# define STATUS_FATAL_USER_CALLBACK_EXCEPTION ((NTSTATUS) 0xC000041DL) -#endif - -#ifndef STATUS_ASSERTION_FAILURE -# define STATUS_ASSERTION_FAILURE ((NTSTATUS) 0xC0000420L) -#endif - -#ifndef STATUS_VERIFIER_STOP -# define STATUS_VERIFIER_STOP ((NTSTATUS) 0xC0000421L) -#endif - -#ifndef STATUS_CALLBACK_POP_STACK -# define STATUS_CALLBACK_POP_STACK ((NTSTATUS) 0xC0000423L) -#endif - -#ifndef STATUS_INCOMPATIBLE_DRIVER_BLOCKED -# define STATUS_INCOMPATIBLE_DRIVER_BLOCKED ((NTSTATUS) 0xC0000424L) -#endif - -#ifndef STATUS_HIVE_UNLOADED -# define STATUS_HIVE_UNLOADED ((NTSTATUS) 0xC0000425L) -#endif - -#ifndef STATUS_COMPRESSION_DISABLED -# define STATUS_COMPRESSION_DISABLED ((NTSTATUS) 0xC0000426L) -#endif - -#ifndef STATUS_FILE_SYSTEM_LIMITATION -# define STATUS_FILE_SYSTEM_LIMITATION ((NTSTATUS) 0xC0000427L) -#endif - -#ifndef STATUS_INVALID_IMAGE_HASH -# define STATUS_INVALID_IMAGE_HASH ((NTSTATUS) 0xC0000428L) -#endif - -#ifndef STATUS_NOT_CAPABLE -# define STATUS_NOT_CAPABLE ((NTSTATUS) 0xC0000429L) -#endif - -#ifndef STATUS_REQUEST_OUT_OF_SEQUENCE -# define STATUS_REQUEST_OUT_OF_SEQUENCE ((NTSTATUS) 0xC000042AL) -#endif - -#ifndef STATUS_IMPLEMENTATION_LIMIT -# define STATUS_IMPLEMENTATION_LIMIT ((NTSTATUS) 0xC000042BL) -#endif - -#ifndef STATUS_ELEVATION_REQUIRED -# define STATUS_ELEVATION_REQUIRED ((NTSTATUS) 0xC000042CL) -#endif - -#ifndef STATUS_NO_SECURITY_CONTEXT -# define STATUS_NO_SECURITY_CONTEXT ((NTSTATUS) 0xC000042DL) -#endif - -#ifndef STATUS_PKU2U_CERT_FAILURE -# define STATUS_PKU2U_CERT_FAILURE ((NTSTATUS) 0xC000042FL) -#endif - -#ifndef STATUS_BEYOND_VDL -# define STATUS_BEYOND_VDL ((NTSTATUS) 0xC0000432L) -#endif - -#ifndef STATUS_ENCOUNTERED_WRITE_IN_PROGRESS -# define STATUS_ENCOUNTERED_WRITE_IN_PROGRESS ((NTSTATUS) 0xC0000433L) -#endif - -#ifndef STATUS_PTE_CHANGED -# define STATUS_PTE_CHANGED ((NTSTATUS) 0xC0000434L) -#endif - -#ifndef STATUS_PURGE_FAILED -# define STATUS_PURGE_FAILED ((NTSTATUS) 0xC0000435L) -#endif - -#ifndef STATUS_CRED_REQUIRES_CONFIRMATION -# define STATUS_CRED_REQUIRES_CONFIRMATION ((NTSTATUS) 0xC0000440L) -#endif - -#ifndef STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE -# define STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE ((NTSTATUS) 0xC0000441L) -#endif - -#ifndef STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER -# define STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER ((NTSTATUS) 0xC0000442L) -#endif - -#ifndef STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE -# define STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE ((NTSTATUS) 0xC0000443L) -#endif - -#ifndef STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE -# define STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE ((NTSTATUS) 0xC0000444L) -#endif - -#ifndef STATUS_CS_ENCRYPTION_FILE_NOT_CSE -# define STATUS_CS_ENCRYPTION_FILE_NOT_CSE ((NTSTATUS) 0xC0000445L) -#endif - -#ifndef STATUS_INVALID_LABEL -# define STATUS_INVALID_LABEL ((NTSTATUS) 0xC0000446L) -#endif - -#ifndef STATUS_DRIVER_PROCESS_TERMINATED -# define STATUS_DRIVER_PROCESS_TERMINATED ((NTSTATUS) 0xC0000450L) -#endif - -#ifndef STATUS_AMBIGUOUS_SYSTEM_DEVICE -# define STATUS_AMBIGUOUS_SYSTEM_DEVICE ((NTSTATUS) 0xC0000451L) -#endif - -#ifndef STATUS_SYSTEM_DEVICE_NOT_FOUND -# define STATUS_SYSTEM_DEVICE_NOT_FOUND ((NTSTATUS) 0xC0000452L) -#endif - -#ifndef STATUS_RESTART_BOOT_APPLICATION -# define STATUS_RESTART_BOOT_APPLICATION ((NTSTATUS) 0xC0000453L) -#endif - -#ifndef STATUS_INSUFFICIENT_NVRAM_RESOURCES -# define STATUS_INSUFFICIENT_NVRAM_RESOURCES ((NTSTATUS) 0xC0000454L) -#endif - -#ifndef STATUS_INVALID_TASK_NAME -# define STATUS_INVALID_TASK_NAME ((NTSTATUS) 0xC0000500L) -#endif - -#ifndef STATUS_INVALID_TASK_INDEX -# define STATUS_INVALID_TASK_INDEX ((NTSTATUS) 0xC0000501L) -#endif - -#ifndef STATUS_THREAD_ALREADY_IN_TASK -# define STATUS_THREAD_ALREADY_IN_TASK ((NTSTATUS) 0xC0000502L) -#endif - -#ifndef STATUS_CALLBACK_BYPASS -# define STATUS_CALLBACK_BYPASS ((NTSTATUS) 0xC0000503L) -#endif - -#ifndef STATUS_FAIL_FAST_EXCEPTION -# define STATUS_FAIL_FAST_EXCEPTION ((NTSTATUS) 0xC0000602L) -#endif - -#ifndef STATUS_IMAGE_CERT_REVOKED -# define STATUS_IMAGE_CERT_REVOKED ((NTSTATUS) 0xC0000603L) -#endif - -#ifndef STATUS_PORT_CLOSED -# define STATUS_PORT_CLOSED ((NTSTATUS) 0xC0000700L) -#endif - -#ifndef STATUS_MESSAGE_LOST -# define STATUS_MESSAGE_LOST ((NTSTATUS) 0xC0000701L) -#endif - -#ifndef STATUS_INVALID_MESSAGE -# define STATUS_INVALID_MESSAGE ((NTSTATUS) 0xC0000702L) -#endif - -#ifndef STATUS_REQUEST_CANCELED -# define STATUS_REQUEST_CANCELED ((NTSTATUS) 0xC0000703L) -#endif - -#ifndef STATUS_RECURSIVE_DISPATCH -# define STATUS_RECURSIVE_DISPATCH ((NTSTATUS) 0xC0000704L) -#endif - -#ifndef STATUS_LPC_RECEIVE_BUFFER_EXPECTED -# define STATUS_LPC_RECEIVE_BUFFER_EXPECTED ((NTSTATUS) 0xC0000705L) -#endif - -#ifndef STATUS_LPC_INVALID_CONNECTION_USAGE -# define STATUS_LPC_INVALID_CONNECTION_USAGE ((NTSTATUS) 0xC0000706L) -#endif - -#ifndef STATUS_LPC_REQUESTS_NOT_ALLOWED -# define STATUS_LPC_REQUESTS_NOT_ALLOWED ((NTSTATUS) 0xC0000707L) -#endif - -#ifndef STATUS_RESOURCE_IN_USE -# define STATUS_RESOURCE_IN_USE ((NTSTATUS) 0xC0000708L) -#endif - -#ifndef STATUS_HARDWARE_MEMORY_ERROR -# define STATUS_HARDWARE_MEMORY_ERROR ((NTSTATUS) 0xC0000709L) -#endif - -#ifndef STATUS_THREADPOOL_HANDLE_EXCEPTION -# define STATUS_THREADPOOL_HANDLE_EXCEPTION ((NTSTATUS) 0xC000070AL) -#endif - -#ifndef STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED -# define STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED ((NTSTATUS) 0xC000070BL) -#endif - -#ifndef STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED -# define STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED ((NTSTATUS) 0xC000070CL) -#endif - -#ifndef STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED -# define STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED ((NTSTATUS) 0xC000070DL) -#endif - -#ifndef STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED -# define STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED ((NTSTATUS) 0xC000070EL) -#endif - -#ifndef STATUS_THREADPOOL_RELEASED_DURING_OPERATION -# define STATUS_THREADPOOL_RELEASED_DURING_OPERATION ((NTSTATUS) 0xC000070FL) -#endif - -#ifndef STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING -# define STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING ((NTSTATUS) 0xC0000710L) -#endif - -#ifndef STATUS_APC_RETURNED_WHILE_IMPERSONATING -# define STATUS_APC_RETURNED_WHILE_IMPERSONATING ((NTSTATUS) 0xC0000711L) -#endif - -#ifndef STATUS_PROCESS_IS_PROTECTED -# define STATUS_PROCESS_IS_PROTECTED ((NTSTATUS) 0xC0000712L) -#endif - -#ifndef STATUS_MCA_EXCEPTION -# define STATUS_MCA_EXCEPTION ((NTSTATUS) 0xC0000713L) -#endif - -#ifndef STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE -# define STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE ((NTSTATUS) 0xC0000714L) -#endif - -#ifndef STATUS_SYMLINK_CLASS_DISABLED -# define STATUS_SYMLINK_CLASS_DISABLED ((NTSTATUS) 0xC0000715L) -#endif - -#ifndef STATUS_INVALID_IDN_NORMALIZATION -# define STATUS_INVALID_IDN_NORMALIZATION ((NTSTATUS) 0xC0000716L) -#endif - -#ifndef STATUS_NO_UNICODE_TRANSLATION -# define STATUS_NO_UNICODE_TRANSLATION ((NTSTATUS) 0xC0000717L) -#endif - -#ifndef STATUS_ALREADY_REGISTERED -# define STATUS_ALREADY_REGISTERED ((NTSTATUS) 0xC0000718L) -#endif - -#ifndef STATUS_CONTEXT_MISMATCH -# define STATUS_CONTEXT_MISMATCH ((NTSTATUS) 0xC0000719L) -#endif - -#ifndef STATUS_PORT_ALREADY_HAS_COMPLETION_LIST -# define STATUS_PORT_ALREADY_HAS_COMPLETION_LIST ((NTSTATUS) 0xC000071AL) -#endif - -#ifndef STATUS_CALLBACK_RETURNED_THREAD_PRIORITY -# define STATUS_CALLBACK_RETURNED_THREAD_PRIORITY ((NTSTATUS) 0xC000071BL) -#endif - -#ifndef STATUS_INVALID_THREAD -# define STATUS_INVALID_THREAD ((NTSTATUS) 0xC000071CL) -#endif - -#ifndef STATUS_CALLBACK_RETURNED_TRANSACTION -# define STATUS_CALLBACK_RETURNED_TRANSACTION ((NTSTATUS) 0xC000071DL) -#endif - -#ifndef STATUS_CALLBACK_RETURNED_LDR_LOCK -# define STATUS_CALLBACK_RETURNED_LDR_LOCK ((NTSTATUS) 0xC000071EL) -#endif - -#ifndef STATUS_CALLBACK_RETURNED_LANG -# define STATUS_CALLBACK_RETURNED_LANG ((NTSTATUS) 0xC000071FL) -#endif - -#ifndef STATUS_CALLBACK_RETURNED_PRI_BACK -# define STATUS_CALLBACK_RETURNED_PRI_BACK ((NTSTATUS) 0xC0000720L) -#endif - -#ifndef STATUS_CALLBACK_RETURNED_THREAD_AFFINITY -# define STATUS_CALLBACK_RETURNED_THREAD_AFFINITY ((NTSTATUS) 0xC0000721L) -#endif - -#ifndef STATUS_DISK_REPAIR_DISABLED -# define STATUS_DISK_REPAIR_DISABLED ((NTSTATUS) 0xC0000800L) -#endif - -#ifndef STATUS_DS_DOMAIN_RENAME_IN_PROGRESS -# define STATUS_DS_DOMAIN_RENAME_IN_PROGRESS ((NTSTATUS) 0xC0000801L) -#endif - -#ifndef STATUS_DISK_QUOTA_EXCEEDED -# define STATUS_DISK_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000802L) -#endif - -#ifndef STATUS_DATA_LOST_REPAIR -# define STATUS_DATA_LOST_REPAIR ((NTSTATUS) 0x80000803L) -#endif - -#ifndef STATUS_CONTENT_BLOCKED -# define STATUS_CONTENT_BLOCKED ((NTSTATUS) 0xC0000804L) -#endif - -#ifndef STATUS_BAD_CLUSTERS -# define STATUS_BAD_CLUSTERS ((NTSTATUS) 0xC0000805L) -#endif - -#ifndef STATUS_VOLUME_DIRTY -# define STATUS_VOLUME_DIRTY ((NTSTATUS) 0xC0000806L) -#endif - -#ifndef STATUS_FILE_CHECKED_OUT -# define STATUS_FILE_CHECKED_OUT ((NTSTATUS) 0xC0000901L) -#endif - -#ifndef STATUS_CHECKOUT_REQUIRED -# define STATUS_CHECKOUT_REQUIRED ((NTSTATUS) 0xC0000902L) -#endif - -#ifndef STATUS_BAD_FILE_TYPE -# define STATUS_BAD_FILE_TYPE ((NTSTATUS) 0xC0000903L) -#endif - -#ifndef STATUS_FILE_TOO_LARGE -# define STATUS_FILE_TOO_LARGE ((NTSTATUS) 0xC0000904L) -#endif - -#ifndef STATUS_FORMS_AUTH_REQUIRED -# define STATUS_FORMS_AUTH_REQUIRED ((NTSTATUS) 0xC0000905L) -#endif - -#ifndef STATUS_VIRUS_INFECTED -# define STATUS_VIRUS_INFECTED ((NTSTATUS) 0xC0000906L) -#endif - -#ifndef STATUS_VIRUS_DELETED -# define STATUS_VIRUS_DELETED ((NTSTATUS) 0xC0000907L) -#endif - -#ifndef STATUS_BAD_MCFG_TABLE -# define STATUS_BAD_MCFG_TABLE ((NTSTATUS) 0xC0000908L) -#endif - -#ifndef STATUS_CANNOT_BREAK_OPLOCK -# define STATUS_CANNOT_BREAK_OPLOCK ((NTSTATUS) 0xC0000909L) -#endif - -#ifndef STATUS_WOW_ASSERTION -# define STATUS_WOW_ASSERTION ((NTSTATUS) 0xC0009898L) -#endif - -#ifndef STATUS_INVALID_SIGNATURE -# define STATUS_INVALID_SIGNATURE ((NTSTATUS) 0xC000A000L) -#endif - -#ifndef STATUS_HMAC_NOT_SUPPORTED -# define STATUS_HMAC_NOT_SUPPORTED ((NTSTATUS) 0xC000A001L) -#endif - -#ifndef STATUS_AUTH_TAG_MISMATCH -# define STATUS_AUTH_TAG_MISMATCH ((NTSTATUS) 0xC000A002L) -#endif - -#ifndef STATUS_IPSEC_QUEUE_OVERFLOW -# define STATUS_IPSEC_QUEUE_OVERFLOW ((NTSTATUS) 0xC000A010L) -#endif - -#ifndef STATUS_ND_QUEUE_OVERFLOW -# define STATUS_ND_QUEUE_OVERFLOW ((NTSTATUS) 0xC000A011L) -#endif - -#ifndef STATUS_HOPLIMIT_EXCEEDED -# define STATUS_HOPLIMIT_EXCEEDED ((NTSTATUS) 0xC000A012L) -#endif - -#ifndef STATUS_PROTOCOL_NOT_SUPPORTED -# define STATUS_PROTOCOL_NOT_SUPPORTED ((NTSTATUS) 0xC000A013L) -#endif - -#ifndef STATUS_FASTPATH_REJECTED -# define STATUS_FASTPATH_REJECTED ((NTSTATUS) 0xC000A014L) -#endif - -#ifndef STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED -# define STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED ((NTSTATUS) 0xC000A080L) -#endif - -#ifndef STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR -# define STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR ((NTSTATUS) 0xC000A081L) -#endif - -#ifndef STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR -# define STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR ((NTSTATUS) 0xC000A082L) -#endif - -#ifndef STATUS_XML_PARSE_ERROR -# define STATUS_XML_PARSE_ERROR ((NTSTATUS) 0xC000A083L) -#endif - -#ifndef STATUS_XMLDSIG_ERROR -# define STATUS_XMLDSIG_ERROR ((NTSTATUS) 0xC000A084L) -#endif - -#ifndef STATUS_WRONG_COMPARTMENT -# define STATUS_WRONG_COMPARTMENT ((NTSTATUS) 0xC000A085L) -#endif - -#ifndef STATUS_AUTHIP_FAILURE -# define STATUS_AUTHIP_FAILURE ((NTSTATUS) 0xC000A086L) -#endif - -#ifndef STATUS_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS -# define STATUS_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS ((NTSTATUS) 0xC000A087L) -#endif - -#ifndef STATUS_DS_OID_NOT_FOUND -# define STATUS_DS_OID_NOT_FOUND ((NTSTATUS) 0xC000A088L) -#endif - -#ifndef STATUS_HASH_NOT_SUPPORTED -# define STATUS_HASH_NOT_SUPPORTED ((NTSTATUS) 0xC000A100L) -#endif - -#ifndef STATUS_HASH_NOT_PRESENT -# define STATUS_HASH_NOT_PRESENT ((NTSTATUS) 0xC000A101L) -#endif - -/* This is not the NTSTATUS_FROM_WIN32 that the DDK provides, because the */ -/* DDK got it wrong! */ -#ifdef NTSTATUS_FROM_WIN32 -# undef NTSTATUS_FROM_WIN32 -#endif -#define NTSTATUS_FROM_WIN32(error) ((NTSTATUS) (error) <= 0 ? \ - ((NTSTATUS) (error)) : ((NTSTATUS) (((error) & 0x0000FFFF) | \ - (FACILITY_NTWIN32 << 16) | ERROR_SEVERITY_WARNING))) - -#ifndef JOB_OBJECT_LIMIT_PROCESS_MEMORY -# define JOB_OBJECT_LIMIT_PROCESS_MEMORY 0x00000100 -#endif -#ifndef JOB_OBJECT_LIMIT_JOB_MEMORY -# define JOB_OBJECT_LIMIT_JOB_MEMORY 0x00000200 -#endif -#ifndef JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION -# define JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION 0x00000400 -#endif -#ifndef JOB_OBJECT_LIMIT_BREAKAWAY_OK -# define JOB_OBJECT_LIMIT_BREAKAWAY_OK 0x00000800 -#endif -#ifndef JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK -# define JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK 0x00001000 -#endif -#ifndef JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE -# define JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE 0x00002000 -#endif - -/* from winternl.h */ -typedef struct _UNICODE_STRING { - USHORT Length; - USHORT MaximumLength; - PWSTR Buffer; -} UNICODE_STRING, *PUNICODE_STRING; - -typedef const UNICODE_STRING *PCUNICODE_STRING; - -/* from ntifs.h */ -#ifndef DEVICE_TYPE -# define DEVICE_TYPE DWORD -#endif - -/* MinGW already has a definition for REPARSE_DATA_BUFFER, but mingw-w64 does - * not. - */ -#if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR) - typedef struct _REPARSE_DATA_BUFFER { - ULONG ReparseTag; - USHORT ReparseDataLength; - USHORT Reserved; - union { - struct { - USHORT SubstituteNameOffset; - USHORT SubstituteNameLength; - USHORT PrintNameOffset; - USHORT PrintNameLength; - ULONG Flags; - WCHAR PathBuffer[1]; - } SymbolicLinkReparseBuffer; - struct { - USHORT SubstituteNameOffset; - USHORT SubstituteNameLength; - USHORT PrintNameOffset; - USHORT PrintNameLength; - WCHAR PathBuffer[1]; - } MountPointReparseBuffer; - struct { - UCHAR DataBuffer[1]; - } GenericReparseBuffer; - } DUMMYUNIONNAME; - } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; -#endif - -typedef struct _IO_STATUS_BLOCK { - union { - NTSTATUS Status; - PVOID Pointer; - } DUMMYUNIONNAME; - ULONG_PTR Information; -} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; - -typedef enum _FILE_INFORMATION_CLASS { - FileDirectoryInformation = 1, - FileFullDirectoryInformation, - FileBothDirectoryInformation, - FileBasicInformation, - FileStandardInformation, - FileInternalInformation, - FileEaInformation, - FileAccessInformation, - FileNameInformation, - FileRenameInformation, - FileLinkInformation, - FileNamesInformation, - FileDispositionInformation, - FilePositionInformation, - FileFullEaInformation, - FileModeInformation, - FileAlignmentInformation, - FileAllInformation, - FileAllocationInformation, - FileEndOfFileInformation, - FileAlternateNameInformation, - FileStreamInformation, - FilePipeInformation, - FilePipeLocalInformation, - FilePipeRemoteInformation, - FileMailslotQueryInformation, - FileMailslotSetInformation, - FileCompressionInformation, - FileObjectIdInformation, - FileCompletionInformation, - FileMoveClusterInformation, - FileQuotaInformation, - FileReparsePointInformation, - FileNetworkOpenInformation, - FileAttributeTagInformation, - FileTrackingInformation, - FileIdBothDirectoryInformation, - FileIdFullDirectoryInformation, - FileValidDataLengthInformation, - FileShortNameInformation, - FileIoCompletionNotificationInformation, - FileIoStatusBlockRangeInformation, - FileIoPriorityHintInformation, - FileSfioReserveInformation, - FileSfioVolumeInformation, - FileHardLinkInformation, - FileProcessIdsUsingFileInformation, - FileNormalizedNameInformation, - FileNetworkPhysicalNameInformation, - FileIdGlobalTxDirectoryInformation, - FileIsRemoteDeviceInformation, - FileAttributeCacheInformation, - FileNumaNodeInformation, - FileStandardLinkInformation, - FileRemoteProtocolInformation, - FileMaximumInformation -} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; - -typedef struct _FILE_DIRECTORY_INFORMATION { - ULONG NextEntryOffset; - ULONG FileIndex; - LARGE_INTEGER CreationTime; - LARGE_INTEGER LastAccessTime; - LARGE_INTEGER LastWriteTime; - LARGE_INTEGER ChangeTime; - LARGE_INTEGER EndOfFile; - LARGE_INTEGER AllocationSize; - ULONG FileAttributes; - ULONG FileNameLength; - WCHAR FileName[1]; -} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION; - -typedef struct _FILE_BOTH_DIR_INFORMATION { - ULONG NextEntryOffset; - ULONG FileIndex; - LARGE_INTEGER CreationTime; - LARGE_INTEGER LastAccessTime; - LARGE_INTEGER LastWriteTime; - LARGE_INTEGER ChangeTime; - LARGE_INTEGER EndOfFile; - LARGE_INTEGER AllocationSize; - ULONG FileAttributes; - ULONG FileNameLength; - ULONG EaSize; - CCHAR ShortNameLength; - WCHAR ShortName[12]; - WCHAR FileName[1]; -} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION; - -typedef struct _FILE_BASIC_INFORMATION { - LARGE_INTEGER CreationTime; - LARGE_INTEGER LastAccessTime; - LARGE_INTEGER LastWriteTime; - LARGE_INTEGER ChangeTime; - DWORD FileAttributes; -} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION; - -typedef struct _FILE_STANDARD_INFORMATION { - LARGE_INTEGER AllocationSize; - LARGE_INTEGER EndOfFile; - ULONG NumberOfLinks; - BOOLEAN DeletePending; - BOOLEAN Directory; -} FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION; - -typedef struct _FILE_INTERNAL_INFORMATION { - LARGE_INTEGER IndexNumber; -} FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION; - -typedef struct _FILE_EA_INFORMATION { - ULONG EaSize; -} FILE_EA_INFORMATION, *PFILE_EA_INFORMATION; - -typedef struct _FILE_ACCESS_INFORMATION { - ACCESS_MASK AccessFlags; -} FILE_ACCESS_INFORMATION, *PFILE_ACCESS_INFORMATION; - -typedef struct _FILE_POSITION_INFORMATION { - LARGE_INTEGER CurrentByteOffset; -} FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION; - -typedef struct _FILE_MODE_INFORMATION { - ULONG Mode; -} FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION; - -typedef struct _FILE_ALIGNMENT_INFORMATION { - ULONG AlignmentRequirement; -} FILE_ALIGNMENT_INFORMATION, *PFILE_ALIGNMENT_INFORMATION; - -typedef struct _FILE_NAME_INFORMATION { - ULONG FileNameLength; - WCHAR FileName[1]; -} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION; - -typedef struct _FILE_END_OF_FILE_INFORMATION { - LARGE_INTEGER EndOfFile; -} FILE_END_OF_FILE_INFORMATION, *PFILE_END_OF_FILE_INFORMATION; - -typedef struct _FILE_ALL_INFORMATION { - FILE_BASIC_INFORMATION BasicInformation; - FILE_STANDARD_INFORMATION StandardInformation; - FILE_INTERNAL_INFORMATION InternalInformation; - FILE_EA_INFORMATION EaInformation; - FILE_ACCESS_INFORMATION AccessInformation; - FILE_POSITION_INFORMATION PositionInformation; - FILE_MODE_INFORMATION ModeInformation; - FILE_ALIGNMENT_INFORMATION AlignmentInformation; - FILE_NAME_INFORMATION NameInformation; -} FILE_ALL_INFORMATION, *PFILE_ALL_INFORMATION; - -typedef struct _FILE_DISPOSITION_INFORMATION { - BOOLEAN DeleteFile; -} FILE_DISPOSITION_INFORMATION, *PFILE_DISPOSITION_INFORMATION; - -typedef struct _FILE_PIPE_LOCAL_INFORMATION { - ULONG NamedPipeType; - ULONG NamedPipeConfiguration; - ULONG MaximumInstances; - ULONG CurrentInstances; - ULONG InboundQuota; - ULONG ReadDataAvailable; - ULONG OutboundQuota; - ULONG WriteQuotaAvailable; - ULONG NamedPipeState; - ULONG NamedPipeEnd; -} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION; - -#define FILE_SYNCHRONOUS_IO_ALERT 0x00000010 -#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020 - -typedef enum _FS_INFORMATION_CLASS { - FileFsVolumeInformation = 1, - FileFsLabelInformation = 2, - FileFsSizeInformation = 3, - FileFsDeviceInformation = 4, - FileFsAttributeInformation = 5, - FileFsControlInformation = 6, - FileFsFullSizeInformation = 7, - FileFsObjectIdInformation = 8, - FileFsDriverPathInformation = 9, - FileFsVolumeFlagsInformation = 10, - FileFsSectorSizeInformation = 11 -} FS_INFORMATION_CLASS, *PFS_INFORMATION_CLASS; - -typedef struct _FILE_FS_VOLUME_INFORMATION { - LARGE_INTEGER VolumeCreationTime; - ULONG VolumeSerialNumber; - ULONG VolumeLabelLength; - BOOLEAN SupportsObjects; - WCHAR VolumeLabel[1]; -} FILE_FS_VOLUME_INFORMATION, *PFILE_FS_VOLUME_INFORMATION; - -typedef struct _FILE_FS_LABEL_INFORMATION { - ULONG VolumeLabelLength; - WCHAR VolumeLabel[1]; -} FILE_FS_LABEL_INFORMATION, *PFILE_FS_LABEL_INFORMATION; - -typedef struct _FILE_FS_SIZE_INFORMATION { - LARGE_INTEGER TotalAllocationUnits; - LARGE_INTEGER AvailableAllocationUnits; - ULONG SectorsPerAllocationUnit; - ULONG BytesPerSector; -} FILE_FS_SIZE_INFORMATION, *PFILE_FS_SIZE_INFORMATION; - -typedef struct _FILE_FS_DEVICE_INFORMATION { - DEVICE_TYPE DeviceType; - ULONG Characteristics; -} FILE_FS_DEVICE_INFORMATION, *PFILE_FS_DEVICE_INFORMATION; - -typedef struct _FILE_FS_ATTRIBUTE_INFORMATION { - ULONG FileSystemAttributes; - LONG MaximumComponentNameLength; - ULONG FileSystemNameLength; - WCHAR FileSystemName[1]; -} FILE_FS_ATTRIBUTE_INFORMATION, *PFILE_FS_ATTRIBUTE_INFORMATION; - -typedef struct _FILE_FS_CONTROL_INFORMATION { - LARGE_INTEGER FreeSpaceStartFiltering; - LARGE_INTEGER FreeSpaceThreshold; - LARGE_INTEGER FreeSpaceStopFiltering; - LARGE_INTEGER DefaultQuotaThreshold; - LARGE_INTEGER DefaultQuotaLimit; - ULONG FileSystemControlFlags; -} FILE_FS_CONTROL_INFORMATION, *PFILE_FS_CONTROL_INFORMATION; - -typedef struct _FILE_FS_FULL_SIZE_INFORMATION { - LARGE_INTEGER TotalAllocationUnits; - LARGE_INTEGER CallerAvailableAllocationUnits; - LARGE_INTEGER ActualAvailableAllocationUnits; - ULONG SectorsPerAllocationUnit; - ULONG BytesPerSector; -} FILE_FS_FULL_SIZE_INFORMATION, *PFILE_FS_FULL_SIZE_INFORMATION; - -typedef struct _FILE_FS_OBJECTID_INFORMATION { - UCHAR ObjectId[16]; - UCHAR ExtendedInfo[48]; -} FILE_FS_OBJECTID_INFORMATION, *PFILE_FS_OBJECTID_INFORMATION; - -typedef struct _FILE_FS_DRIVER_PATH_INFORMATION { - BOOLEAN DriverInPath; - ULONG DriverNameLength; - WCHAR DriverName[1]; -} FILE_FS_DRIVER_PATH_INFORMATION, *PFILE_FS_DRIVER_PATH_INFORMATION; - -typedef struct _FILE_FS_VOLUME_FLAGS_INFORMATION { - ULONG Flags; -} FILE_FS_VOLUME_FLAGS_INFORMATION, *PFILE_FS_VOLUME_FLAGS_INFORMATION; - -typedef struct _FILE_FS_SECTOR_SIZE_INFORMATION { - ULONG LogicalBytesPerSector; - ULONG PhysicalBytesPerSectorForAtomicity; - ULONG PhysicalBytesPerSectorForPerformance; - ULONG FileSystemEffectivePhysicalBytesPerSectorForAtomicity; - ULONG Flags; - ULONG ByteOffsetForSectorAlignment; - ULONG ByteOffsetForPartitionAlignment; -} FILE_FS_SECTOR_SIZE_INFORMATION, *PFILE_FS_SECTOR_SIZE_INFORMATION; - -typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION { - LARGE_INTEGER IdleTime; - LARGE_INTEGER KernelTime; - LARGE_INTEGER UserTime; - LARGE_INTEGER DpcTime; - LARGE_INTEGER InterruptTime; - ULONG InterruptCount; -} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, *PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION; - -#ifndef SystemProcessorPerformanceInformation -# define SystemProcessorPerformanceInformation 8 -#endif - -#ifndef FILE_DEVICE_FILE_SYSTEM -# define FILE_DEVICE_FILE_SYSTEM 0x00000009 -#endif - -#ifndef FILE_DEVICE_NETWORK -# define FILE_DEVICE_NETWORK 0x00000012 -#endif - -#ifndef METHOD_BUFFERED -# define METHOD_BUFFERED 0 -#endif - -#ifndef METHOD_IN_DIRECT -# define METHOD_IN_DIRECT 1 -#endif - -#ifndef METHOD_OUT_DIRECT -# define METHOD_OUT_DIRECT 2 -#endif - -#ifndef METHOD_NEITHER -#define METHOD_NEITHER 3 -#endif - -#ifndef METHOD_DIRECT_TO_HARDWARE -# define METHOD_DIRECT_TO_HARDWARE METHOD_IN_DIRECT -#endif - -#ifndef METHOD_DIRECT_FROM_HARDWARE -# define METHOD_DIRECT_FROM_HARDWARE METHOD_OUT_DIRECT -#endif - -#ifndef FILE_ANY_ACCESS -# define FILE_ANY_ACCESS 0 -#endif - -#ifndef FILE_SPECIAL_ACCESS -# define FILE_SPECIAL_ACCESS (FILE_ANY_ACCESS) -#endif - -#ifndef FILE_READ_ACCESS -# define FILE_READ_ACCESS 0x0001 -#endif - -#ifndef FILE_WRITE_ACCESS -# define FILE_WRITE_ACCESS 0x0002 -#endif - -#ifndef CTL_CODE -# define CTL_CODE(device_type, function, method, access) \ - (((device_type) << 16) | ((access) << 14) | ((function) << 2) | (method)) -#endif - -#ifndef FSCTL_SET_REPARSE_POINT -# define FSCTL_SET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, \ - 41, \ - METHOD_BUFFERED, \ - FILE_SPECIAL_ACCESS) -#endif - -#ifndef FSCTL_GET_REPARSE_POINT -# define FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, \ - 42, \ - METHOD_BUFFERED, \ - FILE_ANY_ACCESS) -#endif - -#ifndef FSCTL_DELETE_REPARSE_POINT -# define FSCTL_DELETE_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, \ - 43, \ - METHOD_BUFFERED, \ - FILE_SPECIAL_ACCESS) -#endif - -#ifndef IO_REPARSE_TAG_SYMLINK -# define IO_REPARSE_TAG_SYMLINK (0xA000000CL) -#endif - -typedef VOID (NTAPI *PIO_APC_ROUTINE) - (PVOID ApcContext, - PIO_STATUS_BLOCK IoStatusBlock, - ULONG Reserved); - -typedef ULONG (NTAPI *sRtlNtStatusToDosError) - (NTSTATUS Status); - -typedef NTSTATUS (NTAPI *sNtDeviceIoControlFile) - (HANDLE FileHandle, - HANDLE Event, - PIO_APC_ROUTINE ApcRoutine, - PVOID ApcContext, - PIO_STATUS_BLOCK IoStatusBlock, - ULONG IoControlCode, - PVOID InputBuffer, - ULONG InputBufferLength, - PVOID OutputBuffer, - ULONG OutputBufferLength); - -typedef NTSTATUS (NTAPI *sNtQueryInformationFile) - (HANDLE FileHandle, - PIO_STATUS_BLOCK IoStatusBlock, - PVOID FileInformation, - ULONG Length, - FILE_INFORMATION_CLASS FileInformationClass); - -typedef NTSTATUS (NTAPI *sNtSetInformationFile) - (HANDLE FileHandle, - PIO_STATUS_BLOCK IoStatusBlock, - PVOID FileInformation, - ULONG Length, - FILE_INFORMATION_CLASS FileInformationClass); - -typedef NTSTATUS (NTAPI *sNtQueryVolumeInformationFile) - (HANDLE FileHandle, - PIO_STATUS_BLOCK IoStatusBlock, - PVOID FsInformation, - ULONG Length, - FS_INFORMATION_CLASS FsInformationClass); - -typedef NTSTATUS (NTAPI *sNtQuerySystemInformation) - (UINT SystemInformationClass, - PVOID SystemInformation, - ULONG SystemInformationLength, - PULONG ReturnLength); - -typedef NTSTATUS (NTAPI *sNtQueryDirectoryFile) - (HANDLE FileHandle, - HANDLE Event, - PIO_APC_ROUTINE ApcRoutine, - PVOID ApcContext, - PIO_STATUS_BLOCK IoStatusBlock, - PVOID FileInformation, - ULONG Length, - FILE_INFORMATION_CLASS FileInformationClass, - BOOLEAN ReturnSingleEntry, - PUNICODE_STRING FileName, - BOOLEAN RestartScan - ); - -/* - * Kernel32 headers - */ -#ifndef FILE_SKIP_COMPLETION_PORT_ON_SUCCESS -# define FILE_SKIP_COMPLETION_PORT_ON_SUCCESS 0x1 -#endif - -#ifndef FILE_SKIP_SET_EVENT_ON_HANDLE -# define FILE_SKIP_SET_EVENT_ON_HANDLE 0x2 -#endif - -#ifndef SYMBOLIC_LINK_FLAG_DIRECTORY -# define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1 -#endif - -#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) - typedef struct _OVERLAPPED_ENTRY { - ULONG_PTR lpCompletionKey; - LPOVERLAPPED lpOverlapped; - ULONG_PTR Internal; - DWORD dwNumberOfBytesTransferred; - } OVERLAPPED_ENTRY, *LPOVERLAPPED_ENTRY; -#endif - -/* from wincon.h */ -#ifndef ENABLE_INSERT_MODE -# define ENABLE_INSERT_MODE 0x20 -#endif - -#ifndef ENABLE_QUICK_EDIT_MODE -# define ENABLE_QUICK_EDIT_MODE 0x40 -#endif - -#ifndef ENABLE_EXTENDED_FLAGS -# define ENABLE_EXTENDED_FLAGS 0x80 -#endif - -/* from winerror.h */ -#ifndef ERROR_SYMLINK_NOT_SUPPORTED -# define ERROR_SYMLINK_NOT_SUPPORTED 1464 -#endif - -#ifndef ERROR_MUI_FILE_NOT_FOUND -# define ERROR_MUI_FILE_NOT_FOUND 15100 -#endif - -#ifndef ERROR_MUI_INVALID_FILE -# define ERROR_MUI_INVALID_FILE 15101 -#endif - -#ifndef ERROR_MUI_INVALID_RC_CONFIG -# define ERROR_MUI_INVALID_RC_CONFIG 15102 -#endif - -#ifndef ERROR_MUI_INVALID_LOCALE_NAME -# define ERROR_MUI_INVALID_LOCALE_NAME 15103 -#endif - -#ifndef ERROR_MUI_INVALID_ULTIMATEFALLBACK_NAME -# define ERROR_MUI_INVALID_ULTIMATEFALLBACK_NAME 15104 -#endif - -#ifndef ERROR_MUI_FILE_NOT_LOADED -# define ERROR_MUI_FILE_NOT_LOADED 15105 -#endif - -typedef BOOL (WINAPI *sGetQueuedCompletionStatusEx) - (HANDLE CompletionPort, - LPOVERLAPPED_ENTRY lpCompletionPortEntries, - ULONG ulCount, - PULONG ulNumEntriesRemoved, - DWORD dwMilliseconds, - BOOL fAlertable); - -typedef BOOL (WINAPI* sSetFileCompletionNotificationModes) - (HANDLE FileHandle, - UCHAR Flags); - -typedef BOOLEAN (WINAPI* sCreateSymbolicLinkW) - (LPCWSTR lpSymlinkFileName, - LPCWSTR lpTargetFileName, - DWORD dwFlags); - -typedef BOOL (WINAPI* sCancelIoEx) - (HANDLE hFile, - LPOVERLAPPED lpOverlapped); - -typedef VOID (WINAPI* sInitializeSRWLock) - (PSRWLOCK SRWLock); - -typedef VOID (WINAPI* sAcquireSRWLockShared) - (PSRWLOCK SRWLock); - -typedef VOID (WINAPI* sAcquireSRWLockExclusive) - (PSRWLOCK SRWLock); - -typedef BOOL (WINAPI* sTryAcquireSRWLockShared) - (PSRWLOCK SRWLock); - -typedef BOOL (WINAPI* sTryAcquireSRWLockExclusive) - (PSRWLOCK SRWLock); - -typedef VOID (WINAPI* sReleaseSRWLockShared) - (PSRWLOCK SRWLock); - -typedef VOID (WINAPI* sReleaseSRWLockExclusive) - (PSRWLOCK SRWLock); - -typedef VOID (WINAPI* sInitializeConditionVariable) - (PCONDITION_VARIABLE ConditionVariable); - -typedef BOOL (WINAPI* sSleepConditionVariableCS) - (PCONDITION_VARIABLE ConditionVariable, - PCRITICAL_SECTION CriticalSection, - DWORD dwMilliseconds); - -typedef BOOL (WINAPI* sSleepConditionVariableSRW) - (PCONDITION_VARIABLE ConditionVariable, - PSRWLOCK SRWLock, - DWORD dwMilliseconds, - ULONG Flags); - -typedef VOID (WINAPI* sWakeAllConditionVariable) - (PCONDITION_VARIABLE ConditionVariable); - -typedef VOID (WINAPI* sWakeConditionVariable) - (PCONDITION_VARIABLE ConditionVariable); - -typedef BOOL (WINAPI* sCancelSynchronousIo) - (HANDLE hThread); - -/* Ntdll function pointers */ -extern sRtlNtStatusToDosError pRtlNtStatusToDosError; -extern sNtDeviceIoControlFile pNtDeviceIoControlFile; -extern sNtQueryInformationFile pNtQueryInformationFile; -extern sNtSetInformationFile pNtSetInformationFile; -extern sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile; -extern sNtQueryDirectoryFile pNtQueryDirectoryFile; -extern sNtQuerySystemInformation pNtQuerySystemInformation; - - -/* Kernel32 function pointers */ -extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx; -extern sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes; -extern sCreateSymbolicLinkW pCreateSymbolicLinkW; -extern sCancelIoEx pCancelIoEx; -extern sInitializeSRWLock pInitializeSRWLock; -extern sAcquireSRWLockShared pAcquireSRWLockShared; -extern sAcquireSRWLockExclusive pAcquireSRWLockExclusive; -extern sTryAcquireSRWLockShared pTryAcquireSRWLockShared; -extern sTryAcquireSRWLockExclusive pTryAcquireSRWLockExclusive; -extern sReleaseSRWLockShared pReleaseSRWLockShared; -extern sReleaseSRWLockExclusive pReleaseSRWLockExclusive; -extern sInitializeConditionVariable pInitializeConditionVariable; -extern sSleepConditionVariableCS pSleepConditionVariableCS; -extern sSleepConditionVariableSRW pSleepConditionVariableSRW; -extern sWakeAllConditionVariable pWakeAllConditionVariable; -extern sWakeConditionVariable pWakeConditionVariable; -extern sCancelSynchronousIo pCancelSynchronousIo; - -#endif /* UV_WIN_WINAPI_H_ */ diff --git a/libuv/src/win/winsock.c b/libuv/src/win/winsock.c deleted file mode 100644 index d2e667e..0000000 --- a/libuv/src/win/winsock.c +++ /dev/null @@ -1,561 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include - -#include "uv.h" -#include "internal.h" - - -/* Whether there are any non-IFS LSPs stacked on TCP */ -int uv_tcp_non_ifs_lsp_ipv4; -int uv_tcp_non_ifs_lsp_ipv6; - -/* Ip address used to bind to any port at any interface */ -struct sockaddr_in uv_addr_ip4_any_; -struct sockaddr_in6 uv_addr_ip6_any_; - - -/* - * Retrieves the pointer to a winsock extension function. - */ -static BOOL uv_get_extension_function(SOCKET socket, GUID guid, - void **target) { - int result; - DWORD bytes; - - result = WSAIoctl(socket, - SIO_GET_EXTENSION_FUNCTION_POINTER, - &guid, - sizeof(guid), - (void*)target, - sizeof(*target), - &bytes, - NULL, - NULL); - - if (result == SOCKET_ERROR) { - *target = NULL; - return FALSE; - } else { - return TRUE; - } -} - - -BOOL uv_get_acceptex_function(SOCKET socket, LPFN_ACCEPTEX* target) { - const GUID wsaid_acceptex = WSAID_ACCEPTEX; - return uv_get_extension_function(socket, wsaid_acceptex, (void**)target); -} - - -BOOL uv_get_connectex_function(SOCKET socket, LPFN_CONNECTEX* target) { - const GUID wsaid_connectex = WSAID_CONNECTEX; - return uv_get_extension_function(socket, wsaid_connectex, (void**)target); -} - - -static int error_means_no_support(DWORD error) { - return error == WSAEPROTONOSUPPORT || error == WSAESOCKTNOSUPPORT || - error == WSAEPFNOSUPPORT || error == WSAEAFNOSUPPORT; -} - - -void uv_winsock_init() { - WSADATA wsa_data; - int errorno; - SOCKET dummy; - WSAPROTOCOL_INFOW protocol_info; - int opt_len; - - /* Initialize winsock */ - errorno = WSAStartup(MAKEWORD(2, 2), &wsa_data); - if (errorno != 0) { - uv_fatal_error(errorno, "WSAStartup"); - } - - /* Set implicit binding address used by connectEx */ - if (uv_ip4_addr("0.0.0.0", 0, &uv_addr_ip4_any_)) { - abort(); - } - - if (uv_ip6_addr("::", 0, &uv_addr_ip6_any_)) { - abort(); - } - - /* Detect non-IFS LSPs */ - dummy = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); - - if (dummy != INVALID_SOCKET) { - opt_len = (int) sizeof protocol_info; - if (getsockopt(dummy, - SOL_SOCKET, - SO_PROTOCOL_INFOW, - (char*) &protocol_info, - &opt_len) == SOCKET_ERROR) - uv_fatal_error(WSAGetLastError(), "getsockopt"); - - if (!(protocol_info.dwServiceFlags1 & XP1_IFS_HANDLES)) - uv_tcp_non_ifs_lsp_ipv4 = 1; - - if (closesocket(dummy) == SOCKET_ERROR) - uv_fatal_error(WSAGetLastError(), "closesocket"); - - } else if (!error_means_no_support(WSAGetLastError())) { - /* Any error other than "socket type not supported" is fatal. */ - uv_fatal_error(WSAGetLastError(), "socket"); - } - - /* Detect IPV6 support and non-IFS LSPs */ - dummy = socket(AF_INET6, SOCK_STREAM, IPPROTO_IP); - - if (dummy != INVALID_SOCKET) { - opt_len = (int) sizeof protocol_info; - if (getsockopt(dummy, - SOL_SOCKET, - SO_PROTOCOL_INFOW, - (char*) &protocol_info, - &opt_len) == SOCKET_ERROR) - uv_fatal_error(WSAGetLastError(), "getsockopt"); - - if (!(protocol_info.dwServiceFlags1 & XP1_IFS_HANDLES)) - uv_tcp_non_ifs_lsp_ipv6 = 1; - - if (closesocket(dummy) == SOCKET_ERROR) - uv_fatal_error(WSAGetLastError(), "closesocket"); - - } else if (!error_means_no_support(WSAGetLastError())) { - /* Any error other than "socket type not supported" is fatal. */ - uv_fatal_error(WSAGetLastError(), "socket"); - } -} - - -int uv_ntstatus_to_winsock_error(NTSTATUS status) { - switch (status) { - case STATUS_SUCCESS: - return ERROR_SUCCESS; - - case STATUS_PENDING: - return ERROR_IO_PENDING; - - case STATUS_INVALID_HANDLE: - case STATUS_OBJECT_TYPE_MISMATCH: - return WSAENOTSOCK; - - case STATUS_INSUFFICIENT_RESOURCES: - case STATUS_PAGEFILE_QUOTA: - case STATUS_COMMITMENT_LIMIT: - case STATUS_WORKING_SET_QUOTA: - case STATUS_NO_MEMORY: - case STATUS_QUOTA_EXCEEDED: - case STATUS_TOO_MANY_PAGING_FILES: - case STATUS_REMOTE_RESOURCES: - return WSAENOBUFS; - - case STATUS_TOO_MANY_ADDRESSES: - case STATUS_SHARING_VIOLATION: - case STATUS_ADDRESS_ALREADY_EXISTS: - return WSAEADDRINUSE; - - case STATUS_LINK_TIMEOUT: - case STATUS_IO_TIMEOUT: - case STATUS_TIMEOUT: - return WSAETIMEDOUT; - - case STATUS_GRACEFUL_DISCONNECT: - return WSAEDISCON; - - case STATUS_REMOTE_DISCONNECT: - case STATUS_CONNECTION_RESET: - case STATUS_LINK_FAILED: - case STATUS_CONNECTION_DISCONNECTED: - case STATUS_PORT_UNREACHABLE: - case STATUS_HOPLIMIT_EXCEEDED: - return WSAECONNRESET; - - case STATUS_LOCAL_DISCONNECT: - case STATUS_TRANSACTION_ABORTED: - case STATUS_CONNECTION_ABORTED: - return WSAECONNABORTED; - - case STATUS_BAD_NETWORK_PATH: - case STATUS_NETWORK_UNREACHABLE: - case STATUS_PROTOCOL_UNREACHABLE: - return WSAENETUNREACH; - - case STATUS_HOST_UNREACHABLE: - return WSAEHOSTUNREACH; - - case STATUS_CANCELLED: - case STATUS_REQUEST_ABORTED: - return WSAEINTR; - - case STATUS_BUFFER_OVERFLOW: - case STATUS_INVALID_BUFFER_SIZE: - return WSAEMSGSIZE; - - case STATUS_BUFFER_TOO_SMALL: - case STATUS_ACCESS_VIOLATION: - return WSAEFAULT; - - case STATUS_DEVICE_NOT_READY: - case STATUS_REQUEST_NOT_ACCEPTED: - return WSAEWOULDBLOCK; - - case STATUS_INVALID_NETWORK_RESPONSE: - case STATUS_NETWORK_BUSY: - case STATUS_NO_SUCH_DEVICE: - case STATUS_NO_SUCH_FILE: - case STATUS_OBJECT_PATH_NOT_FOUND: - case STATUS_OBJECT_NAME_NOT_FOUND: - case STATUS_UNEXPECTED_NETWORK_ERROR: - return WSAENETDOWN; - - case STATUS_INVALID_CONNECTION: - return WSAENOTCONN; - - case STATUS_REMOTE_NOT_LISTENING: - case STATUS_CONNECTION_REFUSED: - return WSAECONNREFUSED; - - case STATUS_PIPE_DISCONNECTED: - return WSAESHUTDOWN; - - case STATUS_CONFLICTING_ADDRESSES: - case STATUS_INVALID_ADDRESS: - case STATUS_INVALID_ADDRESS_COMPONENT: - return WSAEADDRNOTAVAIL; - - case STATUS_NOT_SUPPORTED: - case STATUS_NOT_IMPLEMENTED: - return WSAEOPNOTSUPP; - - case STATUS_ACCESS_DENIED: - return WSAEACCES; - - default: - if ((status & (FACILITY_NTWIN32 << 16)) == (FACILITY_NTWIN32 << 16) && - (status & (ERROR_SEVERITY_ERROR | ERROR_SEVERITY_WARNING))) { - /* It's a windows error that has been previously mapped to an */ - /* ntstatus code. */ - return (DWORD) (status & 0xffff); - } else { - /* The default fallback for unmappable ntstatus codes. */ - return WSAEINVAL; - } - } -} - - -/* - * This function provides a workaround for a bug in the winsock implementation - * of WSARecv. The problem is that when SetFileCompletionNotificationModes is - * used to avoid IOCP notifications of completed reads, WSARecv does not - * reliably indicate whether we can expect a completion package to be posted - * when the receive buffer is smaller than the received datagram. - * - * However it is desirable to use SetFileCompletionNotificationModes because - * it yields a massive performance increase. - * - * This function provides a workaround for that bug, but it only works for the - * specific case that we need it for. E.g. it assumes that the "avoid iocp" - * bit has been set, and supports only overlapped operation. It also requires - * the user to use the default msafd driver, doesn't work when other LSPs are - * stacked on top of it. - */ -int WSAAPI uv_wsarecv_workaround(SOCKET socket, WSABUF* buffers, - DWORD buffer_count, DWORD* bytes, DWORD* flags, WSAOVERLAPPED *overlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine) { - NTSTATUS status; - void* apc_context; - IO_STATUS_BLOCK* iosb = (IO_STATUS_BLOCK*) &overlapped->Internal; - AFD_RECV_INFO info; - DWORD error; - - if (overlapped == NULL || completion_routine != NULL) { - WSASetLastError(WSAEINVAL); - return SOCKET_ERROR; - } - - info.BufferArray = buffers; - info.BufferCount = buffer_count; - info.AfdFlags = AFD_OVERLAPPED; - info.TdiFlags = TDI_RECEIVE_NORMAL; - - if (*flags & MSG_PEEK) { - info.TdiFlags |= TDI_RECEIVE_PEEK; - } - - if (*flags & MSG_PARTIAL) { - info.TdiFlags |= TDI_RECEIVE_PARTIAL; - } - - if (!((intptr_t) overlapped->hEvent & 1)) { - apc_context = (void*) overlapped; - } else { - apc_context = NULL; - } - - iosb->Status = STATUS_PENDING; - iosb->Pointer = 0; - - status = pNtDeviceIoControlFile((HANDLE) socket, - overlapped->hEvent, - NULL, - apc_context, - iosb, - IOCTL_AFD_RECEIVE, - &info, - sizeof(info), - NULL, - 0); - - *flags = 0; - *bytes = (DWORD) iosb->Information; - - switch (status) { - case STATUS_SUCCESS: - error = ERROR_SUCCESS; - break; - - case STATUS_PENDING: - error = WSA_IO_PENDING; - break; - - case STATUS_BUFFER_OVERFLOW: - error = WSAEMSGSIZE; - break; - - case STATUS_RECEIVE_EXPEDITED: - error = ERROR_SUCCESS; - *flags = MSG_OOB; - break; - - case STATUS_RECEIVE_PARTIAL_EXPEDITED: - error = ERROR_SUCCESS; - *flags = MSG_PARTIAL | MSG_OOB; - break; - - case STATUS_RECEIVE_PARTIAL: - error = ERROR_SUCCESS; - *flags = MSG_PARTIAL; - break; - - default: - error = uv_ntstatus_to_winsock_error(status); - break; - } - - WSASetLastError(error); - - if (error == ERROR_SUCCESS) { - return 0; - } else { - return SOCKET_ERROR; - } -} - - -/* See description of uv_wsarecv_workaround. */ -int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers, - DWORD buffer_count, DWORD* bytes, DWORD* flags, struct sockaddr* addr, - int* addr_len, WSAOVERLAPPED *overlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine) { - NTSTATUS status; - void* apc_context; - IO_STATUS_BLOCK* iosb = (IO_STATUS_BLOCK*) &overlapped->Internal; - AFD_RECV_DATAGRAM_INFO info; - DWORD error; - - if (overlapped == NULL || addr == NULL || addr_len == NULL || - completion_routine != NULL) { - WSASetLastError(WSAEINVAL); - return SOCKET_ERROR; - } - - info.BufferArray = buffers; - info.BufferCount = buffer_count; - info.AfdFlags = AFD_OVERLAPPED; - info.TdiFlags = TDI_RECEIVE_NORMAL; - info.Address = addr; - info.AddressLength = addr_len; - - if (*flags & MSG_PEEK) { - info.TdiFlags |= TDI_RECEIVE_PEEK; - } - - if (*flags & MSG_PARTIAL) { - info.TdiFlags |= TDI_RECEIVE_PARTIAL; - } - - if (!((intptr_t) overlapped->hEvent & 1)) { - apc_context = (void*) overlapped; - } else { - apc_context = NULL; - } - - iosb->Status = STATUS_PENDING; - iosb->Pointer = 0; - - status = pNtDeviceIoControlFile((HANDLE) socket, - overlapped->hEvent, - NULL, - apc_context, - iosb, - IOCTL_AFD_RECEIVE_DATAGRAM, - &info, - sizeof(info), - NULL, - 0); - - *flags = 0; - *bytes = (DWORD) iosb->Information; - - switch (status) { - case STATUS_SUCCESS: - error = ERROR_SUCCESS; - break; - - case STATUS_PENDING: - error = WSA_IO_PENDING; - break; - - case STATUS_BUFFER_OVERFLOW: - error = WSAEMSGSIZE; - break; - - case STATUS_RECEIVE_EXPEDITED: - error = ERROR_SUCCESS; - *flags = MSG_OOB; - break; - - case STATUS_RECEIVE_PARTIAL_EXPEDITED: - error = ERROR_SUCCESS; - *flags = MSG_PARTIAL | MSG_OOB; - break; - - case STATUS_RECEIVE_PARTIAL: - error = ERROR_SUCCESS; - *flags = MSG_PARTIAL; - break; - - default: - error = uv_ntstatus_to_winsock_error(status); - break; - } - - WSASetLastError(error); - - if (error == ERROR_SUCCESS) { - return 0; - } else { - return SOCKET_ERROR; - } -} - - -int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in, - AFD_POLL_INFO* info_out, OVERLAPPED* overlapped) { - IO_STATUS_BLOCK iosb; - IO_STATUS_BLOCK* iosb_ptr; - HANDLE event = NULL; - void* apc_context; - NTSTATUS status; - DWORD error; - - if (overlapped != NULL) { - /* Overlapped operation. */ - iosb_ptr = (IO_STATUS_BLOCK*) &overlapped->Internal; - event = overlapped->hEvent; - - /* Do not report iocp completion if hEvent is tagged. */ - if ((uintptr_t) event & 1) { - event = (HANDLE)((uintptr_t) event & ~(uintptr_t) 1); - apc_context = NULL; - } else { - apc_context = overlapped; - } - - } else { - /* Blocking operation. */ - iosb_ptr = &iosb; - event = CreateEvent(NULL, FALSE, FALSE, NULL); - if (event == NULL) { - return SOCKET_ERROR; - } - apc_context = NULL; - } - - iosb_ptr->Status = STATUS_PENDING; - status = pNtDeviceIoControlFile((HANDLE) socket, - event, - NULL, - apc_context, - iosb_ptr, - IOCTL_AFD_POLL, - info_in, - sizeof *info_in, - info_out, - sizeof *info_out); - - if (overlapped == NULL) { - /* If this is a blocking operation, wait for the event to become */ - /* signaled, and then grab the real status from the io status block. */ - if (status == STATUS_PENDING) { - DWORD r = WaitForSingleObject(event, INFINITE); - - if (r == WAIT_FAILED) { - DWORD saved_error = GetLastError(); - CloseHandle(event); - WSASetLastError(saved_error); - return SOCKET_ERROR; - } - - status = iosb.Status; - } - - CloseHandle(event); - } - - switch (status) { - case STATUS_SUCCESS: - error = ERROR_SUCCESS; - break; - - case STATUS_PENDING: - error = WSA_IO_PENDING; - break; - - default: - error = uv_ntstatus_to_winsock_error(status); - break; - } - - WSASetLastError(error); - - if (error == ERROR_SUCCESS) { - return 0; - } else { - return SOCKET_ERROR; - } -} diff --git a/libuv/src/win/winsock.h b/libuv/src/win/winsock.h deleted file mode 100644 index 7c007ab..0000000 --- a/libuv/src/win/winsock.h +++ /dev/null @@ -1,190 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef UV_WIN_WINSOCK_H_ -#define UV_WIN_WINSOCK_H_ - -#include -#include -#include -#include -#include - -#include "winapi.h" - - -/* - * MinGW is missing these too - */ -#ifndef SO_UPDATE_CONNECT_CONTEXT -# define SO_UPDATE_CONNECT_CONTEXT 0x7010 -#endif - -#ifndef TCP_KEEPALIVE -# define TCP_KEEPALIVE 3 -#endif - -#ifndef IPV6_V6ONLY -# define IPV6_V6ONLY 27 -#endif - -#ifndef IPV6_HOPLIMIT -# define IPV6_HOPLIMIT 21 -#endif - -#ifndef SIO_BASE_HANDLE -# define SIO_BASE_HANDLE 0x48000022 -#endif - -/* - * TDI defines that are only in the DDK. - * We only need receive flags so far. - */ -#ifndef TDI_RECEIVE_NORMAL - #define TDI_RECEIVE_BROADCAST 0x00000004 - #define TDI_RECEIVE_MULTICAST 0x00000008 - #define TDI_RECEIVE_PARTIAL 0x00000010 - #define TDI_RECEIVE_NORMAL 0x00000020 - #define TDI_RECEIVE_EXPEDITED 0x00000040 - #define TDI_RECEIVE_PEEK 0x00000080 - #define TDI_RECEIVE_NO_RESPONSE_EXP 0x00000100 - #define TDI_RECEIVE_COPY_LOOKAHEAD 0x00000200 - #define TDI_RECEIVE_ENTIRE_MESSAGE 0x00000400 - #define TDI_RECEIVE_AT_DISPATCH_LEVEL 0x00000800 - #define TDI_RECEIVE_CONTROL_INFO 0x00001000 - #define TDI_RECEIVE_FORCE_INDICATION 0x00002000 - #define TDI_RECEIVE_NO_PUSH 0x00004000 -#endif - -/* - * The "Auxiliary Function Driver" is the windows kernel-mode driver that does - * TCP, UDP etc. Winsock is just a layer that dispatches requests to it. - * Having these definitions allows us to bypass winsock and make an AFD kernel - * call directly, avoiding a bug in winsock's recvfrom implementation. - */ - -#define AFD_NO_FAST_IO 0x00000001 -#define AFD_OVERLAPPED 0x00000002 -#define AFD_IMMEDIATE 0x00000004 - -#define AFD_POLL_RECEIVE_BIT 0 -#define AFD_POLL_RECEIVE (1 << AFD_POLL_RECEIVE_BIT) -#define AFD_POLL_RECEIVE_EXPEDITED_BIT 1 -#define AFD_POLL_RECEIVE_EXPEDITED (1 << AFD_POLL_RECEIVE_EXPEDITED_BIT) -#define AFD_POLL_SEND_BIT 2 -#define AFD_POLL_SEND (1 << AFD_POLL_SEND_BIT) -#define AFD_POLL_DISCONNECT_BIT 3 -#define AFD_POLL_DISCONNECT (1 << AFD_POLL_DISCONNECT_BIT) -#define AFD_POLL_ABORT_BIT 4 -#define AFD_POLL_ABORT (1 << AFD_POLL_ABORT_BIT) -#define AFD_POLL_LOCAL_CLOSE_BIT 5 -#define AFD_POLL_LOCAL_CLOSE (1 << AFD_POLL_LOCAL_CLOSE_BIT) -#define AFD_POLL_CONNECT_BIT 6 -#define AFD_POLL_CONNECT (1 << AFD_POLL_CONNECT_BIT) -#define AFD_POLL_ACCEPT_BIT 7 -#define AFD_POLL_ACCEPT (1 << AFD_POLL_ACCEPT_BIT) -#define AFD_POLL_CONNECT_FAIL_BIT 8 -#define AFD_POLL_CONNECT_FAIL (1 << AFD_POLL_CONNECT_FAIL_BIT) -#define AFD_POLL_QOS_BIT 9 -#define AFD_POLL_QOS (1 << AFD_POLL_QOS_BIT) -#define AFD_POLL_GROUP_QOS_BIT 10 -#define AFD_POLL_GROUP_QOS (1 << AFD_POLL_GROUP_QOS_BIT) - -#define AFD_NUM_POLL_EVENTS 11 -#define AFD_POLL_ALL ((1 << AFD_NUM_POLL_EVENTS) - 1) - -typedef struct _AFD_RECV_DATAGRAM_INFO { - LPWSABUF BufferArray; - ULONG BufferCount; - ULONG AfdFlags; - ULONG TdiFlags; - struct sockaddr* Address; - int* AddressLength; -} AFD_RECV_DATAGRAM_INFO, *PAFD_RECV_DATAGRAM_INFO; - -typedef struct _AFD_RECV_INFO { - LPWSABUF BufferArray; - ULONG BufferCount; - ULONG AfdFlags; - ULONG TdiFlags; -} AFD_RECV_INFO, *PAFD_RECV_INFO; - - -#define _AFD_CONTROL_CODE(operation, method) \ - ((FSCTL_AFD_BASE) << 12 | (operation << 2) | method) - -#define FSCTL_AFD_BASE FILE_DEVICE_NETWORK - -#define AFD_RECEIVE 5 -#define AFD_RECEIVE_DATAGRAM 6 -#define AFD_POLL 9 - -#define IOCTL_AFD_RECEIVE \ - _AFD_CONTROL_CODE(AFD_RECEIVE, METHOD_NEITHER) - -#define IOCTL_AFD_RECEIVE_DATAGRAM \ - _AFD_CONTROL_CODE(AFD_RECEIVE_DATAGRAM, METHOD_NEITHER) - -#define IOCTL_AFD_POLL \ - _AFD_CONTROL_CODE(AFD_POLL, METHOD_BUFFERED) - -#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) -typedef struct _IP_ADAPTER_UNICAST_ADDRESS_XP { - /* FIXME: __C89_NAMELESS was removed */ - /* __C89_NAMELESS */ union { - ULONGLONG Alignment; - /* __C89_NAMELESS */ struct { - ULONG Length; - DWORD Flags; - }; - }; - struct _IP_ADAPTER_UNICAST_ADDRESS_XP *Next; - SOCKET_ADDRESS Address; - IP_PREFIX_ORIGIN PrefixOrigin; - IP_SUFFIX_ORIGIN SuffixOrigin; - IP_DAD_STATE DadState; - ULONG ValidLifetime; - ULONG PreferredLifetime; - ULONG LeaseLifetime; -} IP_ADAPTER_UNICAST_ADDRESS_XP,*PIP_ADAPTER_UNICAST_ADDRESS_XP; - -typedef struct _IP_ADAPTER_UNICAST_ADDRESS_LH { - union { - ULONGLONG Alignment; - struct { - ULONG Length; - DWORD Flags; - }; - }; - struct _IP_ADAPTER_UNICAST_ADDRESS_LH *Next; - SOCKET_ADDRESS Address; - IP_PREFIX_ORIGIN PrefixOrigin; - IP_SUFFIX_ORIGIN SuffixOrigin; - IP_DAD_STATE DadState; - ULONG ValidLifetime; - ULONG PreferredLifetime; - ULONG LeaseLifetime; - UINT8 OnLinkPrefixLength; -} IP_ADAPTER_UNICAST_ADDRESS_LH,*PIP_ADAPTER_UNICAST_ADDRESS_LH; - -#endif - -#endif /* UV_WIN_WINSOCK_H_ */ diff --git a/libuv/test/benchmark-async-pummel.c b/libuv/test/benchmark-async-pummel.c deleted file mode 100644 index cca3de1..0000000 --- a/libuv/test/benchmark-async-pummel.c +++ /dev/null @@ -1,119 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "task.h" -#include "uv.h" - -#include -#include - -#define NUM_PINGS (1000 * 1000) -#define ACCESS_ONCE(type, var) (*(volatile type*) &(var)) - -static unsigned int callbacks; -static volatile int done; - -static const char running[] = "running"; -static const char stop[] = "stop"; -static const char stopped[] = "stopped"; - - -static void async_cb(uv_async_t* handle) { - if (++callbacks == NUM_PINGS) { - /* Tell the pummel thread to stop. */ - ACCESS_ONCE(const char*, handle->data) = stop; - - /* Wait for for the pummel thread to acknowledge that it has stoppped. */ - while (ACCESS_ONCE(const char*, handle->data) != stopped) - uv_sleep(0); - - uv_close((uv_handle_t*) handle, NULL); - } -} - - -static void pummel(void* arg) { - uv_async_t* handle = (uv_async_t*) arg; - - while (ACCESS_ONCE(const char*, handle->data) == running) - uv_async_send(handle); - - /* Acknowledge that we've seen handle->data change. */ - ACCESS_ONCE(const char*, handle->data) = stopped; -} - - -static int test_async_pummel(int nthreads) { - uv_thread_t* tids; - uv_async_t handle; - uint64_t time; - int i; - - tids = calloc(nthreads, sizeof(tids[0])); - ASSERT(tids != NULL); - - ASSERT(0 == uv_async_init(uv_default_loop(), &handle, async_cb)); - ACCESS_ONCE(const char*, handle.data) = running; - - for (i = 0; i < nthreads; i++) - ASSERT(0 == uv_thread_create(tids + i, pummel, &handle)); - - time = uv_hrtime(); - - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); - - time = uv_hrtime() - time; - done = 1; - - for (i = 0; i < nthreads; i++) - ASSERT(0 == uv_thread_join(tids + i)); - - printf("async_pummel_%d: %s callbacks in %.2f seconds (%s/sec)\n", - nthreads, - fmt(callbacks), - time / 1e9, - fmt(callbacks / (time / 1e9))); - - free(tids); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -BENCHMARK_IMPL(async_pummel_1) { - return test_async_pummel(1); -} - - -BENCHMARK_IMPL(async_pummel_2) { - return test_async_pummel(2); -} - - -BENCHMARK_IMPL(async_pummel_4) { - return test_async_pummel(4); -} - - -BENCHMARK_IMPL(async_pummel_8) { - return test_async_pummel(8); -} diff --git a/libuv/test/benchmark-async.c b/libuv/test/benchmark-async.c deleted file mode 100644 index e44165f..0000000 --- a/libuv/test/benchmark-async.c +++ /dev/null @@ -1,141 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "task.h" -#include "uv.h" - -#include -#include - -#define NUM_PINGS (1000 * 1000) - -struct ctx { - uv_loop_t loop; - uv_thread_t thread; - uv_async_t main_async; /* wake up main thread */ - uv_async_t worker_async; /* wake up worker */ - unsigned int nthreads; - unsigned int main_sent; - unsigned int main_seen; - unsigned int worker_sent; - unsigned int worker_seen; -}; - - -static void worker_async_cb(uv_async_t* handle) { - struct ctx* ctx = container_of(handle, struct ctx, worker_async); - - ASSERT(0 == uv_async_send(&ctx->main_async)); - ctx->worker_sent++; - ctx->worker_seen++; - - if (ctx->worker_sent >= NUM_PINGS) - uv_close((uv_handle_t*) &ctx->worker_async, NULL); -} - - -static void main_async_cb(uv_async_t* handle) { - struct ctx* ctx = container_of(handle, struct ctx, main_async); - - ASSERT(0 == uv_async_send(&ctx->worker_async)); - ctx->main_sent++; - ctx->main_seen++; - - if (ctx->main_sent >= NUM_PINGS) - uv_close((uv_handle_t*) &ctx->main_async, NULL); -} - - -static void worker(void* arg) { - struct ctx* ctx = arg; - ASSERT(0 == uv_async_send(&ctx->main_async)); - ASSERT(0 == uv_run(&ctx->loop, UV_RUN_DEFAULT)); - uv_loop_close(&ctx->loop); -} - - -static int test_async(int nthreads) { - struct ctx* threads; - struct ctx* ctx; - uint64_t time; - int i; - - threads = calloc(nthreads, sizeof(threads[0])); - ASSERT(threads != NULL); - - for (i = 0; i < nthreads; i++) { - ctx = threads + i; - ctx->nthreads = nthreads; - ASSERT(0 == uv_loop_init(&ctx->loop)); - ASSERT(0 == uv_async_init(&ctx->loop, &ctx->worker_async, worker_async_cb)); - ASSERT(0 == uv_async_init(uv_default_loop(), - &ctx->main_async, - main_async_cb)); - ASSERT(0 == uv_thread_create(&ctx->thread, worker, ctx)); - } - - time = uv_hrtime(); - - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); - - for (i = 0; i < nthreads; i++) - ASSERT(0 == uv_thread_join(&threads[i].thread)); - - time = uv_hrtime() - time; - - for (i = 0; i < nthreads; i++) { - ctx = threads + i; - ASSERT(ctx->worker_sent == NUM_PINGS); - ASSERT(ctx->worker_seen == NUM_PINGS); - ASSERT(ctx->main_sent == (unsigned int) NUM_PINGS); - ASSERT(ctx->main_seen == (unsigned int) NUM_PINGS); - } - - printf("async%d: %.2f sec (%s/sec)\n", - nthreads, - time / 1e9, - fmt(NUM_PINGS / (time / 1e9))); - - free(threads); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -BENCHMARK_IMPL(async1) { - return test_async(1); -} - - -BENCHMARK_IMPL(async2) { - return test_async(2); -} - - -BENCHMARK_IMPL(async4) { - return test_async(4); -} - - -BENCHMARK_IMPL(async8) { - return test_async(8); -} diff --git a/libuv/test/benchmark-fs-stat.c b/libuv/test/benchmark-fs-stat.c deleted file mode 100644 index 5c87de0..0000000 --- a/libuv/test/benchmark-fs-stat.c +++ /dev/null @@ -1,136 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "task.h" -#include "uv.h" - -#include -#include - -#define NUM_SYNC_REQS (10 * 1e5) -#define NUM_ASYNC_REQS (1 * (int) 1e5) -#define MAX_CONCURRENT_REQS 32 - -#define sync_stat(req, path) \ - do { \ - uv_fs_stat(uv_default_loop(), (req), (path), NULL); \ - uv_fs_req_cleanup((req)); \ - } \ - while (0) - -struct async_req { - const char* path; - uv_fs_t fs_req; - int* count; -}; - - -static void warmup(const char* path) { - uv_fs_t reqs[MAX_CONCURRENT_REQS]; - unsigned int i; - - /* warm up the thread pool */ - for (i = 0; i < ARRAY_SIZE(reqs); i++) - uv_fs_stat(uv_default_loop(), reqs + i, path, uv_fs_req_cleanup); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - /* warm up the OS dirent cache */ - for (i = 0; i < 16; i++) - sync_stat(reqs + 0, path); -} - - -static void sync_bench(const char* path) { - uint64_t before; - uint64_t after; - uv_fs_t req; - int i; - - /* do the sync benchmark */ - before = uv_hrtime(); - - for (i = 0; i < NUM_SYNC_REQS; i++) - sync_stat(&req, path); - - after = uv_hrtime(); - - printf("%s stats (sync): %.2fs (%s/s)\n", - fmt(1.0 * NUM_SYNC_REQS), - (after - before) / 1e9, - fmt((1.0 * NUM_SYNC_REQS) / ((after - before) / 1e9))); - fflush(stdout); -} - - -static void stat_cb(uv_fs_t* fs_req) { - struct async_req* req = container_of(fs_req, struct async_req, fs_req); - uv_fs_req_cleanup(&req->fs_req); - if (*req->count == 0) return; - uv_fs_stat(uv_default_loop(), &req->fs_req, req->path, stat_cb); - (*req->count)--; -} - - -static void async_bench(const char* path) { - struct async_req reqs[MAX_CONCURRENT_REQS]; - struct async_req* req; - uint64_t before; - uint64_t after; - int count; - int i; - - for (i = 1; i <= MAX_CONCURRENT_REQS; i++) { - count = NUM_ASYNC_REQS; - - for (req = reqs; req < reqs + i; req++) { - req->path = path; - req->count = &count; - uv_fs_stat(uv_default_loop(), &req->fs_req, req->path, stat_cb); - } - - before = uv_hrtime(); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - after = uv_hrtime(); - - printf("%s stats (%d concurrent): %.2fs (%s/s)\n", - fmt(1.0 * NUM_ASYNC_REQS), - i, - (after - before) / 1e9, - fmt((1.0 * NUM_ASYNC_REQS) / ((after - before) / 1e9))); - fflush(stdout); - } -} - - -/* This benchmark aims to measure the overhead of doing I/O syscalls from - * the thread pool. The stat() syscall was chosen because its results are - * easy for the operating system to cache, taking the actual I/O overhead - * out of the equation. - */ -BENCHMARK_IMPL(fs_stat) { - const char path[] = "."; - warmup(path); - sync_bench(path); - async_bench(path); - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/benchmark-getaddrinfo.c b/libuv/test/benchmark-getaddrinfo.c deleted file mode 100644 index c7f99a2..0000000 --- a/libuv/test/benchmark-getaddrinfo.c +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" -#include - -#define CONCURRENT_CALLS 10 -#define TOTAL_CALLS 10000 - -static const char* name = "localhost"; - -static uv_loop_t* loop; - -static uv_getaddrinfo_t handles[CONCURRENT_CALLS]; - -static int calls_initiated = 0; -static int calls_completed = 0; -static int64_t start_time; -static int64_t end_time; - - -static void getaddrinfo_initiate(uv_getaddrinfo_t* handle); - - -static void getaddrinfo_cb(uv_getaddrinfo_t* handle, int status, - struct addrinfo* res) { - ASSERT(status == 0); - calls_completed++; - if (calls_initiated < TOTAL_CALLS) { - getaddrinfo_initiate(handle); - } - - uv_freeaddrinfo(res); -} - - -static void getaddrinfo_initiate(uv_getaddrinfo_t* handle) { - int r; - - calls_initiated++; - - r = uv_getaddrinfo(loop, handle, &getaddrinfo_cb, name, NULL, NULL); - ASSERT(r == 0); -} - - -BENCHMARK_IMPL(getaddrinfo) { - int i; - - loop = uv_default_loop(); - - uv_update_time(loop); - start_time = uv_now(loop); - - for (i = 0; i < CONCURRENT_CALLS; i++) { - getaddrinfo_initiate(&handles[i]); - } - - uv_run(loop, UV_RUN_DEFAULT); - - uv_update_time(loop); - end_time = uv_now(loop); - - ASSERT(calls_initiated == TOTAL_CALLS); - ASSERT(calls_completed == TOTAL_CALLS); - - LOGF("getaddrinfo: %.0f req/s\n", - (double) calls_completed / (double) (end_time - start_time) * 1000.0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/benchmark-list.h b/libuv/test/benchmark-list.h deleted file mode 100644 index 1e84307..0000000 --- a/libuv/test/benchmark-list.h +++ /dev/null @@ -1,163 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -BENCHMARK_DECLARE (sizes) -BENCHMARK_DECLARE (loop_count) -BENCHMARK_DECLARE (loop_count_timed) -BENCHMARK_DECLARE (ping_pongs) -BENCHMARK_DECLARE (tcp_write_batch) -BENCHMARK_DECLARE (tcp4_pound_100) -BENCHMARK_DECLARE (tcp4_pound_1000) -BENCHMARK_DECLARE (pipe_pound_100) -BENCHMARK_DECLARE (pipe_pound_1000) -BENCHMARK_DECLARE (tcp_pump100_client) -BENCHMARK_DECLARE (tcp_pump1_client) -BENCHMARK_DECLARE (pipe_pump100_client) -BENCHMARK_DECLARE (pipe_pump1_client) - -BENCHMARK_DECLARE (tcp_multi_accept2) -BENCHMARK_DECLARE (tcp_multi_accept4) -BENCHMARK_DECLARE (tcp_multi_accept8) - -/* Run until X packets have been sent/received. */ -BENCHMARK_DECLARE (udp_pummel_1v1) -BENCHMARK_DECLARE (udp_pummel_1v10) -BENCHMARK_DECLARE (udp_pummel_1v100) -BENCHMARK_DECLARE (udp_pummel_1v1000) -BENCHMARK_DECLARE (udp_pummel_10v10) -BENCHMARK_DECLARE (udp_pummel_10v100) -BENCHMARK_DECLARE (udp_pummel_10v1000) -BENCHMARK_DECLARE (udp_pummel_100v100) -BENCHMARK_DECLARE (udp_pummel_100v1000) -BENCHMARK_DECLARE (udp_pummel_1000v1000) - -/* Run until X seconds have elapsed. */ -BENCHMARK_DECLARE (udp_timed_pummel_1v1) -BENCHMARK_DECLARE (udp_timed_pummel_1v10) -BENCHMARK_DECLARE (udp_timed_pummel_1v100) -BENCHMARK_DECLARE (udp_timed_pummel_1v1000) -BENCHMARK_DECLARE (udp_timed_pummel_10v10) -BENCHMARK_DECLARE (udp_timed_pummel_10v100) -BENCHMARK_DECLARE (udp_timed_pummel_10v1000) -BENCHMARK_DECLARE (udp_timed_pummel_100v100) -BENCHMARK_DECLARE (udp_timed_pummel_100v1000) -BENCHMARK_DECLARE (udp_timed_pummel_1000v1000) - -BENCHMARK_DECLARE (getaddrinfo) -BENCHMARK_DECLARE (fs_stat) -BENCHMARK_DECLARE (async1) -BENCHMARK_DECLARE (async2) -BENCHMARK_DECLARE (async4) -BENCHMARK_DECLARE (async8) -BENCHMARK_DECLARE (async_pummel_1) -BENCHMARK_DECLARE (async_pummel_2) -BENCHMARK_DECLARE (async_pummel_4) -BENCHMARK_DECLARE (async_pummel_8) -BENCHMARK_DECLARE (spawn) -BENCHMARK_DECLARE (thread_create) -BENCHMARK_DECLARE (million_async) -BENCHMARK_DECLARE (million_timers) -HELPER_DECLARE (tcp4_blackhole_server) -HELPER_DECLARE (tcp_pump_server) -HELPER_DECLARE (pipe_pump_server) -HELPER_DECLARE (tcp4_echo_server) -HELPER_DECLARE (pipe_echo_server) -HELPER_DECLARE (dns_server) - -TASK_LIST_START - BENCHMARK_ENTRY (sizes) - BENCHMARK_ENTRY (loop_count) - BENCHMARK_ENTRY (loop_count_timed) - - BENCHMARK_ENTRY (ping_pongs) - BENCHMARK_HELPER (ping_pongs, tcp4_echo_server) - - BENCHMARK_ENTRY (tcp_write_batch) - BENCHMARK_HELPER (tcp_write_batch, tcp4_blackhole_server) - - BENCHMARK_ENTRY (tcp_pump100_client) - BENCHMARK_HELPER (tcp_pump100_client, tcp_pump_server) - - BENCHMARK_ENTRY (tcp_pump1_client) - BENCHMARK_HELPER (tcp_pump1_client, tcp_pump_server) - - BENCHMARK_ENTRY (tcp4_pound_100) - BENCHMARK_HELPER (tcp4_pound_100, tcp4_echo_server) - - BENCHMARK_ENTRY (tcp4_pound_1000) - BENCHMARK_HELPER (tcp4_pound_1000, tcp4_echo_server) - - BENCHMARK_ENTRY (pipe_pump100_client) - BENCHMARK_HELPER (pipe_pump100_client, pipe_pump_server) - - BENCHMARK_ENTRY (pipe_pump1_client) - BENCHMARK_HELPER (pipe_pump1_client, pipe_pump_server) - - BENCHMARK_ENTRY (pipe_pound_100) - BENCHMARK_HELPER (pipe_pound_100, pipe_echo_server) - - BENCHMARK_ENTRY (pipe_pound_1000) - BENCHMARK_HELPER (pipe_pound_1000, pipe_echo_server) - - BENCHMARK_ENTRY (tcp_multi_accept2) - BENCHMARK_ENTRY (tcp_multi_accept4) - BENCHMARK_ENTRY (tcp_multi_accept8) - - BENCHMARK_ENTRY (udp_pummel_1v1) - BENCHMARK_ENTRY (udp_pummel_1v10) - BENCHMARK_ENTRY (udp_pummel_1v100) - BENCHMARK_ENTRY (udp_pummel_1v1000) - BENCHMARK_ENTRY (udp_pummel_10v10) - BENCHMARK_ENTRY (udp_pummel_10v100) - BENCHMARK_ENTRY (udp_pummel_10v1000) - BENCHMARK_ENTRY (udp_pummel_100v100) - BENCHMARK_ENTRY (udp_pummel_100v1000) - BENCHMARK_ENTRY (udp_pummel_1000v1000) - - BENCHMARK_ENTRY (udp_timed_pummel_1v1) - BENCHMARK_ENTRY (udp_timed_pummel_1v10) - BENCHMARK_ENTRY (udp_timed_pummel_1v100) - BENCHMARK_ENTRY (udp_timed_pummel_1v1000) - BENCHMARK_ENTRY (udp_timed_pummel_10v10) - BENCHMARK_ENTRY (udp_timed_pummel_10v100) - BENCHMARK_ENTRY (udp_timed_pummel_10v1000) - BENCHMARK_ENTRY (udp_timed_pummel_100v100) - BENCHMARK_ENTRY (udp_timed_pummel_100v1000) - BENCHMARK_ENTRY (udp_timed_pummel_1000v1000) - - BENCHMARK_ENTRY (getaddrinfo) - - BENCHMARK_ENTRY (fs_stat) - - BENCHMARK_ENTRY (async1) - BENCHMARK_ENTRY (async2) - BENCHMARK_ENTRY (async4) - BENCHMARK_ENTRY (async8) - BENCHMARK_ENTRY (async_pummel_1) - BENCHMARK_ENTRY (async_pummel_2) - BENCHMARK_ENTRY (async_pummel_4) - BENCHMARK_ENTRY (async_pummel_8) - - BENCHMARK_ENTRY (spawn) - BENCHMARK_ENTRY (thread_create) - BENCHMARK_ENTRY (million_async) - BENCHMARK_ENTRY (million_timers) -TASK_LIST_END diff --git a/libuv/test/benchmark-loop-count.c b/libuv/test/benchmark-loop-count.c deleted file mode 100644 index 5cb8132..0000000 --- a/libuv/test/benchmark-loop-count.c +++ /dev/null @@ -1,90 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "task.h" -#include "uv.h" - -#include -#include - -#define NUM_TICKS (2 * 1000 * 1000) - -static unsigned long ticks; -static uv_idle_t idle_handle; -static uv_timer_t timer_handle; - - -static void idle_cb(uv_idle_t* handle) { - if (++ticks == NUM_TICKS) - uv_idle_stop(handle); -} - - -static void idle2_cb(uv_idle_t* handle) { - ticks++; -} - - -static void timer_cb(uv_timer_t* handle) { - uv_idle_stop(&idle_handle); - uv_timer_stop(&timer_handle); -} - - -BENCHMARK_IMPL(loop_count) { - uv_loop_t* loop = uv_default_loop(); - uint64_t ns; - - uv_idle_init(loop, &idle_handle); - uv_idle_start(&idle_handle, idle_cb); - - ns = uv_hrtime(); - uv_run(loop, UV_RUN_DEFAULT); - ns = uv_hrtime() - ns; - - ASSERT(ticks == NUM_TICKS); - - LOGF("loop_count: %d ticks in %.2fs (%.0f/s)\n", - NUM_TICKS, - ns / 1e9, - NUM_TICKS / (ns / 1e9)); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -BENCHMARK_IMPL(loop_count_timed) { - uv_loop_t* loop = uv_default_loop(); - - uv_idle_init(loop, &idle_handle); - uv_idle_start(&idle_handle, idle2_cb); - - uv_timer_init(loop, &timer_handle); - uv_timer_start(&timer_handle, timer_cb, 5000, 0); - - uv_run(loop, UV_RUN_DEFAULT); - - LOGF("loop_count: %lu ticks (%.0f ticks/s)\n", ticks, ticks / 5.0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/benchmark-million-async.c b/libuv/test/benchmark-million-async.c deleted file mode 100644 index 5395ed5..0000000 --- a/libuv/test/benchmark-million-async.c +++ /dev/null @@ -1,112 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "task.h" -#include "uv.h" - -struct async_container { - unsigned async_events; - unsigned handles_seen; - uv_async_t async_handles[1024 * 1024]; -}; - -static volatile int done; -static uv_thread_t thread_id; -static struct async_container* container; - - -static unsigned fastrand(void) { - static unsigned g = 0; - g = g * 214013 + 2531011; - return g; -} - - -static void thread_cb(void* arg) { - unsigned i; - - while (done == 0) { - i = fastrand() % ARRAY_SIZE(container->async_handles); - uv_async_send(container->async_handles + i); - } -} - - -static void async_cb(uv_async_t* handle) { - container->async_events++; - handle->data = handle; -} - - -static void timer_cb(uv_timer_t* handle) { - unsigned i; - - done = 1; - ASSERT(0 == uv_thread_join(&thread_id)); - - for (i = 0; i < ARRAY_SIZE(container->async_handles); i++) { - uv_async_t* handle = container->async_handles + i; - - if (handle->data != NULL) - container->handles_seen++; - - uv_close((uv_handle_t*) handle, NULL); - } - - uv_close((uv_handle_t*) handle, NULL); -} - - -BENCHMARK_IMPL(million_async) { - uv_timer_t timer_handle; - uv_async_t* handle; - uv_loop_t* loop; - int timeout; - unsigned i; - - loop = uv_default_loop(); - timeout = 5000; - - container = malloc(sizeof(*container)); - ASSERT(container != NULL); - container->async_events = 0; - container->handles_seen = 0; - - for (i = 0; i < ARRAY_SIZE(container->async_handles); i++) { - handle = container->async_handles + i; - ASSERT(0 == uv_async_init(loop, handle, async_cb)); - handle->data = NULL; - } - - ASSERT(0 == uv_timer_init(loop, &timer_handle)); - ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, timeout, 0)); - ASSERT(0 == uv_thread_create(&thread_id, thread_cb, NULL)); - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - printf("%s async events in %.1f seconds (%s/s, %s unique handles seen)\n", - fmt(container->async_events), - timeout / 1000., - fmt(container->async_events / (timeout / 1000.)), - fmt(container->handles_seen)); - free(container); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/benchmark-million-timers.c b/libuv/test/benchmark-million-timers.c deleted file mode 100644 index 6027d60..0000000 --- a/libuv/test/benchmark-million-timers.c +++ /dev/null @@ -1,85 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "task.h" -#include "uv.h" - -#define NUM_TIMERS (10 * 1000 * 1000) - -static int timer_cb_called; -static int close_cb_called; - - -static void timer_cb(uv_timer_t* handle) { - timer_cb_called++; -} - - -static void close_cb(uv_handle_t* handle) { - close_cb_called++; -} - - -BENCHMARK_IMPL(million_timers) { - uv_timer_t* timers; - uv_loop_t* loop; - uint64_t before_all; - uint64_t before_run; - uint64_t after_run; - uint64_t after_all; - int timeout; - int i; - - timers = malloc(NUM_TIMERS * sizeof(timers[0])); - ASSERT(timers != NULL); - - loop = uv_default_loop(); - timeout = 0; - - before_all = uv_hrtime(); - for (i = 0; i < NUM_TIMERS; i++) { - if (i % 1000 == 0) timeout++; - ASSERT(0 == uv_timer_init(loop, timers + i)); - ASSERT(0 == uv_timer_start(timers + i, timer_cb, timeout, 0)); - } - - before_run = uv_hrtime(); - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - after_run = uv_hrtime(); - - for (i = 0; i < NUM_TIMERS; i++) - uv_close((uv_handle_t*) (timers + i), close_cb); - - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - after_all = uv_hrtime(); - - ASSERT(timer_cb_called == NUM_TIMERS); - ASSERT(close_cb_called == NUM_TIMERS); - free(timers); - - LOGF("%.2f seconds total\n", (after_all - before_all) / 1e9); - LOGF("%.2f seconds init\n", (before_run - before_all) / 1e9); - LOGF("%.2f seconds dispatch\n", (after_run - before_run) / 1e9); - LOGF("%.2f seconds cleanup\n", (after_all - after_run) / 1e9); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/benchmark-multi-accept.c b/libuv/test/benchmark-multi-accept.c deleted file mode 100644 index 2f32c0c..0000000 --- a/libuv/test/benchmark-multi-accept.c +++ /dev/null @@ -1,447 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "task.h" -#include "uv.h" - -#define IPC_PIPE_NAME TEST_PIPENAME -#define NUM_CONNECTS (250 * 1000) - -union stream_handle { - uv_pipe_t pipe; - uv_tcp_t tcp; -}; - -/* Use as (uv_stream_t *) &handle_storage -- it's kind of clunky but it - * avoids aliasing warnings. - */ -typedef unsigned char handle_storage_t[sizeof(union stream_handle)]; - -/* Used for passing around the listen handle, not part of the benchmark proper. - * We have an overabundance of server types here. It works like this: - * - * 1. The main thread starts an IPC pipe server. - * 2. The worker threads connect to the IPC server and obtain a listen handle. - * 3. The worker threads start accepting requests on the listen handle. - * 4. The main thread starts connecting repeatedly. - * - * Step #4 should perhaps be farmed out over several threads. - */ -struct ipc_server_ctx { - handle_storage_t server_handle; - unsigned int num_connects; - uv_pipe_t ipc_pipe; -}; - -struct ipc_peer_ctx { - handle_storage_t peer_handle; - uv_write_t write_req; -}; - -struct ipc_client_ctx { - uv_connect_t connect_req; - uv_stream_t* server_handle; - uv_pipe_t ipc_pipe; - char scratch[16]; -}; - -/* Used in the actual benchmark. */ -struct server_ctx { - handle_storage_t server_handle; - unsigned int num_connects; - uv_async_t async_handle; - uv_thread_t thread_id; - uv_sem_t semaphore; -}; - -struct client_ctx { - handle_storage_t client_handle; - unsigned int num_connects; - uv_connect_t connect_req; - uv_idle_t idle_handle; -}; - -static void ipc_connection_cb(uv_stream_t* ipc_pipe, int status); -static void ipc_write_cb(uv_write_t* req, int status); -static void ipc_close_cb(uv_handle_t* handle); -static void ipc_connect_cb(uv_connect_t* req, int status); -static void ipc_read_cb(uv_stream_t* handle, - ssize_t nread, - const uv_buf_t* buf); -static void ipc_alloc_cb(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf); - -static void sv_async_cb(uv_async_t* handle); -static void sv_connection_cb(uv_stream_t* server_handle, int status); -static void sv_read_cb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf); -static void sv_alloc_cb(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf); - -static void cl_connect_cb(uv_connect_t* req, int status); -static void cl_idle_cb(uv_idle_t* handle); -static void cl_close_cb(uv_handle_t* handle); - -static struct sockaddr_in listen_addr; - - -static void ipc_connection_cb(uv_stream_t* ipc_pipe, int status) { - struct ipc_server_ctx* sc; - struct ipc_peer_ctx* pc; - uv_loop_t* loop; - uv_buf_t buf; - - loop = ipc_pipe->loop; - buf = uv_buf_init("PING", 4); - sc = container_of(ipc_pipe, struct ipc_server_ctx, ipc_pipe); - pc = calloc(1, sizeof(*pc)); - ASSERT(pc != NULL); - - if (ipc_pipe->type == UV_TCP) - ASSERT(0 == uv_tcp_init(loop, (uv_tcp_t*) &pc->peer_handle)); - else if (ipc_pipe->type == UV_NAMED_PIPE) - ASSERT(0 == uv_pipe_init(loop, (uv_pipe_t*) &pc->peer_handle, 1)); - else - ASSERT(0); - - ASSERT(0 == uv_accept(ipc_pipe, (uv_stream_t*) &pc->peer_handle)); - ASSERT(0 == uv_write2(&pc->write_req, - (uv_stream_t*) &pc->peer_handle, - &buf, - 1, - (uv_stream_t*) &sc->server_handle, - ipc_write_cb)); - - if (--sc->num_connects == 0) - uv_close((uv_handle_t*) ipc_pipe, NULL); -} - - -static void ipc_write_cb(uv_write_t* req, int status) { - struct ipc_peer_ctx* ctx; - ctx = container_of(req, struct ipc_peer_ctx, write_req); - uv_close((uv_handle_t*) &ctx->peer_handle, ipc_close_cb); -} - - -static void ipc_close_cb(uv_handle_t* handle) { - struct ipc_peer_ctx* ctx; - ctx = container_of(handle, struct ipc_peer_ctx, peer_handle); - free(ctx); -} - - -static void ipc_connect_cb(uv_connect_t* req, int status) { - struct ipc_client_ctx* ctx; - ctx = container_of(req, struct ipc_client_ctx, connect_req); - ASSERT(0 == status); - ASSERT(0 == uv_read_start((uv_stream_t*) &ctx->ipc_pipe, - ipc_alloc_cb, - ipc_read_cb)); -} - - -static void ipc_alloc_cb(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf) { - struct ipc_client_ctx* ctx; - ctx = container_of(handle, struct ipc_client_ctx, ipc_pipe); - buf->base = ctx->scratch; - buf->len = sizeof(ctx->scratch); -} - - -static void ipc_read_cb(uv_stream_t* handle, - ssize_t nread, - const uv_buf_t* buf) { - struct ipc_client_ctx* ctx; - uv_loop_t* loop; - uv_handle_type type; - uv_pipe_t* ipc_pipe; - - ipc_pipe = (uv_pipe_t*) handle; - ctx = container_of(ipc_pipe, struct ipc_client_ctx, ipc_pipe); - loop = ipc_pipe->loop; - - ASSERT(1 == uv_pipe_pending_count(ipc_pipe)); - type = uv_pipe_pending_type(ipc_pipe); - if (type == UV_TCP) - ASSERT(0 == uv_tcp_init(loop, (uv_tcp_t*) ctx->server_handle)); - else if (type == UV_NAMED_PIPE) - ASSERT(0 == uv_pipe_init(loop, (uv_pipe_t*) ctx->server_handle, 0)); - else - ASSERT(0); - - ASSERT(0 == uv_accept(handle, ctx->server_handle)); - uv_close((uv_handle_t*) &ctx->ipc_pipe, NULL); -} - - -/* Set up an IPC pipe server that hands out listen sockets to the worker - * threads. It's kind of cumbersome for such a simple operation, maybe we - * should revive uv_import() and uv_export(). - */ -static void send_listen_handles(uv_handle_type type, - unsigned int num_servers, - struct server_ctx* servers) { - struct ipc_server_ctx ctx; - uv_loop_t* loop; - unsigned int i; - - loop = uv_default_loop(); - ctx.num_connects = num_servers; - - if (type == UV_TCP) { - ASSERT(0 == uv_tcp_init(loop, (uv_tcp_t*) &ctx.server_handle)); - ASSERT(0 == uv_tcp_bind((uv_tcp_t*) &ctx.server_handle, - (const struct sockaddr*) &listen_addr, - 0)); - } - else - ASSERT(0); - - ASSERT(0 == uv_pipe_init(loop, &ctx.ipc_pipe, 1)); - ASSERT(0 == uv_pipe_bind(&ctx.ipc_pipe, IPC_PIPE_NAME)); - ASSERT(0 == uv_listen((uv_stream_t*) &ctx.ipc_pipe, 128, ipc_connection_cb)); - - for (i = 0; i < num_servers; i++) - uv_sem_post(&servers[i].semaphore); - - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - uv_close((uv_handle_t*) &ctx.server_handle, NULL); - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - - for (i = 0; i < num_servers; i++) - uv_sem_wait(&servers[i].semaphore); -} - - -static void get_listen_handle(uv_loop_t* loop, uv_stream_t* server_handle) { - struct ipc_client_ctx ctx; - - ctx.server_handle = server_handle; - ctx.server_handle->data = "server handle"; - - ASSERT(0 == uv_pipe_init(loop, &ctx.ipc_pipe, 1)); - uv_pipe_connect(&ctx.connect_req, - &ctx.ipc_pipe, - IPC_PIPE_NAME, - ipc_connect_cb); - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); -} - - -static void server_cb(void *arg) { - struct server_ctx *ctx; - uv_loop_t loop; - - ctx = arg; - ASSERT(0 == uv_loop_init(&loop)); - - ASSERT(0 == uv_async_init(&loop, &ctx->async_handle, sv_async_cb)); - uv_unref((uv_handle_t*) &ctx->async_handle); - - /* Wait until the main thread is ready. */ - uv_sem_wait(&ctx->semaphore); - get_listen_handle(&loop, (uv_stream_t*) &ctx->server_handle); - uv_sem_post(&ctx->semaphore); - - /* Now start the actual benchmark. */ - ASSERT(0 == uv_listen((uv_stream_t*) &ctx->server_handle, - 128, - sv_connection_cb)); - ASSERT(0 == uv_run(&loop, UV_RUN_DEFAULT)); - - uv_loop_close(&loop); -} - - -static void sv_async_cb(uv_async_t* handle) { - struct server_ctx* ctx; - ctx = container_of(handle, struct server_ctx, async_handle); - uv_close((uv_handle_t*) &ctx->server_handle, NULL); - uv_close((uv_handle_t*) &ctx->async_handle, NULL); -} - - -static void sv_connection_cb(uv_stream_t* server_handle, int status) { - handle_storage_t* storage; - struct server_ctx* ctx; - - ctx = container_of(server_handle, struct server_ctx, server_handle); - ASSERT(status == 0); - - storage = malloc(sizeof(*storage)); - ASSERT(storage != NULL); - - if (server_handle->type == UV_TCP) - ASSERT(0 == uv_tcp_init(server_handle->loop, (uv_tcp_t*) storage)); - else if (server_handle->type == UV_NAMED_PIPE) - ASSERT(0 == uv_pipe_init(server_handle->loop, (uv_pipe_t*) storage, 0)); - else - ASSERT(0); - - ASSERT(0 == uv_accept(server_handle, (uv_stream_t*) storage)); - ASSERT(0 == uv_read_start((uv_stream_t*) storage, sv_alloc_cb, sv_read_cb)); - ctx->num_connects++; -} - - -static void sv_alloc_cb(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf) { - static char slab[32]; - buf->base = slab; - buf->len = sizeof(slab); -} - - -static void sv_read_cb(uv_stream_t* handle, - ssize_t nread, - const uv_buf_t* buf) { - ASSERT(nread == UV_EOF); - uv_close((uv_handle_t*) handle, (uv_close_cb) free); -} - - -static void cl_connect_cb(uv_connect_t* req, int status) { - struct client_ctx* ctx = container_of(req, struct client_ctx, connect_req); - uv_idle_start(&ctx->idle_handle, cl_idle_cb); - ASSERT(0 == status); -} - - -static void cl_idle_cb(uv_idle_t* handle) { - struct client_ctx* ctx = container_of(handle, struct client_ctx, idle_handle); - uv_close((uv_handle_t*) &ctx->client_handle, cl_close_cb); - uv_idle_stop(&ctx->idle_handle); -} - - -static void cl_close_cb(uv_handle_t* handle) { - struct client_ctx* ctx; - - ctx = container_of(handle, struct client_ctx, client_handle); - - if (--ctx->num_connects == 0) { - uv_close((uv_handle_t*) &ctx->idle_handle, NULL); - return; - } - - ASSERT(0 == uv_tcp_init(handle->loop, (uv_tcp_t*) &ctx->client_handle)); - ASSERT(0 == uv_tcp_connect(&ctx->connect_req, - (uv_tcp_t*) &ctx->client_handle, - (const struct sockaddr*) &listen_addr, - cl_connect_cb)); -} - - -static int test_tcp(unsigned int num_servers, unsigned int num_clients) { - struct server_ctx* servers; - struct client_ctx* clients; - uv_loop_t* loop; - uv_tcp_t* handle; - unsigned int i; - double time; - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &listen_addr)); - loop = uv_default_loop(); - - servers = calloc(num_servers, sizeof(servers[0])); - clients = calloc(num_clients, sizeof(clients[0])); - ASSERT(servers != NULL); - ASSERT(clients != NULL); - - /* We're making the assumption here that from the perspective of the - * OS scheduler, threads are functionally equivalent to and interchangeable - * with full-blown processes. - */ - for (i = 0; i < num_servers; i++) { - struct server_ctx* ctx = servers + i; - ASSERT(0 == uv_sem_init(&ctx->semaphore, 0)); - ASSERT(0 == uv_thread_create(&ctx->thread_id, server_cb, ctx)); - } - - send_listen_handles(UV_TCP, num_servers, servers); - - for (i = 0; i < num_clients; i++) { - struct client_ctx* ctx = clients + i; - ctx->num_connects = NUM_CONNECTS / num_clients; - handle = (uv_tcp_t*) &ctx->client_handle; - handle->data = "client handle"; - ASSERT(0 == uv_tcp_init(loop, handle)); - ASSERT(0 == uv_tcp_connect(&ctx->connect_req, - handle, - (const struct sockaddr*) &listen_addr, - cl_connect_cb)); - ASSERT(0 == uv_idle_init(loop, &ctx->idle_handle)); - } - - { - uint64_t t = uv_hrtime(); - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - t = uv_hrtime() - t; - time = t / 1e9; - } - - for (i = 0; i < num_servers; i++) { - struct server_ctx* ctx = servers + i; - uv_async_send(&ctx->async_handle); - ASSERT(0 == uv_thread_join(&ctx->thread_id)); - uv_sem_destroy(&ctx->semaphore); - } - - printf("accept%u: %.0f accepts/sec (%u total)\n", - num_servers, - NUM_CONNECTS / time, - NUM_CONNECTS); - - for (i = 0; i < num_servers; i++) { - struct server_ctx* ctx = servers + i; - printf(" thread #%u: %.0f accepts/sec (%u total, %.1f%%)\n", - i, - ctx->num_connects / time, - ctx->num_connects, - ctx->num_connects * 100.0 / NUM_CONNECTS); - } - - free(clients); - free(servers); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -BENCHMARK_IMPL(tcp_multi_accept2) { - return test_tcp(2, 40); -} - - -BENCHMARK_IMPL(tcp_multi_accept4) { - return test_tcp(4, 40); -} - - -BENCHMARK_IMPL(tcp_multi_accept8) { - return test_tcp(8, 40); -} diff --git a/libuv/test/benchmark-ping-pongs.c b/libuv/test/benchmark-ping-pongs.c deleted file mode 100644 index bb560d7..0000000 --- a/libuv/test/benchmark-ping-pongs.c +++ /dev/null @@ -1,220 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include - -/* Run the benchmark for this many ms */ -#define TIME 5000 - - -typedef struct { - int pongs; - int state; - uv_tcp_t tcp; - uv_connect_t connect_req; - uv_shutdown_t shutdown_req; -} pinger_t; - -typedef struct buf_s { - uv_buf_t uv_buf_t; - struct buf_s* next; -} buf_t; - - -static char PING[] = "PING\n"; - -static uv_loop_t* loop; - -static buf_t* buf_freelist = NULL; -static int pinger_shutdown_cb_called; -static int completed_pingers = 0; -static int64_t start_time; - - -static void buf_alloc(uv_handle_t* tcp, size_t size, uv_buf_t* buf) { - buf_t* ab; - - ab = buf_freelist; - if (ab != NULL) - buf_freelist = ab->next; - else { - ab = malloc(size + sizeof(*ab)); - ab->uv_buf_t.len = size; - ab->uv_buf_t.base = (char*) (ab + 1); - } - - *buf = ab->uv_buf_t; -} - - -static void buf_free(const uv_buf_t* buf) { - buf_t* ab = (buf_t*) buf->base - 1; - ab->next = buf_freelist; - buf_freelist = ab; -} - - -static void pinger_close_cb(uv_handle_t* handle) { - pinger_t* pinger; - - pinger = (pinger_t*)handle->data; - LOGF("ping_pongs: %d roundtrips/s\n", (1000 * pinger->pongs) / TIME); - - free(pinger); - - completed_pingers++; -} - - -static void pinger_write_cb(uv_write_t* req, int status) { - ASSERT(status == 0); - - free(req); -} - - -static void pinger_write_ping(pinger_t* pinger) { - uv_write_t* req; - uv_buf_t buf; - - buf = uv_buf_init(PING, sizeof(PING) - 1); - - req = malloc(sizeof *req); - if (uv_write(req, (uv_stream_t*) &pinger->tcp, &buf, 1, pinger_write_cb)) { - FATAL("uv_write failed"); - } -} - - -static void pinger_shutdown_cb(uv_shutdown_t* req, int status) { - ASSERT(status == 0); - pinger_shutdown_cb_called++; - - /* - * The close callback has not been triggered yet. We must wait for EOF - * until we close the connection. - */ - ASSERT(completed_pingers == 0); -} - - -static void pinger_read_cb(uv_stream_t* tcp, - ssize_t nread, - const uv_buf_t* buf) { - ssize_t i; - pinger_t* pinger; - - pinger = (pinger_t*)tcp->data; - - if (nread < 0) { - ASSERT(nread == UV_EOF); - - if (buf->base) { - buf_free(buf); - } - - ASSERT(pinger_shutdown_cb_called == 1); - uv_close((uv_handle_t*)tcp, pinger_close_cb); - - return; - } - - /* Now we count the pings */ - for (i = 0; i < nread; i++) { - ASSERT(buf->base[i] == PING[pinger->state]); - pinger->state = (pinger->state + 1) % (sizeof(PING) - 1); - if (pinger->state == 0) { - pinger->pongs++; - if (uv_now(loop) - start_time > TIME) { - uv_shutdown(&pinger->shutdown_req, - (uv_stream_t*) tcp, - pinger_shutdown_cb); - break; - } else { - pinger_write_ping(pinger); - } - } - } - - buf_free(buf); -} - - -static void pinger_connect_cb(uv_connect_t* req, int status) { - pinger_t *pinger = (pinger_t*)req->handle->data; - - ASSERT(status == 0); - - pinger_write_ping(pinger); - - if (uv_read_start(req->handle, buf_alloc, pinger_read_cb)) { - FATAL("uv_read_start failed"); - } -} - - -static void pinger_new(void) { - struct sockaddr_in client_addr; - struct sockaddr_in server_addr; - pinger_t *pinger; - int r; - - ASSERT(0 == uv_ip4_addr("0.0.0.0", 0, &client_addr)); - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &server_addr)); - pinger = malloc(sizeof(*pinger)); - pinger->state = 0; - pinger->pongs = 0; - - /* Try to connect to the server and do NUM_PINGS ping-pongs. */ - r = uv_tcp_init(loop, &pinger->tcp); - ASSERT(!r); - - pinger->tcp.data = pinger; - - ASSERT(0 == uv_tcp_bind(&pinger->tcp, - (const struct sockaddr*) &client_addr, - 0)); - - r = uv_tcp_connect(&pinger->connect_req, - &pinger->tcp, - (const struct sockaddr*) &server_addr, - pinger_connect_cb); - ASSERT(!r); -} - - -BENCHMARK_IMPL(ping_pongs) { - loop = uv_default_loop(); - - start_time = uv_now(loop); - - pinger_new(); - uv_run(loop, UV_RUN_DEFAULT); - - ASSERT(completed_pingers == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/benchmark-pound.c b/libuv/test/benchmark-pound.c deleted file mode 100644 index 5879285..0000000 --- a/libuv/test/benchmark-pound.c +++ /dev/null @@ -1,350 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "task.h" -#include "uv.h" - -/* Update this is you're going to run > 1000 concurrent requests. */ -#define MAX_CONNS 1000 - -#undef NANOSEC -#define NANOSEC ((uint64_t) 1e9) - -#undef DEBUG -#define DEBUG 0 - -struct conn_rec_s; - -typedef void (*setup_fn)(int num, void* arg); -typedef void (*make_connect_fn)(struct conn_rec_s* conn); -typedef int (*connect_fn)(int num, make_connect_fn make_connect, void* arg); - -/* Base class for tcp_conn_rec and pipe_conn_rec. - * The ordering of fields matters! - */ -typedef struct conn_rec_s { - int i; - uv_connect_t conn_req; - uv_write_t write_req; - make_connect_fn make_connect; - uv_stream_t stream; -} conn_rec; - -typedef struct { - int i; - uv_connect_t conn_req; - uv_write_t write_req; - make_connect_fn make_connect; - uv_tcp_t stream; -} tcp_conn_rec; - -typedef struct { - int i; - uv_connect_t conn_req; - uv_write_t write_req; - make_connect_fn make_connect; - uv_pipe_t stream; -} pipe_conn_rec; - -static char buffer[] = "QS"; - -static uv_loop_t* loop; - -static tcp_conn_rec tcp_conns[MAX_CONNS]; -static pipe_conn_rec pipe_conns[MAX_CONNS]; - -static uint64_t start; /* in ms */ -static int closed_streams; -static int conns_failed; - -static void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf); -static void connect_cb(uv_connect_t* conn_req, int status); -static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf); -static void close_cb(uv_handle_t* handle); - - -static void alloc_cb(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf) { - static char slab[65536]; - buf->base = slab; - buf->len = sizeof(slab); -} - - -static void after_write(uv_write_t* req, int status) { - if (status != 0) { - fprintf(stderr, "write error %s\n", uv_err_name(status)); - uv_close((uv_handle_t*)req->handle, close_cb); - conns_failed++; - return; - } -} - - -static void connect_cb(uv_connect_t* req, int status) { - conn_rec* conn; - uv_buf_t buf; - int r; - - if (status != 0) { -#if DEBUG - fprintf(stderr, "connect error %s\n", uv_err_name(status)); -#endif - uv_close((uv_handle_t*)req->handle, close_cb); - conns_failed++; - return; - } - - ASSERT(req != NULL); - ASSERT(status == 0); - - conn = (conn_rec*)req->data; - ASSERT(conn != NULL); - -#if DEBUG - printf("connect_cb %d\n", conn->i); -#endif - - r = uv_read_start(&conn->stream, alloc_cb, read_cb); - ASSERT(r == 0); - - buf.base = buffer; - buf.len = sizeof(buffer) - 1; - - r = uv_write(&conn->write_req, &conn->stream, &buf, 1, after_write); - ASSERT(r == 0); -} - - -static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { - - ASSERT(stream != NULL); - -#if DEBUG - printf("read_cb %d\n", p->i); -#endif - - uv_close((uv_handle_t*)stream, close_cb); - - if (nread < 0) { - if (nread == UV_EOF) { - ; - } else if (nread == UV_ECONNRESET) { - conns_failed++; - } else { - fprintf(stderr, "read error %s\n", uv_err_name(nread)); - ASSERT(0); - } - } -} - - -static void close_cb(uv_handle_t* handle) { - conn_rec* p = (conn_rec*)handle->data; - - ASSERT(handle != NULL); - closed_streams++; - -#if DEBUG - printf("close_cb %d\n", p->i); -#endif - - if (uv_now(loop) - start < 10000) { - p->make_connect(p); - } -} - - -static void tcp_do_setup(int num, void* arg) { - int i; - - for (i = 0; i < num; i++) { - tcp_conns[i].i = i; - } -} - - -static void pipe_do_setup(int num, void* arg) { - int i; - - for (i = 0; i < num; i++) { - pipe_conns[i].i = i; - } -} - - -static void tcp_make_connect(conn_rec* p) { - struct sockaddr_in addr; - tcp_conn_rec* tp; - int r; - - tp = (tcp_conn_rec*) p; - - r = uv_tcp_init(loop, (uv_tcp_t*)&p->stream); - ASSERT(r == 0); - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - - r = uv_tcp_connect(&tp->conn_req, - (uv_tcp_t*) &p->stream, - (const struct sockaddr*) &addr, - connect_cb); - if (r) { - fprintf(stderr, "uv_tcp_connect error %s\n", uv_err_name(r)); - ASSERT(0); - } - -#if DEBUG - printf("make connect %d\n", p->i); -#endif - - p->conn_req.data = p; - p->write_req.data = p; - p->stream.data = p; -} - - -static void pipe_make_connect(conn_rec* p) { - int r; - - r = uv_pipe_init(loop, (uv_pipe_t*)&p->stream, 0); - ASSERT(r == 0); - - uv_pipe_connect(&((pipe_conn_rec*) p)->conn_req, - (uv_pipe_t*) &p->stream, - TEST_PIPENAME, - connect_cb); - -#if DEBUG - printf("make connect %d\n", p->i); -#endif - - p->conn_req.data = p; - p->write_req.data = p; - p->stream.data = p; -} - - -static int tcp_do_connect(int num, make_connect_fn make_connect, void* arg) { - int i; - - for (i = 0; i < num; i++) { - tcp_make_connect((conn_rec*)&tcp_conns[i]); - tcp_conns[i].make_connect = make_connect; - } - - return 0; -} - - -static int pipe_do_connect(int num, make_connect_fn make_connect, void* arg) { - int i; - - for (i = 0; i < num; i++) { - pipe_make_connect((conn_rec*)&pipe_conns[i]); - pipe_conns[i].make_connect = make_connect; - } - - return 0; -} - - -static int pound_it(int concurrency, - const char* type, - setup_fn do_setup, - connect_fn do_connect, - make_connect_fn make_connect, - void* arg) { - double secs; - int r; - uint64_t start_time; /* in ns */ - uint64_t end_time; - - loop = uv_default_loop(); - - uv_update_time(loop); - start = uv_now(loop); - - /* Run benchmark for at least five seconds. */ - start_time = uv_hrtime(); - - do_setup(concurrency, arg); - - r = do_connect(concurrency, make_connect, arg); - ASSERT(!r); - - uv_run(loop, UV_RUN_DEFAULT); - - end_time = uv_hrtime(); - - /* Number of fractional seconds it took to run the benchmark. */ - secs = (double)(end_time - start_time) / NANOSEC; - - LOGF("%s-conn-pound-%d: %.0f accepts/s (%d failed)\n", - type, - concurrency, - closed_streams / secs, - conns_failed); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -BENCHMARK_IMPL(tcp4_pound_100) { - return pound_it(100, - "tcp", - tcp_do_setup, - tcp_do_connect, - tcp_make_connect, - NULL); -} - - -BENCHMARK_IMPL(tcp4_pound_1000) { - return pound_it(1000, - "tcp", - tcp_do_setup, - tcp_do_connect, - tcp_make_connect, - NULL); -} - - -BENCHMARK_IMPL(pipe_pound_100) { - return pound_it(100, - "pipe", - pipe_do_setup, - pipe_do_connect, - pipe_make_connect, - NULL); -} - - -BENCHMARK_IMPL(pipe_pound_1000) { - return pound_it(1000, - "pipe", - pipe_do_setup, - pipe_do_connect, - pipe_make_connect, - NULL); -} diff --git a/libuv/test/benchmark-pump.c b/libuv/test/benchmark-pump.c deleted file mode 100644 index d58f46a..0000000 --- a/libuv/test/benchmark-pump.c +++ /dev/null @@ -1,470 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "task.h" -#include "uv.h" - -#include -#include - - -static int TARGET_CONNECTIONS; -#define WRITE_BUFFER_SIZE 8192 -#define MAX_SIMULTANEOUS_CONNECTS 100 - -#define PRINT_STATS 0 -#define STATS_INTERVAL 1000 /* msec */ -#define STATS_COUNT 5 - - -static void do_write(uv_stream_t*); -static void maybe_connect_some(); - -static uv_req_t* req_alloc(); -static void req_free(uv_req_t* uv_req); - -static void buf_alloc(uv_handle_t* handle, size_t size, uv_buf_t* buf); -static void buf_free(const uv_buf_t* buf); - -static uv_loop_t* loop; - -static uv_tcp_t tcpServer; -static uv_pipe_t pipeServer; -static uv_stream_t* server; -static struct sockaddr_in listen_addr; -static struct sockaddr_in connect_addr; - -static int64_t start_time; - -static int max_connect_socket = 0; -static int max_read_sockets = 0; -static int read_sockets = 0; -static int write_sockets = 0; - -static int64_t nrecv = 0; -static int64_t nrecv_total = 0; -static int64_t nsent = 0; -static int64_t nsent_total = 0; - -static int stats_left = 0; - -static char write_buffer[WRITE_BUFFER_SIZE]; - -/* Make this as large as you need. */ -#define MAX_WRITE_HANDLES 1000 - -static stream_type type; - -static uv_tcp_t tcp_write_handles[MAX_WRITE_HANDLES]; -static uv_pipe_t pipe_write_handles[MAX_WRITE_HANDLES]; - -static uv_timer_t timer_handle; - - -static double gbit(int64_t bytes, int64_t passed_ms) { - double gbits = ((double)bytes / (1024 * 1024 * 1024)) * 8; - return gbits / ((double)passed_ms / 1000); -} - - -static void show_stats(uv_timer_t* handle) { - int64_t diff; - int i; - -#if PRINT_STATS - LOGF("connections: %d, write: %.1f gbit/s\n", - write_sockets, - gbit(nsent, STATS_INTERVAL)); -#endif - - /* Exit if the show is over */ - if (!--stats_left) { - - uv_update_time(loop); - diff = uv_now(loop) - start_time; - - LOGF("%s_pump%d_client: %.1f gbit/s\n", - type == TCP ? "tcp" : "pipe", - write_sockets, - gbit(nsent_total, diff)); - - for (i = 0; i < write_sockets; i++) { - if (type == TCP) - uv_close((uv_handle_t*) &tcp_write_handles[i], NULL); - else - uv_close((uv_handle_t*) &pipe_write_handles[i], NULL); - } - - exit(0); - } - - /* Reset read and write counters */ - nrecv = 0; - nsent = 0; -} - - -static void read_show_stats(void) { - int64_t diff; - - uv_update_time(loop); - diff = uv_now(loop) - start_time; - - LOGF("%s_pump%d_server: %.1f gbit/s\n", - type == TCP ? "tcp" : "pipe", - max_read_sockets, - gbit(nrecv_total, diff)); -} - - - -static void read_sockets_close_cb(uv_handle_t* handle) { - free(handle); - read_sockets--; - - /* If it's past the first second and everyone has closed their connection - * Then print stats. - */ - if (uv_now(loop) - start_time > 1000 && read_sockets == 0) { - read_show_stats(); - uv_close((uv_handle_t*)server, NULL); - } -} - - -static void start_stats_collection(void) { - int r; - - /* Show-stats timer */ - stats_left = STATS_COUNT; - r = uv_timer_init(loop, &timer_handle); - ASSERT(r == 0); - r = uv_timer_start(&timer_handle, show_stats, STATS_INTERVAL, STATS_INTERVAL); - ASSERT(r == 0); - - uv_update_time(loop); - start_time = uv_now(loop); -} - - -static void read_cb(uv_stream_t* stream, ssize_t bytes, const uv_buf_t* buf) { - if (nrecv_total == 0) { - ASSERT(start_time == 0); - uv_update_time(loop); - start_time = uv_now(loop); - } - - if (bytes < 0) { - uv_close((uv_handle_t*)stream, read_sockets_close_cb); - return; - } - - buf_free(buf); - - nrecv += bytes; - nrecv_total += bytes; -} - - -static void write_cb(uv_write_t* req, int status) { - ASSERT(status == 0); - - req_free((uv_req_t*) req); - - nsent += sizeof write_buffer; - nsent_total += sizeof write_buffer; - - do_write((uv_stream_t*) req->handle); -} - - -static void do_write(uv_stream_t* stream) { - uv_write_t* req; - uv_buf_t buf; - int r; - - buf.base = (char*) &write_buffer; - buf.len = sizeof write_buffer; - - req = (uv_write_t*) req_alloc(); - r = uv_write(req, stream, &buf, 1, write_cb); - ASSERT(r == 0); -} - - -static void connect_cb(uv_connect_t* req, int status) { - int i; - - if (status) LOG(uv_strerror(status)); - ASSERT(status == 0); - - write_sockets++; - req_free((uv_req_t*) req); - - maybe_connect_some(); - - if (write_sockets == TARGET_CONNECTIONS) { - start_stats_collection(); - - /* Yay! start writing */ - for (i = 0; i < write_sockets; i++) { - if (type == TCP) - do_write((uv_stream_t*) &tcp_write_handles[i]); - else - do_write((uv_stream_t*) &pipe_write_handles[i]); - } - } -} - - -static void maybe_connect_some(void) { - uv_connect_t* req; - uv_tcp_t* tcp; - uv_pipe_t* pipe; - int r; - - while (max_connect_socket < TARGET_CONNECTIONS && - max_connect_socket < write_sockets + MAX_SIMULTANEOUS_CONNECTS) { - if (type == TCP) { - tcp = &tcp_write_handles[max_connect_socket++]; - - r = uv_tcp_init(loop, tcp); - ASSERT(r == 0); - - req = (uv_connect_t*) req_alloc(); - r = uv_tcp_connect(req, - tcp, - (const struct sockaddr*) &connect_addr, - connect_cb); - ASSERT(r == 0); - } else { - pipe = &pipe_write_handles[max_connect_socket++]; - - r = uv_pipe_init(loop, pipe, 0); - ASSERT(r == 0); - - req = (uv_connect_t*) req_alloc(); - uv_pipe_connect(req, pipe, TEST_PIPENAME, connect_cb); - } - } -} - - -static void connection_cb(uv_stream_t* s, int status) { - uv_stream_t* stream; - int r; - - ASSERT(server == s); - ASSERT(status == 0); - - if (type == TCP) { - stream = (uv_stream_t*)malloc(sizeof(uv_tcp_t)); - r = uv_tcp_init(loop, (uv_tcp_t*)stream); - ASSERT(r == 0); - } else { - stream = (uv_stream_t*)malloc(sizeof(uv_pipe_t)); - r = uv_pipe_init(loop, (uv_pipe_t*)stream, 0); - ASSERT(r == 0); - } - - r = uv_accept(s, stream); - ASSERT(r == 0); - - r = uv_read_start(stream, buf_alloc, read_cb); - ASSERT(r == 0); - - read_sockets++; - max_read_sockets++; -} - - -/* - * Request allocator - */ - -typedef struct req_list_s { - union uv_any_req uv_req; - struct req_list_s* next; -} req_list_t; - - -static req_list_t* req_freelist = NULL; - - -static uv_req_t* req_alloc(void) { - req_list_t* req; - - req = req_freelist; - if (req != NULL) { - req_freelist = req->next; - return (uv_req_t*) req; - } - - req = (req_list_t*) malloc(sizeof *req); - return (uv_req_t*) req; -} - - -static void req_free(uv_req_t* uv_req) { - req_list_t* req = (req_list_t*) uv_req; - - req->next = req_freelist; - req_freelist = req; -} - - -/* - * Buffer allocator - */ - -typedef struct buf_list_s { - uv_buf_t uv_buf_t; - struct buf_list_s* next; -} buf_list_t; - - -static buf_list_t* buf_freelist = NULL; - - -static void buf_alloc(uv_handle_t* handle, size_t size, uv_buf_t* buf) { - buf_list_t* ab; - - ab = buf_freelist; - if (ab != NULL) - buf_freelist = ab->next; - else { - ab = malloc(size + sizeof(*ab)); - ab->uv_buf_t.len = size; - ab->uv_buf_t.base = (char*) (ab + 1); - } - - *buf = ab->uv_buf_t; -} - - -static void buf_free(const uv_buf_t* buf) { - buf_list_t* ab = (buf_list_t*) buf->base - 1; - ab->next = buf_freelist; - buf_freelist = ab; -} - - -HELPER_IMPL(tcp_pump_server) { - int r; - - type = TCP; - loop = uv_default_loop(); - - ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &listen_addr)); - - /* Server */ - server = (uv_stream_t*)&tcpServer; - r = uv_tcp_init(loop, &tcpServer); - ASSERT(r == 0); - r = uv_tcp_bind(&tcpServer, (const struct sockaddr*) &listen_addr, 0); - ASSERT(r == 0); - r = uv_listen((uv_stream_t*)&tcpServer, MAX_WRITE_HANDLES, connection_cb); - ASSERT(r == 0); - - uv_run(loop, UV_RUN_DEFAULT); - - return 0; -} - - -HELPER_IMPL(pipe_pump_server) { - int r; - type = PIPE; - - loop = uv_default_loop(); - - /* Server */ - server = (uv_stream_t*)&pipeServer; - r = uv_pipe_init(loop, &pipeServer, 0); - ASSERT(r == 0); - r = uv_pipe_bind(&pipeServer, TEST_PIPENAME); - ASSERT(r == 0); - r = uv_listen((uv_stream_t*)&pipeServer, MAX_WRITE_HANDLES, connection_cb); - ASSERT(r == 0); - - uv_run(loop, UV_RUN_DEFAULT); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -static void tcp_pump(int n) { - ASSERT(n <= MAX_WRITE_HANDLES); - TARGET_CONNECTIONS = n; - type = TCP; - - loop = uv_default_loop(); - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &connect_addr)); - - /* Start making connections */ - maybe_connect_some(); - - uv_run(loop, UV_RUN_DEFAULT); - - MAKE_VALGRIND_HAPPY(); -} - - -static void pipe_pump(int n) { - ASSERT(n <= MAX_WRITE_HANDLES); - TARGET_CONNECTIONS = n; - type = PIPE; - - loop = uv_default_loop(); - - /* Start making connections */ - maybe_connect_some(); - - uv_run(loop, UV_RUN_DEFAULT); - - MAKE_VALGRIND_HAPPY(); -} - - -BENCHMARK_IMPL(tcp_pump100_client) { - tcp_pump(100); - return 0; -} - - -BENCHMARK_IMPL(tcp_pump1_client) { - tcp_pump(1); - return 0; -} - - -BENCHMARK_IMPL(pipe_pump100_client) { - pipe_pump(100); - return 0; -} - - -BENCHMARK_IMPL(pipe_pump1_client) { - pipe_pump(1); - return 0; -} diff --git a/libuv/test/benchmark-sizes.c b/libuv/test/benchmark-sizes.c deleted file mode 100644 index 8ccf10e..0000000 --- a/libuv/test/benchmark-sizes.c +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "task.h" -#include "uv.h" - - -BENCHMARK_IMPL(sizes) { - LOGF("uv_shutdown_t: %u bytes\n", (unsigned int) sizeof(uv_shutdown_t)); - LOGF("uv_write_t: %u bytes\n", (unsigned int) sizeof(uv_write_t)); - LOGF("uv_connect_t: %u bytes\n", (unsigned int) sizeof(uv_connect_t)); - LOGF("uv_udp_send_t: %u bytes\n", (unsigned int) sizeof(uv_udp_send_t)); - LOGF("uv_tcp_t: %u bytes\n", (unsigned int) sizeof(uv_tcp_t)); - LOGF("uv_pipe_t: %u bytes\n", (unsigned int) sizeof(uv_pipe_t)); - LOGF("uv_tty_t: %u bytes\n", (unsigned int) sizeof(uv_tty_t)); - LOGF("uv_prepare_t: %u bytes\n", (unsigned int) sizeof(uv_prepare_t)); - LOGF("uv_check_t: %u bytes\n", (unsigned int) sizeof(uv_check_t)); - LOGF("uv_idle_t: %u bytes\n", (unsigned int) sizeof(uv_idle_t)); - LOGF("uv_async_t: %u bytes\n", (unsigned int) sizeof(uv_async_t)); - LOGF("uv_timer_t: %u bytes\n", (unsigned int) sizeof(uv_timer_t)); - LOGF("uv_fs_poll_t: %u bytes\n", (unsigned int) sizeof(uv_fs_poll_t)); - LOGF("uv_fs_event_t: %u bytes\n", (unsigned int) sizeof(uv_fs_event_t)); - LOGF("uv_process_t: %u bytes\n", (unsigned int) sizeof(uv_process_t)); - LOGF("uv_poll_t: %u bytes\n", (unsigned int) sizeof(uv_poll_t)); - LOGF("uv_loop_t: %u bytes\n", (unsigned int) sizeof(uv_loop_t)); - return 0; -} diff --git a/libuv/test/benchmark-spawn.c b/libuv/test/benchmark-spawn.c deleted file mode 100644 index 9cae41a..0000000 --- a/libuv/test/benchmark-spawn.c +++ /dev/null @@ -1,163 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* This benchmark spawns itself 1000 times. */ - -#include "task.h" -#include "uv.h" - -static uv_loop_t* loop; - -static int N = 1000; -static int done; - -static uv_process_t process; -static uv_process_options_t options; -static char exepath[1024]; -static size_t exepath_size = 1024; -static char* args[3]; -static uv_pipe_t out; - -#define OUTPUT_SIZE 1024 -static char output[OUTPUT_SIZE]; -static int output_used; - -static int process_open; -static int pipe_open; - - -static void spawn(void); - - -static void maybe_spawn(void) { - if (process_open == 0 && pipe_open == 0) { - done++; - if (done < N) { - spawn(); - } - } -} - - -static void process_close_cb(uv_handle_t* handle) { - ASSERT(process_open == 1); - process_open = 0; - maybe_spawn(); -} - - -static void exit_cb(uv_process_t* process, - int64_t exit_status, - int term_signal) { - ASSERT(exit_status == 42); - ASSERT(term_signal == 0); - uv_close((uv_handle_t*)process, process_close_cb); -} - - -static void on_alloc(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf) { - buf->base = output + output_used; - buf->len = OUTPUT_SIZE - output_used; -} - - -static void pipe_close_cb(uv_handle_t* pipe) { - ASSERT(pipe_open == 1); - pipe_open = 0; - maybe_spawn(); -} - - -static void on_read(uv_stream_t* pipe, ssize_t nread, const uv_buf_t* buf) { - if (nread > 0) { - ASSERT(pipe_open == 1); - output_used += nread; - } else if (nread < 0) { - if (nread == UV_EOF) { - uv_close((uv_handle_t*)pipe, pipe_close_cb); - } - } -} - - -static void spawn(void) { - uv_stdio_container_t stdio[2]; - int r; - - ASSERT(process_open == 0); - ASSERT(pipe_open == 0); - - args[0] = exepath; - args[1] = "spawn_helper"; - args[2] = NULL; - options.file = exepath; - options.args = args; - options.exit_cb = exit_cb; - - uv_pipe_init(loop, &out, 0); - - options.stdio = stdio; - options.stdio_count = 2; - options.stdio[0].flags = UV_IGNORE; - options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; - options.stdio[1].data.stream = (uv_stream_t*)&out; - - r = uv_spawn(loop, &process, &options); - ASSERT(r == 0); - - process_open = 1; - pipe_open = 1; - output_used = 0; - - r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read); - ASSERT(r == 0); -} - - -BENCHMARK_IMPL(spawn) { - int r; - static int64_t start_time, end_time; - - loop = uv_default_loop(); - - r = uv_exepath(exepath, &exepath_size); - ASSERT(r == 0); - exepath[exepath_size] = '\0'; - - uv_update_time(loop); - start_time = uv_now(loop); - - spawn(); - - r = uv_run(loop, UV_RUN_DEFAULT); - ASSERT(r == 0); - - uv_update_time(loop); - end_time = uv_now(loop); - - LOGF("spawn: %.0f spawns/s\n", - (double) N / (double) (end_time - start_time) * 1000.0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/benchmark-tcp-write-batch.c b/libuv/test/benchmark-tcp-write-batch.c deleted file mode 100644 index 96921b7..0000000 --- a/libuv/test/benchmark-tcp-write-batch.c +++ /dev/null @@ -1,144 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include - -#define WRITE_REQ_DATA "Hello, world." -#define NUM_WRITE_REQS (1000 * 1000) - -typedef struct { - uv_write_t req; - uv_buf_t buf; -} write_req; - - -static write_req* write_reqs; -static uv_tcp_t tcp_client; -static uv_connect_t connect_req; -static uv_shutdown_t shutdown_req; - -static int shutdown_cb_called = 0; -static int connect_cb_called = 0; -static int write_cb_called = 0; -static int close_cb_called = 0; - -static void connect_cb(uv_connect_t* req, int status); -static void write_cb(uv_write_t* req, int status); -static void shutdown_cb(uv_shutdown_t* req, int status); -static void close_cb(uv_handle_t* handle); - - -static void connect_cb(uv_connect_t* req, int status) { - write_req* w; - int i; - int r; - - ASSERT(req->handle == (uv_stream_t*)&tcp_client); - - for (i = 0; i < NUM_WRITE_REQS; i++) { - w = &write_reqs[i]; - r = uv_write(&w->req, req->handle, &w->buf, 1, write_cb); - ASSERT(r == 0); - } - - r = uv_shutdown(&shutdown_req, req->handle, shutdown_cb); - ASSERT(r == 0); - - connect_cb_called++; -} - - -static void write_cb(uv_write_t* req, int status) { - ASSERT(req != NULL); - ASSERT(status == 0); - write_cb_called++; -} - - -static void shutdown_cb(uv_shutdown_t* req, int status) { - ASSERT(req->handle == (uv_stream_t*)&tcp_client); - ASSERT(req->handle->write_queue_size == 0); - - uv_close((uv_handle_t*)req->handle, close_cb); - free(write_reqs); - - shutdown_cb_called++; -} - - -static void close_cb(uv_handle_t* handle) { - ASSERT(handle == (uv_handle_t*)&tcp_client); - close_cb_called++; -} - - -BENCHMARK_IMPL(tcp_write_batch) { - struct sockaddr_in addr; - uv_loop_t* loop; - uint64_t start; - uint64_t stop; - int i; - int r; - - write_reqs = malloc(sizeof(*write_reqs) * NUM_WRITE_REQS); - ASSERT(write_reqs != NULL); - - /* Prepare the data to write out. */ - for (i = 0; i < NUM_WRITE_REQS; i++) { - write_reqs[i].buf = uv_buf_init(WRITE_REQ_DATA, - sizeof(WRITE_REQ_DATA) - 1); - } - - loop = uv_default_loop(); - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - - r = uv_tcp_init(loop, &tcp_client); - ASSERT(r == 0); - - r = uv_tcp_connect(&connect_req, - &tcp_client, - (const struct sockaddr*) &addr, - connect_cb); - ASSERT(r == 0); - - start = uv_hrtime(); - - r = uv_run(loop, UV_RUN_DEFAULT); - ASSERT(r == 0); - - stop = uv_hrtime(); - - ASSERT(connect_cb_called == 1); - ASSERT(write_cb_called == NUM_WRITE_REQS); - ASSERT(shutdown_cb_called == 1); - ASSERT(close_cb_called == 1); - - printf("%ld write requests in %.2fs.\n", - (long)NUM_WRITE_REQS, - (stop - start) / 1e9); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/benchmark-thread.c b/libuv/test/benchmark-thread.c deleted file mode 100644 index b37a7fd..0000000 --- a/libuv/test/benchmark-thread.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include - -#define NUM_THREADS (20 * 1000) - -static volatile int num_threads; - - -static void thread_entry(void* arg) { - ASSERT(arg == (void *) 42); - num_threads++; - /* FIXME write barrier? */ -} - - -BENCHMARK_IMPL(thread_create) { - uint64_t start_time; - double duration; - uv_thread_t tid; - int i, r; - - start_time = uv_hrtime(); - - for (i = 0; i < NUM_THREADS; i++) { - r = uv_thread_create(&tid, thread_entry, (void *) 42); - ASSERT(r == 0); - - r = uv_thread_join(&tid); - ASSERT(r == 0); - } - - duration = (uv_hrtime() - start_time) / 1e9; - - ASSERT(num_threads == NUM_THREADS); - - printf("%d threads created in %.2f seconds (%.0f/s)\n", - NUM_THREADS, duration, NUM_THREADS / duration); - - return 0; -} diff --git a/libuv/test/benchmark-udp-pummel.c b/libuv/test/benchmark-udp-pummel.c deleted file mode 100644 index 68a2373..0000000 --- a/libuv/test/benchmark-udp-pummel.c +++ /dev/null @@ -1,243 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "task.h" -#include "uv.h" - -#include -#include -#include - -#define EXPECTED "RANG TANG DING DONG I AM THE JAPANESE SANDMAN" - -#define TEST_DURATION 5000 /* ms */ - -#define BASE_PORT 12345 - -struct sender_state { - struct sockaddr_in addr; - uv_udp_send_t send_req; - uv_udp_t udp_handle; -}; - -struct receiver_state { - struct sockaddr_in addr; - uv_udp_t udp_handle; -}; - -/* not used in timed mode */ -static unsigned int packet_counter = (unsigned int) 1e6; - -static int n_senders_; -static int n_receivers_; -static uv_buf_t bufs[5]; -static struct sender_state senders[1024]; -static struct receiver_state receivers[1024]; - -static unsigned int send_cb_called; -static unsigned int recv_cb_called; -static unsigned int close_cb_called; -static int timed; -static int exiting; - - -static void alloc_cb(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf) { - static char slab[65536]; - ASSERT(suggested_size <= sizeof(slab)); - buf->base = slab; - buf->len = sizeof(slab); -} - - -static void send_cb(uv_udp_send_t* req, int status) { - struct sender_state* s; - - ASSERT(req != NULL); - - if (status != 0) { - ASSERT(status == UV_ECANCELED); - return; - } - - if (exiting) - return; - - s = container_of(req, struct sender_state, send_req); - ASSERT(req->handle == &s->udp_handle); - - if (timed) - goto send; - - if (packet_counter == 0) { - uv_close((uv_handle_t*)&s->udp_handle, NULL); - return; - } - - packet_counter--; - -send: - ASSERT(0 == uv_udp_send(&s->send_req, - &s->udp_handle, - bufs, - ARRAY_SIZE(bufs), - (const struct sockaddr*) &s->addr, - send_cb)); - send_cb_called++; -} - - -static void recv_cb(uv_udp_t* handle, - ssize_t nread, - const uv_buf_t* buf, - const struct sockaddr* addr, - unsigned flags) { - if (nread == 0) - return; - - if (nread < 0) { - ASSERT(nread == UV_ECANCELED); - return; - } - - ASSERT(addr->sa_family == AF_INET); - ASSERT(!memcmp(buf->base, EXPECTED, nread)); - - recv_cb_called++; -} - - -static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); - close_cb_called++; -} - - -static void timeout_cb(uv_timer_t* timer) { - int i; - - exiting = 1; - - for (i = 0; i < n_senders_; i++) - uv_close((uv_handle_t*)&senders[i].udp_handle, close_cb); - - for (i = 0; i < n_receivers_; i++) - uv_close((uv_handle_t*)&receivers[i].udp_handle, close_cb); -} - - -static int pummel(unsigned int n_senders, - unsigned int n_receivers, - unsigned long timeout) { - uv_timer_t timer_handle; - uint64_t duration; - uv_loop_t* loop; - unsigned int i; - - ASSERT(n_senders <= ARRAY_SIZE(senders)); - ASSERT(n_receivers <= ARRAY_SIZE(receivers)); - - loop = uv_default_loop(); - - n_senders_ = n_senders; - n_receivers_ = n_receivers; - - if (timeout) { - ASSERT(0 == uv_timer_init(loop, &timer_handle)); - ASSERT(0 == uv_timer_start(&timer_handle, timeout_cb, timeout, 0)); - /* Timer should not keep loop alive. */ - uv_unref((uv_handle_t*)&timer_handle); - timed = 1; - } - - for (i = 0; i < n_receivers; i++) { - struct receiver_state* s = receivers + i; - struct sockaddr_in addr; - ASSERT(0 == uv_ip4_addr("0.0.0.0", BASE_PORT + i, &addr)); - ASSERT(0 == uv_udp_init(loop, &s->udp_handle)); - ASSERT(0 == uv_udp_bind(&s->udp_handle, (const struct sockaddr*) &addr, 0)); - ASSERT(0 == uv_udp_recv_start(&s->udp_handle, alloc_cb, recv_cb)); - uv_unref((uv_handle_t*)&s->udp_handle); - } - - bufs[0] = uv_buf_init(EXPECTED + 0, 10); - bufs[1] = uv_buf_init(EXPECTED + 10, 10); - bufs[2] = uv_buf_init(EXPECTED + 20, 10); - bufs[3] = uv_buf_init(EXPECTED + 30, 10); - bufs[4] = uv_buf_init(EXPECTED + 40, 5); - - for (i = 0; i < n_senders; i++) { - struct sender_state* s = senders + i; - ASSERT(0 == uv_ip4_addr("127.0.0.1", - BASE_PORT + (i % n_receivers), - &s->addr)); - ASSERT(0 == uv_udp_init(loop, &s->udp_handle)); - ASSERT(0 == uv_udp_send(&s->send_req, - &s->udp_handle, - bufs, - ARRAY_SIZE(bufs), - (const struct sockaddr*) &s->addr, - send_cb)); - } - - duration = uv_hrtime(); - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - duration = uv_hrtime() - duration; - /* convert from nanoseconds to milliseconds */ - duration = duration / (uint64_t) 1e6; - - printf("udp_pummel_%dv%d: %.0f/s received, %.0f/s sent. " - "%u received, %u sent in %.1f seconds.\n", - n_receivers, - n_senders, - recv_cb_called / (duration / 1000.0), - send_cb_called / (duration / 1000.0), - recv_cb_called, - send_cb_called, - duration / 1000.0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -#define X(a, b) \ - BENCHMARK_IMPL(udp_pummel_##a##v##b) { \ - return pummel(a, b, 0); \ - } \ - BENCHMARK_IMPL(udp_timed_pummel_##a##v##b) { \ - return pummel(a, b, TEST_DURATION); \ - } - -X(1, 1) -X(1, 10) -X(1, 100) -X(1, 1000) -X(10, 10) -X(10, 100) -X(10, 1000) -X(100, 10) -X(100, 100) -X(100, 1000) -X(1000, 1000) - -#undef X diff --git a/libuv/test/blackhole-server.c b/libuv/test/blackhole-server.c deleted file mode 100644 index ad878b3..0000000 --- a/libuv/test/blackhole-server.c +++ /dev/null @@ -1,121 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include - -typedef struct { - uv_tcp_t handle; - uv_shutdown_t shutdown_req; -} conn_rec; - -static uv_tcp_t tcp_server; - -static void connection_cb(uv_stream_t* stream, int status); -static void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf); -static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf); -static void shutdown_cb(uv_shutdown_t* req, int status); -static void close_cb(uv_handle_t* handle); - - -static void connection_cb(uv_stream_t* stream, int status) { - conn_rec* conn; - int r; - - ASSERT(status == 0); - ASSERT(stream == (uv_stream_t*)&tcp_server); - - conn = malloc(sizeof *conn); - ASSERT(conn != NULL); - - r = uv_tcp_init(stream->loop, &conn->handle); - ASSERT(r == 0); - - r = uv_accept(stream, (uv_stream_t*)&conn->handle); - ASSERT(r == 0); - - r = uv_read_start((uv_stream_t*)&conn->handle, alloc_cb, read_cb); - ASSERT(r == 0); -} - - -static void alloc_cb(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf) { - static char slab[65536]; - buf->base = slab; - buf->len = sizeof(slab); -} - - -static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { - conn_rec* conn; - int r; - - if (nread >= 0) - return; - - ASSERT(nread == UV_EOF); - - conn = container_of(stream, conn_rec, handle); - - r = uv_shutdown(&conn->shutdown_req, stream, shutdown_cb); - ASSERT(r == 0); -} - - -static void shutdown_cb(uv_shutdown_t* req, int status) { - conn_rec* conn = container_of(req, conn_rec, shutdown_req); - uv_close((uv_handle_t*)&conn->handle, close_cb); -} - - -static void close_cb(uv_handle_t* handle) { - conn_rec* conn = container_of(handle, conn_rec, handle); - free(conn); -} - - -HELPER_IMPL(tcp4_blackhole_server) { - struct sockaddr_in addr; - uv_loop_t* loop; - int r; - - loop = uv_default_loop(); - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - - r = uv_tcp_init(loop, &tcp_server); - ASSERT(r == 0); - - r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - - r = uv_listen((uv_stream_t*)&tcp_server, 128, connection_cb); - ASSERT(r == 0); - - r = uv_run(loop, UV_RUN_DEFAULT); - ASSERT(0 && "Blackhole server dropped out of event loop."); - - return 0; -} diff --git a/libuv/test/dns-server.c b/libuv/test/dns-server.c deleted file mode 100644 index 80052c7..0000000 --- a/libuv/test/dns-server.c +++ /dev/null @@ -1,340 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" -#include -#include -#include - - -typedef struct { - uv_write_t req; - uv_buf_t buf; -} write_req_t; - - -/* used to track multiple DNS requests received */ -typedef struct { - char* prevbuf_ptr; - int prevbuf_pos; - int prevbuf_rem; -} dnsstate; - - -/* modify handle to append dnsstate */ -typedef struct { - uv_tcp_t handle; - dnsstate state; -} dnshandle; - - -static uv_loop_t* loop; - - -static uv_tcp_t server; - - -static void after_write(uv_write_t* req, int status); -static void after_read(uv_stream_t*, ssize_t nread, const uv_buf_t* buf); -static void on_close(uv_handle_t* peer); -static void on_connection(uv_stream_t*, int status); - -#define WRITE_BUF_LEN (64*1024) -#define DNSREC_LEN (4) - -#define LEN_OFFSET 0 -#define QUERYID_OFFSET 2 - -static unsigned char DNSRsp[] = { - 0, 43, 0, 0, 0x81, 0x80, 0, 1, 0, 1, 0, 0, 0, 0 -}; - -static unsigned char qrecord[] = { - 5, 'e', 'c', 'h', 'o', 's', 3, 's', 'r', 'v', 0, 0, 1, 0, 1 -}; - -static unsigned char arecord[] = { - 0xc0, 0x0c, 0, 1, 0, 1, 0, 0, 5, 0xbd, 0, 4, 10, 0, 1, 1 -}; - - -static void after_write(uv_write_t* req, int status) { - write_req_t* wr; - - if (status) { - fprintf(stderr, "uv_write error: %s\n", uv_strerror(status)); - ASSERT(0); - } - - wr = (write_req_t*) req; - - /* Free the read/write buffer and the request */ - free(wr->buf.base); - free(wr); -} - - -static void after_shutdown(uv_shutdown_t* req, int status) { - uv_close((uv_handle_t*) req->handle, on_close); - free(req); -} - - -static void addrsp(write_req_t* wr, char* hdr) { - char * dnsrsp; - short int rsplen; - short int* reclen; - - rsplen = sizeof(DNSRsp) + sizeof(qrecord) + sizeof(arecord); - - ASSERT (rsplen + wr->buf.len < WRITE_BUF_LEN); - - dnsrsp = wr->buf.base + wr->buf.len; - - /* copy stock response */ - memcpy(dnsrsp, DNSRsp, sizeof(DNSRsp)); - memcpy(dnsrsp + sizeof(DNSRsp), qrecord, sizeof(qrecord)); - memcpy(dnsrsp + sizeof(DNSRsp) + sizeof(qrecord), arecord, sizeof(arecord)); - - /* overwrite with network order length and id from request header */ - reclen = (short int*)dnsrsp; - *reclen = htons(rsplen-2); - dnsrsp[QUERYID_OFFSET] = hdr[QUERYID_OFFSET]; - dnsrsp[QUERYID_OFFSET+1] = hdr[QUERYID_OFFSET+1]; - - wr->buf.len += rsplen; -} - -static void process_req(uv_stream_t* handle, - ssize_t nread, - const uv_buf_t* buf) { - write_req_t* wr; - dnshandle* dns = (dnshandle*)handle; - char hdrbuf[DNSREC_LEN]; - int hdrbuf_remaining = DNSREC_LEN; - int rec_remaining = 0; - int readbuf_remaining; - char* dnsreq; - char* hdrstart; - int usingprev = 0; - - wr = (write_req_t*) malloc(sizeof *wr); - wr->buf.base = (char*)malloc(WRITE_BUF_LEN); - wr->buf.len = 0; - - if (dns->state.prevbuf_ptr != NULL) { - dnsreq = dns->state.prevbuf_ptr + dns->state.prevbuf_pos; - readbuf_remaining = dns->state.prevbuf_rem; - usingprev = 1; - } else { - dnsreq = buf->base; - readbuf_remaining = nread; - } - hdrstart = dnsreq; - - while (dnsreq != NULL) { - /* something to process */ - while (readbuf_remaining > 0) { - /* something to process in current buffer */ - if (hdrbuf_remaining > 0) { - /* process len and id */ - if (readbuf_remaining < hdrbuf_remaining) { - /* too little to get request header. save for next buffer */ - memcpy(&hdrbuf[DNSREC_LEN - hdrbuf_remaining], - dnsreq, - readbuf_remaining); - hdrbuf_remaining = DNSREC_LEN - readbuf_remaining; - break; - } else { - /* save header */ - memcpy(&hdrbuf[DNSREC_LEN - hdrbuf_remaining], - dnsreq, - hdrbuf_remaining); - dnsreq += hdrbuf_remaining; - readbuf_remaining -= hdrbuf_remaining; - hdrbuf_remaining = 0; - - /* get record length */ - rec_remaining = (unsigned) hdrbuf[0] * 256 + (unsigned) hdrbuf[1]; - rec_remaining -= (DNSREC_LEN - 2); - } - } - - if (rec_remaining <= readbuf_remaining) { - /* prepare reply */ - addrsp(wr, hdrbuf); - - /* move to next record */ - dnsreq += rec_remaining; - hdrstart = dnsreq; - readbuf_remaining -= rec_remaining; - rec_remaining = 0; - hdrbuf_remaining = DNSREC_LEN; - } else { - /* otherwise this buffer is done. */ - rec_remaining -= readbuf_remaining; - break; - } - } - - /* If we had to use bytes from prev buffer, start processing the current - * one. - */ - if (usingprev == 1) { - /* free previous buffer */ - free(dns->state.prevbuf_ptr); - dnsreq = buf->base; - readbuf_remaining = nread; - usingprev = 0; - } else { - dnsreq = NULL; - } - } - - /* send write buffer */ - if (wr->buf.len > 0) { - if (uv_write((uv_write_t*) &wr->req, handle, &wr->buf, 1, after_write)) { - FATAL("uv_write failed"); - } - } - - if (readbuf_remaining > 0) { - /* save start of record position, so we can continue on next read */ - dns->state.prevbuf_ptr = buf->base; - dns->state.prevbuf_pos = hdrstart - buf->base; - dns->state.prevbuf_rem = nread - dns->state.prevbuf_pos; - } else { - /* nothing left in this buffer */ - dns->state.prevbuf_ptr = NULL; - dns->state.prevbuf_pos = 0; - dns->state.prevbuf_rem = 0; - free(buf->base); - } -} - -static void after_read(uv_stream_t* handle, - ssize_t nread, - const uv_buf_t* buf) { - uv_shutdown_t* req; - - if (nread < 0) { - /* Error or EOF */ - ASSERT(nread == UV_EOF); - - if (buf->base) { - free(buf->base); - } - - req = malloc(sizeof *req); - uv_shutdown(req, handle, after_shutdown); - - return; - } - - if (nread == 0) { - /* Everything OK, but nothing read. */ - free(buf->base); - return; - } - /* process requests and send responses */ - process_req(handle, nread, buf); -} - - -static void on_close(uv_handle_t* peer) { - free(peer); -} - - -static void buf_alloc(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf) { - buf->base = malloc(suggested_size); - buf->len = suggested_size; -} - - -static void on_connection(uv_stream_t* server, int status) { - dnshandle* handle; - int r; - - ASSERT(status == 0); - - handle = (dnshandle*) malloc(sizeof *handle); - ASSERT(handle != NULL); - - /* initialize read buffer state */ - handle->state.prevbuf_ptr = 0; - handle->state.prevbuf_pos = 0; - handle->state.prevbuf_rem = 0; - - r = uv_tcp_init(loop, (uv_tcp_t*)handle); - ASSERT(r == 0); - - r = uv_accept(server, (uv_stream_t*)handle); - ASSERT(r == 0); - - r = uv_read_start((uv_stream_t*)handle, buf_alloc, after_read); - ASSERT(r == 0); -} - - -static int dns_start(int port) { - struct sockaddr_in addr; - int r; - - ASSERT(0 == uv_ip4_addr("0.0.0.0", port, &addr)); - - r = uv_tcp_init(loop, &server); - if (r) { - /* TODO: Error codes */ - fprintf(stderr, "Socket creation error\n"); - return 1; - } - - r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); - if (r) { - /* TODO: Error codes */ - fprintf(stderr, "Bind error\n"); - return 1; - } - - r = uv_listen((uv_stream_t*)&server, 128, on_connection); - if (r) { - /* TODO: Error codes */ - fprintf(stderr, "Listen error\n"); - return 1; - } - - return 0; -} - - -HELPER_IMPL(dns_server) { - loop = uv_default_loop(); - - if (dns_start(TEST_PORT_2)) - return 1; - - uv_run(loop, UV_RUN_DEFAULT); - return 0; -} diff --git a/libuv/test/echo-server.c b/libuv/test/echo-server.c deleted file mode 100644 index f223981..0000000 --- a/libuv/test/echo-server.c +++ /dev/null @@ -1,378 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" -#include -#include - -typedef struct { - uv_write_t req; - uv_buf_t buf; -} write_req_t; - -static uv_loop_t* loop; - -static int server_closed; -static stream_type serverType; -static uv_tcp_t tcpServer; -static uv_udp_t udpServer; -static uv_pipe_t pipeServer; -static uv_handle_t* server; - -static void after_write(uv_write_t* req, int status); -static void after_read(uv_stream_t*, ssize_t nread, const uv_buf_t* buf); -static void on_close(uv_handle_t* peer); -static void on_server_close(uv_handle_t* handle); -static void on_connection(uv_stream_t*, int status); - - -static void after_write(uv_write_t* req, int status) { - write_req_t* wr; - - /* Free the read/write buffer and the request */ - wr = (write_req_t*) req; - free(wr->buf.base); - free(wr); - - if (status == 0) - return; - - fprintf(stderr, - "uv_write error: %s - %s\n", - uv_err_name(status), - uv_strerror(status)); -} - - -static void after_shutdown(uv_shutdown_t* req, int status) { - uv_close((uv_handle_t*) req->handle, on_close); - free(req); -} - - -static void after_read(uv_stream_t* handle, - ssize_t nread, - const uv_buf_t* buf) { - int i; - write_req_t *wr; - uv_shutdown_t* sreq; - - if (nread < 0) { - /* Error or EOF */ - ASSERT(nread == UV_EOF); - - free(buf->base); - sreq = malloc(sizeof* sreq); - ASSERT(0 == uv_shutdown(sreq, handle, after_shutdown)); - return; - } - - if (nread == 0) { - /* Everything OK, but nothing read. */ - free(buf->base); - return; - } - - /* - * Scan for the letter Q which signals that we should quit the server. - * If we get QS it means close the stream. - */ - if (!server_closed) { - for (i = 0; i < nread; i++) { - if (buf->base[i] == 'Q') { - if (i + 1 < nread && buf->base[i + 1] == 'S') { - free(buf->base); - uv_close((uv_handle_t*)handle, on_close); - return; - } else { - uv_close(server, on_server_close); - server_closed = 1; - } - } - } - } - - wr = (write_req_t*) malloc(sizeof *wr); - ASSERT(wr != NULL); - wr->buf = uv_buf_init(buf->base, nread); - - if (uv_write(&wr->req, handle, &wr->buf, 1, after_write)) { - FATAL("uv_write failed"); - } -} - - -static void on_close(uv_handle_t* peer) { - free(peer); -} - - -static void echo_alloc(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf) { - buf->base = malloc(suggested_size); - buf->len = suggested_size; -} - - -static void on_connection(uv_stream_t* server, int status) { - uv_stream_t* stream; - int r; - - if (status != 0) { - fprintf(stderr, "Connect error %s\n", uv_err_name(status)); - } - ASSERT(status == 0); - - switch (serverType) { - case TCP: - stream = malloc(sizeof(uv_tcp_t)); - ASSERT(stream != NULL); - r = uv_tcp_init(loop, (uv_tcp_t*)stream); - ASSERT(r == 0); - break; - - case PIPE: - stream = malloc(sizeof(uv_pipe_t)); - ASSERT(stream != NULL); - r = uv_pipe_init(loop, (uv_pipe_t*)stream, 0); - ASSERT(r == 0); - break; - - default: - ASSERT(0 && "Bad serverType"); - abort(); - } - - /* associate server with stream */ - stream->data = server; - - r = uv_accept(server, stream); - ASSERT(r == 0); - - r = uv_read_start(stream, echo_alloc, after_read); - ASSERT(r == 0); -} - - -static void on_server_close(uv_handle_t* handle) { - ASSERT(handle == server); -} - - -static void on_send(uv_udp_send_t* req, int status); - - -static void on_recv(uv_udp_t* handle, - ssize_t nread, - const uv_buf_t* rcvbuf, - const struct sockaddr* addr, - unsigned flags) { - uv_udp_send_t* req; - uv_buf_t sndbuf; - - ASSERT(nread > 0); - ASSERT(addr->sa_family == AF_INET); - - req = malloc(sizeof(*req)); - ASSERT(req != NULL); - - sndbuf = *rcvbuf; - ASSERT(0 == uv_udp_send(req, handle, &sndbuf, 1, addr, on_send)); -} - - -static void on_send(uv_udp_send_t* req, int status) { - ASSERT(status == 0); - free(req); -} - - -static int tcp4_echo_start(int port) { - struct sockaddr_in addr; - int r; - - ASSERT(0 == uv_ip4_addr("0.0.0.0", port, &addr)); - - server = (uv_handle_t*)&tcpServer; - serverType = TCP; - - r = uv_tcp_init(loop, &tcpServer); - if (r) { - /* TODO: Error codes */ - fprintf(stderr, "Socket creation error\n"); - return 1; - } - - r = uv_tcp_bind(&tcpServer, (const struct sockaddr*) &addr, 0); - if (r) { - /* TODO: Error codes */ - fprintf(stderr, "Bind error\n"); - return 1; - } - - r = uv_listen((uv_stream_t*)&tcpServer, SOMAXCONN, on_connection); - if (r) { - /* TODO: Error codes */ - fprintf(stderr, "Listen error %s\n", uv_err_name(r)); - return 1; - } - - return 0; -} - - -static int tcp6_echo_start(int port) { - struct sockaddr_in6 addr6; - int r; - - ASSERT(0 == uv_ip6_addr("::1", port, &addr6)); - - server = (uv_handle_t*)&tcpServer; - serverType = TCP; - - r = uv_tcp_init(loop, &tcpServer); - if (r) { - /* TODO: Error codes */ - fprintf(stderr, "Socket creation error\n"); - return 1; - } - - /* IPv6 is optional as not all platforms support it */ - r = uv_tcp_bind(&tcpServer, (const struct sockaddr*) &addr6, 0); - if (r) { - /* show message but return OK */ - fprintf(stderr, "IPv6 not supported\n"); - return 0; - } - - r = uv_listen((uv_stream_t*)&tcpServer, SOMAXCONN, on_connection); - if (r) { - /* TODO: Error codes */ - fprintf(stderr, "Listen error\n"); - return 1; - } - - return 0; -} - - -static int udp4_echo_start(int port) { - int r; - - server = (uv_handle_t*)&udpServer; - serverType = UDP; - - r = uv_udp_init(loop, &udpServer); - if (r) { - fprintf(stderr, "uv_udp_init: %s\n", uv_strerror(r)); - return 1; - } - - r = uv_udp_recv_start(&udpServer, echo_alloc, on_recv); - if (r) { - fprintf(stderr, "uv_udp_recv_start: %s\n", uv_strerror(r)); - return 1; - } - - return 0; -} - - -static int pipe_echo_start(char* pipeName) { - int r; - -#ifndef _WIN32 - { - uv_fs_t req; - uv_fs_unlink(uv_default_loop(), &req, pipeName, NULL); - uv_fs_req_cleanup(&req); - } -#endif - - server = (uv_handle_t*)&pipeServer; - serverType = PIPE; - - r = uv_pipe_init(loop, &pipeServer, 0); - if (r) { - fprintf(stderr, "uv_pipe_init: %s\n", uv_strerror(r)); - return 1; - } - - r = uv_pipe_bind(&pipeServer, pipeName); - if (r) { - fprintf(stderr, "uv_pipe_bind: %s\n", uv_strerror(r)); - return 1; - } - - r = uv_listen((uv_stream_t*)&pipeServer, SOMAXCONN, on_connection); - if (r) { - fprintf(stderr, "uv_pipe_listen: %s\n", uv_strerror(r)); - return 1; - } - - return 0; -} - - -HELPER_IMPL(tcp4_echo_server) { - loop = uv_default_loop(); - - if (tcp4_echo_start(TEST_PORT)) - return 1; - - uv_run(loop, UV_RUN_DEFAULT); - return 0; -} - - -HELPER_IMPL(tcp6_echo_server) { - loop = uv_default_loop(); - - if (tcp6_echo_start(TEST_PORT)) - return 1; - - uv_run(loop, UV_RUN_DEFAULT); - return 0; -} - - -HELPER_IMPL(pipe_echo_server) { - loop = uv_default_loop(); - - if (pipe_echo_start(TEST_PIPENAME)) - return 1; - - uv_run(loop, UV_RUN_DEFAULT); - return 0; -} - - -HELPER_IMPL(udp4_echo_server) { - loop = uv_default_loop(); - - if (udp4_echo_start(TEST_PORT)) - return 1; - - uv_run(loop, UV_RUN_DEFAULT); - return 0; -} diff --git a/libuv/test/fixtures/empty_file b/libuv/test/fixtures/empty_file deleted file mode 100644 index e69de29..0000000 diff --git a/libuv/test/fixtures/load_error.node b/libuv/test/fixtures/load_error.node deleted file mode 100644 index 323fae0..0000000 --- a/libuv/test/fixtures/load_error.node +++ /dev/null @@ -1 +0,0 @@ -foobar diff --git a/libuv/test/run-benchmarks.c b/libuv/test/run-benchmarks.c deleted file mode 100644 index 8d4f549..0000000 --- a/libuv/test/run-benchmarks.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include - -#include "runner.h" -#include "task.h" - -/* Actual benchmarks and helpers are defined in benchmark-list.h */ -#include "benchmark-list.h" - - -static int maybe_run_test(int argc, char **argv); - - -int main(int argc, char **argv) { - if (platform_init(argc, argv)) - return EXIT_FAILURE; - - switch (argc) { - case 1: return run_tests(1); - case 2: return maybe_run_test(argc, argv); - case 3: return run_test_part(argv[1], argv[2]); - default: - LOGF("Too many arguments.\n"); - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} - - -static int maybe_run_test(int argc, char **argv) { - if (strcmp(argv[1], "--list") == 0) { - print_tests(stdout); - return 0; - } - - if (strcmp(argv[1], "spawn_helper") == 0) { - printf("hello world\n"); - return 42; - } - - return run_test(argv[1], 1, 1); -} diff --git a/libuv/test/run-tests.c b/libuv/test/run-tests.c deleted file mode 100644 index e92c930..0000000 --- a/libuv/test/run-tests.c +++ /dev/null @@ -1,175 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include - -#ifdef _WIN32 -# include -#else -# include -#endif - -#include "uv.h" -#include "runner.h" -#include "task.h" - -/* Actual tests and helpers are defined in test-list.h */ -#include "test-list.h" - -int ipc_helper(int listen_after_write); -int ipc_helper_tcp_connection(void); -int ipc_send_recv_helper(void); -int ipc_helper_bind_twice(void); -int stdio_over_pipes_helper(void); - -static int maybe_run_test(int argc, char **argv); - - -int main(int argc, char **argv) { - if (platform_init(argc, argv)) - return EXIT_FAILURE; - - argv = uv_setup_args(argc, argv); - - switch (argc) { - case 1: return run_tests(0); - case 2: return maybe_run_test(argc, argv); - case 3: return run_test_part(argv[1], argv[2]); - default: - LOGF("Too many arguments.\n"); - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} - - -static int maybe_run_test(int argc, char **argv) { - if (strcmp(argv[1], "--list") == 0) { - print_tests(stdout); - return 0; - } - - if (strcmp(argv[1], "ipc_helper_listen_before_write") == 0) { - return ipc_helper(0); - } - - if (strcmp(argv[1], "ipc_helper_listen_after_write") == 0) { - return ipc_helper(1); - } - - if (strcmp(argv[1], "ipc_send_recv_helper") == 0) { - return ipc_send_recv_helper(); - } - - if (strcmp(argv[1], "ipc_helper_tcp_connection") == 0) { - return ipc_helper_tcp_connection(); - } - - if (strcmp(argv[1], "ipc_helper_bind_twice") == 0) { - return ipc_helper_bind_twice(); - } - - if (strcmp(argv[1], "stdio_over_pipes_helper") == 0) { - return stdio_over_pipes_helper(); - } - - if (strcmp(argv[1], "spawn_helper1") == 0) { - return 1; - } - - if (strcmp(argv[1], "spawn_helper2") == 0) { - printf("hello world\n"); - return 1; - } - - if (strcmp(argv[1], "spawn_helper3") == 0) { - char buffer[256]; - ASSERT(buffer == fgets(buffer, sizeof(buffer) - 1, stdin)); - buffer[sizeof(buffer) - 1] = '\0'; - fputs(buffer, stdout); - return 1; - } - - if (strcmp(argv[1], "spawn_helper4") == 0) { - /* Never surrender, never return! */ - while (1) uv_sleep(10000); - } - - if (strcmp(argv[1], "spawn_helper5") == 0) { - const char out[] = "fourth stdio!\n"; -#ifdef _WIN32 - DWORD bytes; - WriteFile((HANDLE) _get_osfhandle(3), out, sizeof(out) - 1, &bytes, NULL); -#else - { - ssize_t r; - - do - r = write(3, out, sizeof(out) - 1); - while (r == -1 && errno == EINTR); - - fsync(3); - } -#endif - return 1; - } - - if (strcmp(argv[1], "spawn_helper6") == 0) { - int r; - - r = fprintf(stdout, "hello world\n"); - ASSERT(r > 0); - - r = fprintf(stderr, "hello errworld\n"); - ASSERT(r > 0); - - return 1; - } - - if (strcmp(argv[1], "spawn_helper7") == 0) { - int r; - char *test; - /* Test if the test value from the parent is still set */ - test = getenv("ENV_TEST"); - ASSERT(test != NULL); - - r = fprintf(stdout, "%s", test); - ASSERT(r > 0); - - return 1; - } - -#ifndef _WIN32 - if (strcmp(argv[1], "spawn_helper8") == 0) { - int fd; - ASSERT(sizeof(fd) == read(0, &fd, sizeof(fd))); - ASSERT(fd > 2); - ASSERT(-1 == write(fd, "x", 1)); - - return 1; - } -#endif /* !_WIN32 */ - - return run_test(argv[1], 0, 1); -} diff --git a/libuv/test/runner-unix.c b/libuv/test/runner-unix.c deleted file mode 100644 index 5da720f..0000000 --- a/libuv/test/runner-unix.c +++ /dev/null @@ -1,366 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "runner-unix.h" -#include "runner.h" - -#include -#include /* uintptr_t */ - -#include -#include /* readlink, usleep */ -#include /* strdup */ -#include -#include -#include -#include -#include -#include -#include - -#include -#include - - -/* Do platform-specific initialization. */ -int platform_init(int argc, char **argv) { - const char* tap; - - tap = getenv("UV_TAP_OUTPUT"); - tap_output = (tap != NULL && atoi(tap) > 0); - - /* Disable stdio output buffering. */ - setvbuf(stdout, NULL, _IONBF, 0); - setvbuf(stderr, NULL, _IONBF, 0); - signal(SIGPIPE, SIG_IGN); - - if (realpath(argv[0], executable_path) == NULL) { - perror("realpath"); - return -1; - } - - return 0; -} - - -/* Invoke "argv[0] test-name [test-part]". Store process info in *p. */ -/* Make sure that all stdio output of the processes is buffered up. */ -int process_start(char* name, char* part, process_info_t* p, int is_helper) { - FILE* stdout_file; - const char* arg; - char* args[16]; - int n; - pid_t pid; - - stdout_file = tmpfile(); - if (!stdout_file) { - perror("tmpfile"); - return -1; - } - - p->terminated = 0; - p->status = 0; - - pid = fork(); - - if (pid < 0) { - perror("fork"); - return -1; - } - - if (pid == 0) { - /* child */ - arg = getenv("UV_USE_VALGRIND"); - n = 0; - - /* Disable valgrind for helpers, it complains about helpers leaking memory. - * They're killed after the test and as such never get a chance to clean up. - */ - if (is_helper == 0 && arg != NULL && atoi(arg) != 0) { - args[n++] = "valgrind"; - args[n++] = "--quiet"; - args[n++] = "--leak-check=full"; - args[n++] = "--show-reachable=yes"; - args[n++] = "--error-exitcode=125"; - } - - args[n++] = executable_path; - args[n++] = name; - args[n++] = part; - args[n++] = NULL; - - dup2(fileno(stdout_file), STDOUT_FILENO); - dup2(fileno(stdout_file), STDERR_FILENO); - execvp(args[0], args); - perror("execvp()"); - _exit(127); - } - - /* parent */ - p->pid = pid; - p->name = strdup(name); - p->stdout_file = stdout_file; - - return 0; -} - - -typedef struct { - int pipe[2]; - process_info_t* vec; - int n; -} dowait_args; - - -/* This function is run inside a pthread. We do this so that we can possibly - * timeout. - */ -static void* dowait(void* data) { - dowait_args* args = data; - - int i, r; - process_info_t* p; - - for (i = 0; i < args->n; i++) { - p = (process_info_t*)(args->vec + i * sizeof(process_info_t)); - if (p->terminated) continue; - r = waitpid(p->pid, &p->status, 0); - if (r < 0) { - perror("waitpid"); - return NULL; - } - p->terminated = 1; - } - - if (args->pipe[1] >= 0) { - /* Write a character to the main thread to notify it about this. */ - ssize_t r; - - do - r = write(args->pipe[1], "", 1); - while (r == -1 && errno == EINTR); - } - - return NULL; -} - - -/* Wait for all `n` processes in `vec` to terminate. */ -/* Time out after `timeout` msec, or never if timeout == -1 */ -/* Return 0 if all processes are terminated, -1 on error, -2 on timeout. */ -int process_wait(process_info_t* vec, int n, int timeout) { - int i; - int r; - int retval; - process_info_t* p; - dowait_args args; - pthread_t tid; - struct timeval tv; - fd_set fds; - - args.vec = vec; - args.n = n; - args.pipe[0] = -1; - args.pipe[1] = -1; - - /* The simple case is where there is no timeout */ - if (timeout == -1) { - dowait(&args); - return 0; - } - - /* Hard case. Do the wait with a timeout. - * - * Assumption: we are the only ones making this call right now. Otherwise - * we'd need to lock vec. - */ - - r = pipe((int*)&(args.pipe)); - if (r) { - perror("pipe()"); - return -1; - } - - r = pthread_create(&tid, NULL, dowait, &args); - if (r) { - perror("pthread_create()"); - retval = -1; - goto terminate; - } - - tv.tv_sec = timeout / 1000; - tv.tv_usec = 0; - - FD_ZERO(&fds); - FD_SET(args.pipe[0], &fds); - - r = select(args.pipe[0] + 1, &fds, NULL, NULL, &tv); - - if (r == -1) { - perror("select()"); - retval = -1; - - } else if (r) { - /* The thread completed successfully. */ - retval = 0; - - } else { - /* Timeout. Kill all the children. */ - for (i = 0; i < n; i++) { - p = (process_info_t*)(vec + i * sizeof(process_info_t)); - kill(p->pid, SIGTERM); - } - retval = -2; - - /* Wait for thread to finish. */ - r = pthread_join(tid, NULL); - if (r) { - perror("pthread_join"); - retval = -1; - } - } - -terminate: - close(args.pipe[0]); - close(args.pipe[1]); - return retval; -} - - -/* Returns the number of bytes in the stdio output buffer for process `p`. */ -long int process_output_size(process_info_t *p) { - /* Size of the p->stdout_file */ - struct stat buf; - - int r = fstat(fileno(p->stdout_file), &buf); - if (r < 0) { - return -1; - } - - return (long)buf.st_size; -} - - -/* Copy the contents of the stdio output buffer to `fd`. */ -int process_copy_output(process_info_t *p, int fd) { - ssize_t nwritten; - char buf[1024]; - int r; - - r = fseek(p->stdout_file, 0, SEEK_SET); - if (r < 0) { - perror("fseek"); - return -1; - } - - /* TODO: what if the line is longer than buf */ - while (fgets(buf, sizeof(buf), p->stdout_file) != NULL) { - /* TODO: what if write doesn't write the whole buffer... */ - nwritten = 0; - - if (tap_output) - nwritten += write(fd, "#", 1); - - nwritten += write(fd, buf, strlen(buf)); - - if (nwritten < 0) { - perror("write"); - return -1; - } - } - - if (ferror(p->stdout_file)) { - perror("read"); - return -1; - } - - return 0; -} - - -/* Copy the last line of the stdio output buffer to `buffer` */ -int process_read_last_line(process_info_t *p, - char* buffer, - size_t buffer_len) { - char* ptr; - - int r = fseek(p->stdout_file, 0, SEEK_SET); - if (r < 0) { - perror("fseek"); - return -1; - } - - buffer[0] = '\0'; - - while (fgets(buffer, buffer_len, p->stdout_file) != NULL) { - for (ptr = buffer; *ptr && *ptr != '\r' && *ptr != '\n'; ptr++); - *ptr = '\0'; - } - - if (ferror(p->stdout_file)) { - perror("read"); - buffer[0] = '\0'; - return -1; - } - return 0; -} - - -/* Return the name that was specified when `p` was started by process_start */ -char* process_get_name(process_info_t *p) { - return p->name; -} - - -/* Terminate process `p`. */ -int process_terminate(process_info_t *p) { - return kill(p->pid, SIGTERM); -} - - -/* Return the exit code of process p. */ -/* On error, return -1. */ -int process_reap(process_info_t *p) { - if (WIFEXITED(p->status)) { - return WEXITSTATUS(p->status); - } else { - return p->status; /* ? */ - } -} - - -/* Clean up after terminating process `p` (e.g. free the output buffer etc.). */ -void process_cleanup(process_info_t *p) { - fclose(p->stdout_file); - free(p->name); -} - - -/* Move the console cursor one line up and back to the first column. */ -void rewind_cursor(void) { - fprintf(stderr, "\033[2K\r"); -} - - -/* Pause the calling thread for a number of milliseconds. */ -void uv_sleep(int msec) { - usleep(msec * 1000); -} diff --git a/libuv/test/runner-unix.h b/libuv/test/runner-unix.h deleted file mode 100644 index e21847f..0000000 --- a/libuv/test/runner-unix.h +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef TEST_RUNNER_UNIX_H -#define TEST_RUNNER_UNIX_H - -#include -#include /* FILE */ - -typedef struct { - FILE* stdout_file; - pid_t pid; - char* name; - int status; - int terminated; -} process_info_t; - -#endif /* TEST_RUNNER_UNIX_H */ diff --git a/libuv/test/runner-win.c b/libuv/test/runner-win.c deleted file mode 100644 index 97ef759..0000000 --- a/libuv/test/runner-win.c +++ /dev/null @@ -1,371 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#if !defined(__MINGW32__) -# include -#endif - - -#include "task.h" -#include "runner.h" - - -/* - * Define the stuff that MinGW doesn't have - */ -#ifndef GetFileSizeEx - WINBASEAPI BOOL WINAPI GetFileSizeEx(HANDLE hFile, - PLARGE_INTEGER lpFileSize); -#endif - - -/* Do platform-specific initialization. */ -int platform_init(int argc, char **argv) { - const char* tap; - - tap = getenv("UV_TAP_OUTPUT"); - tap_output = (tap != NULL && atoi(tap) > 0); - - /* Disable the "application crashed" popup. */ - SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | - SEM_NOOPENFILEERRORBOX); -#if !defined(__MINGW32__) - _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG); - _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG); -#endif - - _setmode(0, _O_BINARY); - _setmode(1, _O_BINARY); - _setmode(2, _O_BINARY); - - /* Disable stdio output buffering. */ - setvbuf(stdout, NULL, _IONBF, 0); - setvbuf(stderr, NULL, _IONBF, 0); - - strcpy(executable_path, argv[0]); - - return 0; -} - - -int process_start(char *name, char *part, process_info_t *p, int is_helper) { - HANDLE file = INVALID_HANDLE_VALUE; - HANDLE nul = INVALID_HANDLE_VALUE; - WCHAR path[MAX_PATH], filename[MAX_PATH]; - WCHAR image[MAX_PATH + 1]; - WCHAR args[MAX_PATH * 2]; - STARTUPINFOW si; - PROCESS_INFORMATION pi; - DWORD result; - - if (GetTempPathW(sizeof(path) / sizeof(WCHAR), (WCHAR*)&path) == 0) - goto error; - if (GetTempFileNameW((WCHAR*)&path, L"uv", 0, (WCHAR*)&filename) == 0) - goto error; - - file = CreateFileW((WCHAR*)filename, - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, - NULL); - if (file == INVALID_HANDLE_VALUE) - goto error; - - if (!SetHandleInformation(file, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) - goto error; - - nul = CreateFileA("nul", - GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - if (nul == INVALID_HANDLE_VALUE) - goto error; - - if (!SetHandleInformation(nul, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) - goto error; - - result = GetModuleFileNameW(NULL, - (WCHAR*) &image, - sizeof(image) / sizeof(WCHAR)); - if (result == 0 || result == sizeof(image)) - goto error; - - if (part) { - if (_snwprintf((WCHAR*)args, - sizeof(args) / sizeof(WCHAR), - L"\"%s\" %S %S", - image, - name, - part) < 0) { - goto error; - } - } else { - if (_snwprintf((WCHAR*)args, - sizeof(args) / sizeof(WCHAR), - L"\"%s\" %S", - image, - name) < 0) { - goto error; - } - } - - memset((void*)&si, 0, sizeof(si)); - si.cb = sizeof(si); - si.dwFlags = STARTF_USESTDHANDLES; - si.hStdInput = nul; - si.hStdOutput = file; - si.hStdError = file; - - if (!CreateProcessW(image, args, NULL, NULL, TRUE, - 0, NULL, NULL, &si, &pi)) - goto error; - - CloseHandle(pi.hThread); - - SetHandleInformation(nul, HANDLE_FLAG_INHERIT, 0); - SetHandleInformation(file, HANDLE_FLAG_INHERIT, 0); - - p->stdio_in = nul; - p->stdio_out = file; - p->process = pi.hProcess; - p->name = part; - - return 0; - -error: - if (file != INVALID_HANDLE_VALUE) - CloseHandle(file); - if (nul != INVALID_HANDLE_VALUE) - CloseHandle(nul); - - return -1; -} - - -/* Timeout is is msecs. Set timeout < 0 to never time out. */ -/* Returns 0 when all processes are terminated, -2 on timeout. */ -int process_wait(process_info_t *vec, int n, int timeout) { - int i; - HANDLE handles[MAXIMUM_WAIT_OBJECTS]; - DWORD timeout_api, result; - - /* If there's nothing to wait for, return immediately. */ - if (n == 0) - return 0; - - ASSERT(n <= MAXIMUM_WAIT_OBJECTS); - - for (i = 0; i < n; i++) - handles[i] = vec[i].process; - - if (timeout >= 0) { - timeout_api = (DWORD)timeout; - } else { - timeout_api = INFINITE; - } - - result = WaitForMultipleObjects(n, handles, TRUE, timeout_api); - - if (result >= WAIT_OBJECT_0 && result < WAIT_OBJECT_0 + n) { - /* All processes are terminated. */ - return 0; - } - if (result == WAIT_TIMEOUT) { - return -2; - } - return -1; -} - - -long int process_output_size(process_info_t *p) { - LARGE_INTEGER size; - if (!GetFileSizeEx(p->stdio_out, &size)) - return -1; - return (long int)size.QuadPart; -} - - -int process_copy_output(process_info_t *p, int fd) { - DWORD read; - char buf[1024]; - char *line, *start; - - if (SetFilePointer(p->stdio_out, - 0, - 0, - FILE_BEGIN) == INVALID_SET_FILE_POINTER) { - return -1; - } - - if (tap_output) - write(fd, "#", 1); - - while (ReadFile(p->stdio_out, (void*)&buf, sizeof(buf), &read, NULL) && - read > 0) { - if (tap_output) { - start = buf; - - while ((line = strchr(start, '\n')) != NULL) { - write(fd, start, line - start + 1); - write(fd, "#", 1); - start = line + 1; - } - - if (start < buf + read) - write(fd, start, buf + read - start); - } else { - write(fd, buf, read); - } - } - - if (tap_output) - write(fd, "\n", 1); - - if (GetLastError() != ERROR_HANDLE_EOF) - return -1; - - return 0; -} - - -int process_read_last_line(process_info_t *p, - char * buffer, - size_t buffer_len) { - DWORD size; - DWORD read; - DWORD start; - OVERLAPPED overlapped; - - ASSERT(buffer_len > 0); - - size = GetFileSize(p->stdio_out, NULL); - if (size == INVALID_FILE_SIZE) - return -1; - - if (size == 0) { - buffer[0] = '\0'; - return 1; - } - - memset(&overlapped, 0, sizeof overlapped); - if (size >= buffer_len) - overlapped.Offset = size - buffer_len - 1; - - if (!ReadFile(p->stdio_out, buffer, buffer_len - 1, &read, &overlapped)) - return -1; - - for (start = read - 1; start >= 0; start--) { - if (buffer[start] == '\n' || buffer[start] == '\r') - break; - } - - if (start > 0) - memmove(buffer, buffer + start, read - start); - - buffer[read - start] = '\0'; - - return 0; -} - - -char* process_get_name(process_info_t *p) { - return p->name; -} - - -int process_terminate(process_info_t *p) { - if (!TerminateProcess(p->process, 1)) - return -1; - return 0; -} - - -int process_reap(process_info_t *p) { - DWORD exitCode; - if (!GetExitCodeProcess(p->process, &exitCode)) - return -1; - return (int)exitCode; -} - - -void process_cleanup(process_info_t *p) { - CloseHandle(p->process); - CloseHandle(p->stdio_in); - CloseHandle(p->stdio_out); -} - - -static int clear_line() { - HANDLE handle; - CONSOLE_SCREEN_BUFFER_INFO info; - COORD coord; - DWORD written; - - handle = (HANDLE)_get_osfhandle(fileno(stderr)); - if (handle == INVALID_HANDLE_VALUE) - return -1; - - if (!GetConsoleScreenBufferInfo(handle, &info)) - return -1; - - coord = info.dwCursorPosition; - if (coord.Y <= 0) - return -1; - - coord.X = 0; - - if (!SetConsoleCursorPosition(handle, coord)) - return -1; - - if (!FillConsoleOutputCharacterW(handle, - 0x20, - info.dwSize.X, - coord, - &written)) { - return -1; - } - - return 0; -} - - -void rewind_cursor() { - if (clear_line() == -1) { - /* If clear_line fails (stdout is not a console), print a newline. */ - fprintf(stderr, "\n"); - } -} - - -/* Pause the calling thread for a number of milliseconds. */ -void uv_sleep(int msec) { - Sleep(msec); -} diff --git a/libuv/test/runner-win.h b/libuv/test/runner-win.h deleted file mode 100644 index c94b89b..0000000 --- a/libuv/test/runner-win.h +++ /dev/null @@ -1,43 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* Don't complain about _snprintf being insecure. */ -#define _CRT_SECURE_NO_WARNINGS - -/* Don't complain about write(), fileno() etc. being deprecated. */ -#pragma warning(disable : 4996) - - -#include -#include -#include - - -/* Windows has no snprintf, only _snprintf. */ -#define snprintf _snprintf - - -typedef struct { - HANDLE process; - HANDLE stdio_in; - HANDLE stdio_out; - char *name; -} process_info_t; diff --git a/libuv/test/runner.c b/libuv/test/runner.c deleted file mode 100644 index e896d43..0000000 --- a/libuv/test/runner.c +++ /dev/null @@ -1,454 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include - -#include "runner.h" -#include "task.h" -#include "uv.h" - -char executable_path[sizeof(executable_path)]; - -int tap_output = 0; - - -static void log_progress(int total, - int passed, - int failed, - int todos, - int skipped, - const char* name) { - int progress; - - if (total == 0) - total = 1; - - progress = 100 * (passed + failed + skipped + todos) / total; - LOGF("[%% %3d|+ %3d|- %3d|T %3d|S %3d]: %s", - progress, - passed, - failed, - todos, - skipped, - name); -} - - -const char* fmt(double d) { - static char buf[1024]; - static char* p; - uint64_t v; - - if (p == NULL) - p = buf; - - p += 31; - - if (p >= buf + sizeof(buf)) - return ""; - - v = (uint64_t) d; - -#if 0 /* works but we don't care about fractional precision */ - if (d - v >= 0.01) { - *--p = '0' + (uint64_t) (d * 100) % 10; - *--p = '0' + (uint64_t) (d * 10) % 10; - *--p = '.'; - } -#endif - - if (v == 0) - *--p = '0'; - - while (v) { - if (v) *--p = '0' + (v % 10), v /= 10; - if (v) *--p = '0' + (v % 10), v /= 10; - if (v) *--p = '0' + (v % 10), v /= 10; - if (v) *--p = ','; - } - - return p; -} - - -int run_tests(int benchmark_output) { - int total; - int passed; - int failed; - int todos; - int skipped; - int current; - int test_result; - task_entry_t* task; - - /* Count the number of tests. */ - total = 0; - for (task = TASKS; task->main; task++) { - if (!task->is_helper) { - total++; - } - } - - if (tap_output) { - LOGF("1..%d\n", total); - } - - /* Run all tests. */ - passed = 0; - failed = 0; - todos = 0; - skipped = 0; - current = 1; - for (task = TASKS; task->main; task++) { - if (task->is_helper) { - continue; - } - - if (!tap_output) - rewind_cursor(); - - if (!benchmark_output && !tap_output) { - log_progress(total, passed, failed, todos, skipped, task->task_name); - } - - test_result = run_test(task->task_name, benchmark_output, current); - switch (test_result) { - case TEST_OK: passed++; break; - case TEST_TODO: todos++; break; - case TEST_SKIP: skipped++; break; - default: failed++; - } - current++; - } - - if (!tap_output) - rewind_cursor(); - - if (!benchmark_output && !tap_output) { - log_progress(total, passed, failed, todos, skipped, "Done.\n"); - } - - return failed; -} - - -void log_tap_result(int test_count, - const char* test, - int status, - process_info_t* process) { - const char* result; - const char* directive; - char reason[1024]; - - switch (status) { - case TEST_OK: - result = "ok"; - directive = ""; - break; - case TEST_TODO: - result = "not ok"; - directive = " # TODO "; - break; - case TEST_SKIP: - result = "ok"; - directive = " # SKIP "; - break; - default: - result = "not ok"; - directive = ""; - } - - if ((status == TEST_SKIP || status == TEST_TODO) && - process_output_size(process) > 0) { - process_read_last_line(process, reason, sizeof reason); - } else { - reason[0] = '\0'; - } - - LOGF("%s %d - %s%s%s\n", result, test_count, test, directive, reason); -} - - -int run_test(const char* test, - int benchmark_output, - int test_count) { - char errmsg[1024] = "no error"; - process_info_t processes[1024]; - process_info_t *main_proc; - task_entry_t* task; - int process_count; - int result; - int status; - int i; - - status = 255; - main_proc = NULL; - process_count = 0; - -#ifndef _WIN32 - /* Clean up stale socket from previous run. */ - remove(TEST_PIPENAME); -#endif - - /* If it's a helper the user asks for, start it directly. */ - for (task = TASKS; task->main; task++) { - if (task->is_helper && strcmp(test, task->process_name) == 0) { - return task->main(); - } - } - - /* Start the helpers first. */ - for (task = TASKS; task->main; task++) { - if (strcmp(test, task->task_name) != 0) { - continue; - } - - /* Skip the test itself. */ - if (!task->is_helper) { - continue; - } - - if (process_start(task->task_name, - task->process_name, - &processes[process_count], - 1 /* is_helper */) == -1) { - snprintf(errmsg, - sizeof errmsg, - "Process `%s` failed to start.", - task->process_name); - goto out; - } - - process_count++; - } - - /* Give the helpers time to settle. Race-y, fix this. */ - uv_sleep(250); - - /* Now start the test itself. */ - for (task = TASKS; task->main; task++) { - if (strcmp(test, task->task_name) != 0) { - continue; - } - - if (task->is_helper) { - continue; - } - - if (process_start(task->task_name, - task->process_name, - &processes[process_count], - 0 /* !is_helper */) == -1) { - snprintf(errmsg, - sizeof errmsg, - "Process `%s` failed to start.", - task->process_name); - goto out; - } - - main_proc = &processes[process_count]; - process_count++; - break; - } - - if (main_proc == NULL) { - snprintf(errmsg, - sizeof errmsg, - "No test with that name: %s", - test); - goto out; - } - - result = process_wait(main_proc, 1, task->timeout); - if (result == -1) { - FATAL("process_wait failed"); - } else if (result == -2) { - /* Don't have to clean up the process, process_wait() has killed it. */ - snprintf(errmsg, - sizeof errmsg, - "timeout"); - goto out; - } - - status = process_reap(main_proc); - if (status != TEST_OK) { - snprintf(errmsg, - sizeof errmsg, - "exit code %d", - status); - goto out; - } - - if (benchmark_output) { - /* Give the helpers time to clean up their act. */ - uv_sleep(1000); - } - -out: - /* Reap running processes except the main process, it's already dead. */ - for (i = 0; i < process_count - 1; i++) { - process_terminate(&processes[i]); - } - - if (process_count > 0 && - process_wait(processes, process_count - 1, -1) < 0) { - FATAL("process_wait failed"); - } - - if (tap_output) - log_tap_result(test_count, test, status, &processes[i]); - - /* Show error and output from processes if the test failed. */ - if (status != 0 || task->show_output) { - if (tap_output) { - LOGF("#"); - } else if (status == TEST_TODO) { - LOGF("\n`%s` todo\n", test); - } else if (status == TEST_SKIP) { - LOGF("\n`%s` skipped\n", test); - } else if (status != 0) { - LOGF("\n`%s` failed: %s\n", test, errmsg); - } else { - LOGF("\n"); - } - - for (i = 0; i < process_count; i++) { - switch (process_output_size(&processes[i])) { - case -1: - LOGF("Output from process `%s`: (unavailable)\n", - process_get_name(&processes[i])); - break; - - case 0: - LOGF("Output from process `%s`: (no output)\n", - process_get_name(&processes[i])); - break; - - default: - LOGF("Output from process `%s`:\n", process_get_name(&processes[i])); - process_copy_output(&processes[i], fileno(stderr)); - break; - } - } - - if (!tap_output) { - LOG("=============================================================\n"); - } - - /* In benchmark mode show concise output from the main process. */ - } else if (benchmark_output) { - switch (process_output_size(main_proc)) { - case -1: - LOGF("%s: (unavailable)\n", test); - break; - - case 0: - LOGF("%s: (no output)\n", test); - break; - - default: - for (i = 0; i < process_count; i++) { - process_copy_output(&processes[i], fileno(stderr)); - } - break; - } - } - - /* Clean up all process handles. */ - for (i = 0; i < process_count; i++) { - process_cleanup(&processes[i]); - } - - return status; -} - - -/* Returns the status code of the task part - * or 255 if no matching task was not found. - */ -int run_test_part(const char* test, const char* part) { - task_entry_t* task; - int r; - - for (task = TASKS; task->main; task++) { - if (strcmp(test, task->task_name) == 0 && - strcmp(part, task->process_name) == 0) { - r = task->main(); - return r; - } - } - - LOGF("No test part with that name: %s:%s\n", test, part); - return 255; -} - - -static int compare_task(const void* va, const void* vb) { - const task_entry_t* a = va; - const task_entry_t* b = vb; - return strcmp(a->task_name, b->task_name); -} - - -static int find_helpers(const task_entry_t* task, - const task_entry_t** helpers) { - const task_entry_t* helper; - int n_helpers; - - for (n_helpers = 0, helper = TASKS; helper->main; helper++) { - if (helper->is_helper && strcmp(helper->task_name, task->task_name) == 0) { - *helpers++ = helper; - n_helpers++; - } - } - - return n_helpers; -} - - -void print_tests(FILE* stream) { - const task_entry_t* helpers[1024]; - const task_entry_t* task; - int n_helpers; - int n_tasks; - int i; - - for (n_tasks = 0, task = TASKS; task->main; n_tasks++, task++); - qsort(TASKS, n_tasks, sizeof(TASKS[0]), compare_task); - - for (task = TASKS; task->main; task++) { - if (task->is_helper) { - continue; - } - - n_helpers = find_helpers(task, helpers); - if (n_helpers) { - printf("%-25s (helpers:", task->task_name); - for (i = 0; i < n_helpers; i++) { - printf(" %s", helpers[i]->process_name); - } - printf(")\n"); - } else { - printf("%s\n", task->task_name); - } - } -} diff --git a/libuv/test/runner.h b/libuv/test/runner.h deleted file mode 100644 index 78f3c88..0000000 --- a/libuv/test/runner.h +++ /dev/null @@ -1,178 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef RUNNER_H_ -#define RUNNER_H_ - -#include /* PATH_MAX */ -#include /* FILE */ - - -/* - * The maximum number of processes (main + helpers) that a test / benchmark - * can have. - */ -#define MAX_PROCESSES 8 - - -/* - * Struct to store both tests and to define helper processes for tasks. - */ -typedef struct { - char *task_name; - char *process_name; - int (*main)(void); - int is_helper; - int show_output; - - /* - * The time in milliseconds after which a single test or benchmark times out. - */ - int timeout; -} task_entry_t, bench_entry_t; - - -/* - * Macros used by test-list.h and benchmark-list.h. - */ -#define TASK_LIST_START \ - task_entry_t TASKS[] = { - -#define TASK_LIST_END \ - { 0, 0, 0, 0, 0, 0 } \ - }; - -#define TEST_DECLARE(name) \ - int run_test_##name(void); - -#define TEST_ENTRY(name) \ - { #name, #name, &run_test_##name, 0, 0, 5000 }, - -#define TEST_ENTRY_CUSTOM(name, is_helper, show_output, timeout) \ - { #name, #name, &run_test_##name, is_helper, show_output, timeout }, - -#define BENCHMARK_DECLARE(name) \ - int run_benchmark_##name(void); - -#define BENCHMARK_ENTRY(name) \ - { #name, #name, &run_benchmark_##name, 0, 0, 60000 }, - -#define HELPER_DECLARE(name) \ - int run_helper_##name(void); - -#define HELPER_ENTRY(task_name, name) \ - { #task_name, #name, &run_helper_##name, 1, 0, 0 }, - -#define TEST_HELPER HELPER_ENTRY -#define BENCHMARK_HELPER HELPER_ENTRY - -#ifdef PATH_MAX -extern char executable_path[PATH_MAX]; -#else -extern char executable_path[4096]; -#endif - -/* - * Include platform-dependent definitions - */ -#ifdef _WIN32 -# include "runner-win.h" -#else -# include "runner-unix.h" -#endif - - -/* The array that is filled by test-list.h or benchmark-list.h */ -extern task_entry_t TASKS[]; - -/* - * Run all tests. - */ -int run_tests(int benchmark_output); - -/* - * Run a single test. Starts up any helpers. - */ -int run_test(const char* test, - int benchmark_output, - int test_count); - -/* - * Run a test part, i.e. the test or one of its helpers. - */ -int run_test_part(const char* test, const char* part); - - -/* - * Print tests in sorted order to `stream`. Used by `./run-tests --list`. - */ -void print_tests(FILE* stream); - - -/* - * Stuff that should be implemented by test-runner-.h - * All functions return 0 on success, -1 on failure, unless specified - * otherwise. - */ - -/* Do platform-specific initialization. */ -int platform_init(int argc, char** argv); - -/* Invoke "argv[0] test-name [test-part]". Store process info in *p. */ -/* Make sure that all stdio output of the processes is buffered up. */ -int process_start(char *name, char* part, process_info_t *p, int is_helper); - -/* Wait for all `n` processes in `vec` to terminate. */ -/* Time out after `timeout` msec, or never if timeout == -1 */ -/* Return 0 if all processes are terminated, -1 on error, -2 on timeout. */ -int process_wait(process_info_t *vec, int n, int timeout); - -/* Returns the number of bytes in the stdio output buffer for process `p`. */ -long int process_output_size(process_info_t *p); - -/* Copy the contents of the stdio output buffer to `fd`. */ -int process_copy_output(process_info_t *p, int fd); - -/* Copy the last line of the stdio output buffer to `buffer` */ -int process_read_last_line(process_info_t *p, - char * buffer, - size_t buffer_len); - -/* Return the name that was specified when `p` was started by process_start */ -char* process_get_name(process_info_t *p); - -/* Terminate process `p`. */ -int process_terminate(process_info_t *p); - -/* Return the exit code of process p. */ -/* On error, return -1. */ -int process_reap(process_info_t *p); - -/* Clean up after terminating process `p` (e.g. free the output buffer etc.). */ -void process_cleanup(process_info_t *p); - -/* Move the console cursor one line up and back to the first column. */ -void rewind_cursor(void); - -/* trigger output as tap */ -extern int tap_output; - -#endif /* RUNNER_H_ */ diff --git a/libuv/test/task.h b/libuv/test/task.h deleted file mode 100644 index 07584c5..0000000 --- a/libuv/test/task.h +++ /dev/null @@ -1,254 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef TASK_H_ -#define TASK_H_ - -#include "uv.h" - -#include -#include -#include - -#if defined(_MSC_VER) && _MSC_VER < 1600 -# include "stdint-msvc2008.h" -#else -# include -#endif - -#if !defined(_WIN32) -# include -# include /* setrlimit() */ -#endif - -#ifdef __clang__ -# pragma clang diagnostic ignored "-Wvariadic-macros" -# pragma clang diagnostic ignored "-Wc99-extensions" -#endif - -#define TEST_PORT 9123 -#define TEST_PORT_2 9124 - -#ifdef _WIN32 -# define TEST_PIPENAME "\\\\?\\pipe\\uv-test" -# define TEST_PIPENAME_2 "\\\\?\\pipe\\uv-test2" -#else -# define TEST_PIPENAME "/tmp/uv-test-sock" -# define TEST_PIPENAME_2 "/tmp/uv-test-sock2" -#endif - -#ifdef _WIN32 -# include -# ifndef S_IRUSR -# define S_IRUSR _S_IREAD -# endif -# ifndef S_IWUSR -# define S_IWUSR _S_IWRITE -# endif -#endif - -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) - -#define container_of(ptr, type, member) \ - ((type *) ((char *) (ptr) - offsetof(type, member))) - -typedef enum { - TCP = 0, - UDP, - PIPE -} stream_type; - -/* Log to stderr. */ -#define LOG(...) \ - do { \ - fprintf(stderr, "%s", __VA_ARGS__); \ - fflush(stderr); \ - } while (0) - -#define LOGF(...) \ - do { \ - fprintf(stderr, __VA_ARGS__); \ - fflush(stderr); \ - } while (0) - -/* Die with fatal error. */ -#define FATAL(msg) \ - do { \ - fprintf(stderr, \ - "Fatal error in %s on line %d: %s\n", \ - __FILE__, \ - __LINE__, \ - msg); \ - fflush(stderr); \ - abort(); \ - } while (0) - -/* Have our own assert, so we are sure it does not get optimized away in - * a release build. - */ -#define ASSERT(expr) \ - do { \ - if (!(expr)) { \ - fprintf(stderr, \ - "Assertion failed in %s on line %d: %s\n", \ - __FILE__, \ - __LINE__, \ - #expr); \ - abort(); \ - } \ - } while (0) - -/* This macro cleans up the main loop. This is used to avoid valgrind - * warnings about memory being "leaked" by the main event loop. - */ -#define MAKE_VALGRIND_HAPPY() \ - do { \ - close_loop(uv_default_loop()); \ - uv_loop_delete(uv_default_loop()); \ - } while (0) - -/* Just sugar for wrapping the main() for a task or helper. */ -#define TEST_IMPL(name) \ - int run_test_##name(void); \ - int run_test_##name(void) - -#define BENCHMARK_IMPL(name) \ - int run_benchmark_##name(void); \ - int run_benchmark_##name(void) - -#define HELPER_IMPL(name) \ - int run_helper_##name(void); \ - int run_helper_##name(void) - -/* Pause the calling thread for a number of milliseconds. */ -void uv_sleep(int msec); - -/* Format big numbers nicely. WARNING: leaks memory. */ -const char* fmt(double d); - -/* Reserved test exit codes. */ -enum test_status { - TEST_OK = 0, - TEST_TODO, - TEST_SKIP -}; - -#define RETURN_OK() \ - do { \ - return TEST_OK; \ - } while (0) - -#define RETURN_TODO(explanation) \ - do { \ - LOGF("%s\n", explanation); \ - return TEST_TODO; \ - } while (0) - -#define RETURN_SKIP(explanation) \ - do { \ - LOGF("%s\n", explanation); \ - return TEST_SKIP; \ - } while (0) - -#if !defined(_WIN32) - -# define TEST_FILE_LIMIT(num) \ - do { \ - struct rlimit lim; \ - lim.rlim_cur = (num); \ - lim.rlim_max = lim.rlim_cur; \ - if (setrlimit(RLIMIT_NOFILE, &lim)) \ - RETURN_SKIP("File descriptor limit too low."); \ - } while (0) - -#else /* defined(_WIN32) */ - -# define TEST_FILE_LIMIT(num) do {} while (0) - -#endif - - -#if defined _WIN32 && ! defined __GNUC__ - -#include - -/* Emulate snprintf() on Windows, _snprintf() doesn't zero-terminate the buffer - * on overflow... - */ -static int snprintf(char* buf, size_t len, const char* fmt, ...) { - va_list ap; - int n; - - va_start(ap, fmt); - n = _vsprintf_p(buf, len, fmt, ap); - va_end(ap); - - /* It's a sad fact of life that no one ever checks the return value of - * snprintf(). Zero-terminating the buffer hopefully reduces the risk - * of gaping security holes. - */ - if (n < 0) - if (len > 0) - buf[0] = '\0'; - - return n; -} - -#endif - -#if defined(__clang__) || \ - defined(__GNUC__) || \ - defined(__INTEL_COMPILER) || \ - defined(__SUNPRO_C) -# define UNUSED __attribute__((unused)) -#else -# define UNUSED -#endif - -/* Fully close a loop */ -static void close_walk_cb(uv_handle_t* handle, void* arg) { - if (!uv_is_closing(handle)) - uv_close(handle, NULL); -} - -UNUSED static void close_loop(uv_loop_t* loop) { - uv_walk(loop, close_walk_cb, NULL); - uv_run(loop, UV_RUN_DEFAULT); -} - -UNUSED static int can_ipv6(void) { - uv_interface_address_t* addr; - int supported; - int count; - int i; - - if (uv_interface_addresses(&addr, &count)) - return 1; /* Assume IPv6 support on failure. */ - - supported = 0; - for (i = 0; supported == 0 && i < count; i += 1) - supported = (AF_INET6 == addr[i].address.address6.sin6_family); - - uv_free_interface_addresses(addr, count); - return supported; -} - -#endif /* TASK_H_ */ diff --git a/libuv/test/test-active.c b/libuv/test/test-active.c deleted file mode 100644 index b17bd17..0000000 --- a/libuv/test/test-active.c +++ /dev/null @@ -1,84 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include - - -static int close_cb_called = 0; - - -static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); - close_cb_called++; -} - - -static void timer_cb(uv_timer_t* handle) { - ASSERT(0 && "timer_cb should not have been called"); -} - - -TEST_IMPL(active) { - int r; - uv_timer_t timer; - - r = uv_timer_init(uv_default_loop(), &timer); - ASSERT(r == 0); - - /* uv_is_active() and uv_is_closing() should always return either 0 or 1. */ - ASSERT(0 == uv_is_active((uv_handle_t*) &timer)); - ASSERT(0 == uv_is_closing((uv_handle_t*) &timer)); - - r = uv_timer_start(&timer, timer_cb, 1000, 0); - ASSERT(r == 0); - - ASSERT(1 == uv_is_active((uv_handle_t*) &timer)); - ASSERT(0 == uv_is_closing((uv_handle_t*) &timer)); - - r = uv_timer_stop(&timer); - ASSERT(r == 0); - - ASSERT(0 == uv_is_active((uv_handle_t*) &timer)); - ASSERT(0 == uv_is_closing((uv_handle_t*) &timer)); - - r = uv_timer_start(&timer, timer_cb, 1000, 0); - ASSERT(r == 0); - - ASSERT(1 == uv_is_active((uv_handle_t*) &timer)); - ASSERT(0 == uv_is_closing((uv_handle_t*) &timer)); - - uv_close((uv_handle_t*) &timer, close_cb); - - ASSERT(0 == uv_is_active((uv_handle_t*) &timer)); - ASSERT(1 == uv_is_closing((uv_handle_t*) &timer)); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-async-null-cb.c b/libuv/test/test-async-null-cb.c deleted file mode 100644 index 757944a..0000000 --- a/libuv/test/test-async-null-cb.c +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -static uv_async_t async_handle; -static uv_check_t check_handle; -static int check_cb_called; -static uv_thread_t thread; - - -static void thread_cb(void* dummy) { - (void) &dummy; - uv_async_send(&async_handle); -} - - -static void check_cb(uv_check_t* handle) { - ASSERT(check_cb_called == 0); - uv_close((uv_handle_t*) &async_handle, NULL); - uv_close((uv_handle_t*) &check_handle, NULL); - check_cb_called++; -} - - -TEST_IMPL(async_null_cb) { - ASSERT(0 == uv_async_init(uv_default_loop(), &async_handle, NULL)); - ASSERT(0 == uv_check_init(uv_default_loop(), &check_handle)); - ASSERT(0 == uv_check_start(&check_handle, check_cb)); - ASSERT(0 == uv_thread_create(&thread, thread_cb, NULL)); - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); - ASSERT(0 == uv_thread_join(&thread)); - ASSERT(1 == check_cb_called); - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-async.c b/libuv/test/test-async.c deleted file mode 100644 index 6f5351b..0000000 --- a/libuv/test/test-async.c +++ /dev/null @@ -1,134 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" -#include -#include - -static uv_thread_t thread; -static uv_mutex_t mutex; - -static uv_prepare_t prepare; -static uv_async_t async; - -static volatile int async_cb_called; -static int prepare_cb_called; -static int close_cb_called; - - -static void thread_cb(void *arg) { - int n; - int r; - - for (;;) { - uv_mutex_lock(&mutex); - n = async_cb_called; - uv_mutex_unlock(&mutex); - - if (n == 3) { - break; - } - - r = uv_async_send(&async); - ASSERT(r == 0); - - /* Work around a bug in Valgrind. - * - * Valgrind runs threads not in parallel but sequentially, i.e. one after - * the other. It also doesn't preempt them, instead it depends on threads - * yielding voluntarily by making a syscall. - * - * That never happens here: the pipe that is associated with the async - * handle is written to once but that's too early for Valgrind's scheduler - * to kick in. Afterwards, the thread busy-loops, starving the main thread. - * Therefore, we yield. - * - * This behavior has been observed with Valgrind 3.7.0 and 3.9.0. - */ - uv_sleep(0); - } -} - - -static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); - close_cb_called++; -} - - -static void async_cb(uv_async_t* handle) { - int n; - - ASSERT(handle == &async); - - uv_mutex_lock(&mutex); - n = ++async_cb_called; - uv_mutex_unlock(&mutex); - - if (n == 3) { - uv_close((uv_handle_t*)&async, close_cb); - uv_close((uv_handle_t*)&prepare, close_cb); - } -} - - -static void prepare_cb(uv_prepare_t* handle) { - int r; - - ASSERT(handle == &prepare); - - if (prepare_cb_called++) - return; - - r = uv_thread_create(&thread, thread_cb, NULL); - ASSERT(r == 0); - uv_mutex_unlock(&mutex); -} - - -TEST_IMPL(async) { - int r; - - r = uv_mutex_init(&mutex); - ASSERT(r == 0); - uv_mutex_lock(&mutex); - - r = uv_prepare_init(uv_default_loop(), &prepare); - ASSERT(r == 0); - r = uv_prepare_start(&prepare, prepare_cb); - ASSERT(r == 0); - - r = uv_async_init(uv_default_loop(), &async, async_cb); - ASSERT(r == 0); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(prepare_cb_called > 0); - ASSERT(async_cb_called == 3); - ASSERT(close_cb_called == 2); - - ASSERT(0 == uv_thread_join(&thread)); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-barrier.c b/libuv/test/test-barrier.c deleted file mode 100644 index dfd2dbd..0000000 --- a/libuv/test/test-barrier.c +++ /dev/null @@ -1,106 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include - -typedef struct { - uv_barrier_t barrier; - int delay; - volatile int posted; - int main_barrier_wait_rval; - int worker_barrier_wait_rval; -} worker_config; - - -static void worker(void* arg) { - worker_config* c = arg; - - if (c->delay) - uv_sleep(c->delay); - - c->worker_barrier_wait_rval = uv_barrier_wait(&c->barrier); -} - - -TEST_IMPL(barrier_1) { - uv_thread_t thread; - worker_config wc; - - memset(&wc, 0, sizeof(wc)); - - ASSERT(0 == uv_barrier_init(&wc.barrier, 2)); - ASSERT(0 == uv_thread_create(&thread, worker, &wc)); - - uv_sleep(100); - wc.main_barrier_wait_rval = uv_barrier_wait(&wc.barrier); - - ASSERT(0 == uv_thread_join(&thread)); - uv_barrier_destroy(&wc.barrier); - - ASSERT(1 == (wc.main_barrier_wait_rval ^ wc.worker_barrier_wait_rval)); - - return 0; -} - - -TEST_IMPL(barrier_2) { - uv_thread_t thread; - worker_config wc; - - memset(&wc, 0, sizeof(wc)); - wc.delay = 100; - - ASSERT(0 == uv_barrier_init(&wc.barrier, 2)); - ASSERT(0 == uv_thread_create(&thread, worker, &wc)); - - wc.main_barrier_wait_rval = uv_barrier_wait(&wc.barrier); - - ASSERT(0 == uv_thread_join(&thread)); - uv_barrier_destroy(&wc.barrier); - - ASSERT(1 == (wc.main_barrier_wait_rval ^ wc.worker_barrier_wait_rval)); - - return 0; -} - - -TEST_IMPL(barrier_3) { - uv_thread_t thread; - worker_config wc; - - memset(&wc, 0, sizeof(wc)); - - ASSERT(0 == uv_barrier_init(&wc.barrier, 2)); - ASSERT(0 == uv_thread_create(&thread, worker, &wc)); - - wc.main_barrier_wait_rval = uv_barrier_wait(&wc.barrier); - - ASSERT(0 == uv_thread_join(&thread)); - uv_barrier_destroy(&wc.barrier); - - ASSERT(1 == (wc.main_barrier_wait_rval ^ wc.worker_barrier_wait_rval)); - - return 0; -} diff --git a/libuv/test/test-callback-order.c b/libuv/test/test-callback-order.c deleted file mode 100644 index 8bc2c4f..0000000 --- a/libuv/test/test-callback-order.c +++ /dev/null @@ -1,77 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -static int idle_cb_called; -static int timer_cb_called; - -static uv_idle_t idle_handle; -static uv_timer_t timer_handle; - - -/* idle_cb should run before timer_cb */ -static void idle_cb(uv_idle_t* handle) { - ASSERT(idle_cb_called == 0); - ASSERT(timer_cb_called == 0); - uv_idle_stop(handle); - idle_cb_called++; -} - - -static void timer_cb(uv_timer_t* handle) { - ASSERT(idle_cb_called == 1); - ASSERT(timer_cb_called == 0); - uv_timer_stop(handle); - timer_cb_called++; -} - - -static void next_tick(uv_idle_t* handle) { - uv_loop_t* loop = handle->loop; - uv_idle_stop(handle); - uv_idle_init(loop, &idle_handle); - uv_idle_start(&idle_handle, idle_cb); - uv_timer_init(loop, &timer_handle); - uv_timer_start(&timer_handle, timer_cb, 0, 0); -} - - -TEST_IMPL(callback_order) { - uv_loop_t* loop; - uv_idle_t idle; - - loop = uv_default_loop(); - uv_idle_init(loop, &idle); - uv_idle_start(&idle, next_tick); - - ASSERT(idle_cb_called == 0); - ASSERT(timer_cb_called == 0); - - uv_run(loop, UV_RUN_DEFAULT); - - ASSERT(idle_cb_called == 1); - ASSERT(timer_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-callback-stack.c b/libuv/test/test-callback-stack.c deleted file mode 100644 index 8855c08..0000000 --- a/libuv/test/test-callback-stack.c +++ /dev/null @@ -1,205 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* - * TODO: Add explanation of why we want on_close to be called from fresh - * stack. - */ - -#include "uv.h" -#include "task.h" - - -static const char MESSAGE[] = "Failure is for the weak. Everyone dies alone."; - -static uv_tcp_t client; -static uv_timer_t timer; -static uv_connect_t connect_req; -static uv_write_t write_req; -static uv_shutdown_t shutdown_req; - -static int nested = 0; -static int close_cb_called = 0; -static int connect_cb_called = 0; -static int write_cb_called = 0; -static int timer_cb_called = 0; -static int bytes_received = 0; -static int shutdown_cb_called = 0; - - -static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) { - buf->len = size; - buf->base = malloc(size); - ASSERT(buf->base != NULL); -} - - -static void close_cb(uv_handle_t* handle) { - ASSERT(nested == 0 && "close_cb must be called from a fresh stack"); - - close_cb_called++; -} - - -static void shutdown_cb(uv_shutdown_t* req, int status) { - ASSERT(status == 0); - ASSERT(nested == 0 && "shutdown_cb must be called from a fresh stack"); - - shutdown_cb_called++; -} - - -static void read_cb(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { - ASSERT(nested == 0 && "read_cb must be called from a fresh stack"); - - printf("Read. nread == %d\n", (int)nread); - free(buf->base); - - if (nread == 0) { - return; - - } else if (nread < 0) { - ASSERT(nread == UV_EOF); - - nested++; - uv_close((uv_handle_t*)tcp, close_cb); - nested--; - - return; - } - - bytes_received += nread; - - /* We call shutdown here because when bytes_received == sizeof MESSAGE */ - /* there will be no more data sent nor received, so here it would be */ - /* possible for a backend to to call shutdown_cb immediately and *not* */ - /* from a fresh stack. */ - if (bytes_received == sizeof MESSAGE) { - nested++; - - puts("Shutdown"); - - if (uv_shutdown(&shutdown_req, (uv_stream_t*)tcp, shutdown_cb)) { - FATAL("uv_shutdown failed"); - } - nested--; - } -} - - -static void timer_cb(uv_timer_t* handle) { - ASSERT(handle == &timer); - ASSERT(nested == 0 && "timer_cb must be called from a fresh stack"); - - puts("Timeout complete. Now read data..."); - - nested++; - if (uv_read_start((uv_stream_t*)&client, alloc_cb, read_cb)) { - FATAL("uv_read_start failed"); - } - nested--; - - timer_cb_called++; - - uv_close((uv_handle_t*)handle, close_cb); -} - - -static void write_cb(uv_write_t* req, int status) { - int r; - - ASSERT(status == 0); - ASSERT(nested == 0 && "write_cb must be called from a fresh stack"); - - puts("Data written. 500ms timeout..."); - - /* After the data has been sent, we're going to wait for a while, then */ - /* start reading. This makes us certain that the message has been echoed */ - /* back to our receive buffer when we start reading. This maximizes the */ - /* temptation for the backend to use dirty stack for calling read_cb. */ - nested++; - r = uv_timer_init(uv_default_loop(), &timer); - ASSERT(r == 0); - r = uv_timer_start(&timer, timer_cb, 500, 0); - ASSERT(r == 0); - nested--; - - write_cb_called++; -} - - -static void connect_cb(uv_connect_t* req, int status) { - uv_buf_t buf; - - puts("Connected. Write some data to echo server..."); - - ASSERT(status == 0); - ASSERT(nested == 0 && "connect_cb must be called from a fresh stack"); - - nested++; - - buf.base = (char*) &MESSAGE; - buf.len = sizeof MESSAGE; - - if (uv_write(&write_req, (uv_stream_t*)req->handle, &buf, 1, write_cb)) { - FATAL("uv_write failed"); - } - - nested--; - - connect_cb_called++; -} - - -TEST_IMPL(callback_stack) { - struct sockaddr_in addr; - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - - if (uv_tcp_init(uv_default_loop(), &client)) { - FATAL("uv_tcp_init failed"); - } - - puts("Connecting..."); - - nested++; - - if (uv_tcp_connect(&connect_req, - &client, - (const struct sockaddr*) &addr, - connect_cb)) { - FATAL("uv_tcp_connect failed"); - } - nested--; - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(nested == 0); - ASSERT(connect_cb_called == 1 && "connect_cb must be called exactly once"); - ASSERT(write_cb_called == 1 && "write_cb must be called exactly once"); - ASSERT(timer_cb_called == 1 && "timer_cb must be called exactly once"); - ASSERT(bytes_received == sizeof MESSAGE); - ASSERT(shutdown_cb_called == 1 && "shutdown_cb must be called exactly once"); - ASSERT(close_cb_called == 2 && "close_cb must be called exactly twice"); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-close-fd.c b/libuv/test/test-close-fd.c deleted file mode 100644 index 93a7bd7..0000000 --- a/libuv/test/test-close-fd.c +++ /dev/null @@ -1,76 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#if !defined(_WIN32) - -#include "uv.h" -#include "task.h" -#include -#include - -static unsigned int read_cb_called; - -static void alloc_cb(uv_handle_t *handle, size_t size, uv_buf_t *buf) { - static char slab[1]; - buf->base = slab; - buf->len = sizeof(slab); -} - -static void read_cb(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf) { - switch (++read_cb_called) { - case 1: - ASSERT(nread == 1); - uv_read_stop(handle); - break; - case 2: - ASSERT(nread == UV_EOF); - uv_close((uv_handle_t *) handle, NULL); - break; - default: - ASSERT(!"read_cb_called > 2"); - } -} - -TEST_IMPL(close_fd) { - uv_pipe_t pipe_handle; - int fd[2]; - - ASSERT(0 == pipe(fd)); - ASSERT(0 == uv_pipe_init(uv_default_loop(), &pipe_handle, 0)); - ASSERT(0 == uv_pipe_open(&pipe_handle, fd[0])); - fd[0] = -1; /* uv_pipe_open() takes ownership of the file descriptor. */ - ASSERT(1 == write(fd[1], "", 1)); - ASSERT(0 == close(fd[1])); - fd[1] = -1; - ASSERT(0 == uv_read_start((uv_stream_t *) &pipe_handle, alloc_cb, read_cb)); - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); - ASSERT(1 == read_cb_called); - ASSERT(0 == uv_is_active((const uv_handle_t *) &pipe_handle)); - ASSERT(0 == uv_read_start((uv_stream_t *) &pipe_handle, alloc_cb, read_cb)); - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); - ASSERT(2 == read_cb_called); - ASSERT(0 != uv_is_closing((const uv_handle_t *) &pipe_handle)); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -#endif /* !defined(_WIN32) */ diff --git a/libuv/test/test-close-order.c b/libuv/test/test-close-order.c deleted file mode 100644 index 2b24f6d..0000000 --- a/libuv/test/test-close-order.c +++ /dev/null @@ -1,80 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -static int check_cb_called; -static int timer_cb_called; -static int close_cb_called; - -static uv_check_t check_handle; -static uv_timer_t timer_handle1; -static uv_timer_t timer_handle2; - - -static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); - close_cb_called++; -} - - -/* check_cb should run before any close_cb */ -static void check_cb(uv_check_t* handle) { - ASSERT(check_cb_called == 0); - ASSERT(timer_cb_called == 1); - ASSERT(close_cb_called == 0); - uv_close((uv_handle_t*) handle, close_cb); - uv_close((uv_handle_t*) &timer_handle2, close_cb); - check_cb_called++; -} - - -static void timer_cb(uv_timer_t* handle) { - uv_close((uv_handle_t*) handle, close_cb); - timer_cb_called++; -} - - -TEST_IMPL(close_order) { - uv_loop_t* loop; - loop = uv_default_loop(); - - uv_check_init(loop, &check_handle); - uv_check_start(&check_handle, check_cb); - uv_timer_init(loop, &timer_handle1); - uv_timer_start(&timer_handle1, timer_cb, 0, 0); - uv_timer_init(loop, &timer_handle2); - uv_timer_start(&timer_handle2, timer_cb, 100000, 0); - - ASSERT(check_cb_called == 0); - ASSERT(close_cb_called == 0); - ASSERT(timer_cb_called == 0); - - uv_run(loop, UV_RUN_DEFAULT); - - ASSERT(check_cb_called == 1); - ASSERT(close_cb_called == 3); - ASSERT(timer_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-condvar.c b/libuv/test/test-condvar.c deleted file mode 100644 index dbacdba..0000000 --- a/libuv/test/test-condvar.c +++ /dev/null @@ -1,173 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include - -typedef struct { - uv_mutex_t mutex; - uv_cond_t cond; - int delay; - int use_broadcast; - volatile int posted; -} worker_config; - - -static void worker(void* arg) { - worker_config* c = arg; - - if (c->delay) - uv_sleep(c->delay); - - uv_mutex_lock(&c->mutex); - ASSERT(c->posted == 0); - c->posted = 1; - if (c->use_broadcast) - uv_cond_broadcast(&c->cond); - else - uv_cond_signal(&c->cond); - uv_mutex_unlock(&c->mutex); -} - - -TEST_IMPL(condvar_1) { - uv_thread_t thread; - worker_config wc; - - memset(&wc, 0, sizeof(wc)); - - ASSERT(0 == uv_cond_init(&wc.cond)); - ASSERT(0 == uv_mutex_init(&wc.mutex)); - ASSERT(0 == uv_thread_create(&thread, worker, &wc)); - - uv_mutex_lock(&wc.mutex); - uv_sleep(100); - uv_cond_wait(&wc.cond, &wc.mutex); - ASSERT(wc.posted == 1); - uv_mutex_unlock(&wc.mutex); - - ASSERT(0 == uv_thread_join(&thread)); - uv_mutex_destroy(&wc.mutex); - uv_cond_destroy(&wc.cond); - - return 0; -} - - -TEST_IMPL(condvar_2) { - uv_thread_t thread; - worker_config wc; - - memset(&wc, 0, sizeof(wc)); - wc.delay = 100; - - ASSERT(0 == uv_cond_init(&wc.cond)); - ASSERT(0 == uv_mutex_init(&wc.mutex)); - ASSERT(0 == uv_thread_create(&thread, worker, &wc)); - - uv_mutex_lock(&wc.mutex); - uv_cond_wait(&wc.cond, &wc.mutex); - uv_mutex_unlock(&wc.mutex); - - ASSERT(0 == uv_thread_join(&thread)); - uv_mutex_destroy(&wc.mutex); - uv_cond_destroy(&wc.cond); - - return 0; -} - - -TEST_IMPL(condvar_3) { - uv_thread_t thread; - worker_config wc; - int r; - - memset(&wc, 0, sizeof(wc)); - wc.delay = 100; - - ASSERT(0 == uv_cond_init(&wc.cond)); - ASSERT(0 == uv_mutex_init(&wc.mutex)); - ASSERT(0 == uv_thread_create(&thread, worker, &wc)); - - uv_mutex_lock(&wc.mutex); - r = uv_cond_timedwait(&wc.cond, &wc.mutex, (uint64_t)(50 * 1e6)); - ASSERT(r == UV_ETIMEDOUT); - uv_mutex_unlock(&wc.mutex); - - ASSERT(0 == uv_thread_join(&thread)); - uv_mutex_destroy(&wc.mutex); - uv_cond_destroy(&wc.cond); - - return 0; -} - - -TEST_IMPL(condvar_4) { - uv_thread_t thread; - worker_config wc; - int r; - - memset(&wc, 0, sizeof(wc)); - wc.delay = 100; - - ASSERT(0 == uv_cond_init(&wc.cond)); - ASSERT(0 == uv_mutex_init(&wc.mutex)); - ASSERT(0 == uv_thread_create(&thread, worker, &wc)); - - uv_mutex_lock(&wc.mutex); - r = uv_cond_timedwait(&wc.cond, &wc.mutex, (uint64_t)(150 * 1e6)); - ASSERT(r == 0); - uv_mutex_unlock(&wc.mutex); - - ASSERT(0 == uv_thread_join(&thread)); - uv_mutex_destroy(&wc.mutex); - uv_cond_destroy(&wc.cond); - - return 0; -} - - -TEST_IMPL(condvar_5) { - uv_thread_t thread; - worker_config wc; - - memset(&wc, 0, sizeof(wc)); - wc.use_broadcast = 1; - - ASSERT(0 == uv_cond_init(&wc.cond)); - ASSERT(0 == uv_mutex_init(&wc.mutex)); - ASSERT(0 == uv_thread_create(&thread, worker, &wc)); - - uv_mutex_lock(&wc.mutex); - uv_sleep(100); - uv_cond_wait(&wc.cond, &wc.mutex); - ASSERT(wc.posted == 1); - uv_mutex_unlock(&wc.mutex); - - ASSERT(0 == uv_thread_join(&thread)); - uv_mutex_destroy(&wc.mutex); - uv_cond_destroy(&wc.cond); - - return 0; -} diff --git a/libuv/test/test-connection-fail.c b/libuv/test/test-connection-fail.c deleted file mode 100644 index 328bff4..0000000 --- a/libuv/test/test-connection-fail.c +++ /dev/null @@ -1,151 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include - - -static uv_tcp_t tcp; -static uv_connect_t req; -static int connect_cb_calls; -static int close_cb_calls; - -static uv_timer_t timer; -static int timer_close_cb_calls; -static int timer_cb_calls; - - -static void on_close(uv_handle_t* handle) { - close_cb_calls++; -} - - -static void timer_close_cb(uv_handle_t* handle) { - timer_close_cb_calls++; -} - - -static void timer_cb(uv_timer_t* handle) { - timer_cb_calls++; - - /* - * These are the important asserts. The connection callback has been made, - * but libuv hasn't automatically closed the socket. The user must - * uv_close the handle manually. - */ - ASSERT(close_cb_calls == 0); - ASSERT(connect_cb_calls == 1); - - /* Close the tcp handle. */ - uv_close((uv_handle_t*)&tcp, on_close); - - /* Close the timer. */ - uv_close((uv_handle_t*)handle, timer_close_cb); -} - - -static void on_connect_with_close(uv_connect_t *req, int status) { - ASSERT((uv_stream_t*) &tcp == req->handle); - ASSERT(status == UV_ECONNREFUSED); - connect_cb_calls++; - - ASSERT(close_cb_calls == 0); - uv_close((uv_handle_t*)req->handle, on_close); -} - - -static void on_connect_without_close(uv_connect_t *req, int status) { - ASSERT(status == UV_ECONNREFUSED); - connect_cb_calls++; - - uv_timer_start(&timer, timer_cb, 100, 0); - - ASSERT(close_cb_calls == 0); -} - - -static void connection_fail(uv_connect_cb connect_cb) { - struct sockaddr_in client_addr, server_addr; - int r; - - ASSERT(0 == uv_ip4_addr("0.0.0.0", 0, &client_addr)); - - /* There should be no servers listening on this port. */ - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &server_addr)); - - /* Try to connect to the server and do NUM_PINGS ping-pongs. */ - r = uv_tcp_init(uv_default_loop(), &tcp); - ASSERT(!r); - - /* We are never doing multiple reads/connects at a time anyway. */ - /* so these handles can be pre-initialized. */ - ASSERT(0 == uv_tcp_bind(&tcp, (const struct sockaddr*) &client_addr, 0)); - - r = uv_tcp_connect(&req, - &tcp, - (const struct sockaddr*) &server_addr, - connect_cb); - ASSERT(!r); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(connect_cb_calls == 1); - ASSERT(close_cb_calls == 1); -} - - -/* - * This test attempts to connect to a port where no server is running. We - * expect an error. - */ -TEST_IMPL(connection_fail) { - connection_fail(on_connect_with_close); - - ASSERT(timer_close_cb_calls == 0); - ASSERT(timer_cb_calls == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -/* - * This test is the same as the first except it check that the close - * callback of the tcp handle hasn't been made after the failed connection - * attempt. - */ -TEST_IMPL(connection_fail_doesnt_auto_close) { - int r; - - r = uv_timer_init(uv_default_loop(), &timer); - ASSERT(r == 0); - - connection_fail(on_connect_without_close); - - ASSERT(timer_close_cb_calls == 1); - ASSERT(timer_cb_calls == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-cwd-and-chdir.c b/libuv/test/test-cwd-and-chdir.c deleted file mode 100644 index 1e95043..0000000 --- a/libuv/test/test-cwd-and-chdir.c +++ /dev/null @@ -1,51 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" -#include - -#define PATHMAX 1024 -extern char executable_path[]; - -TEST_IMPL(cwd_and_chdir) { - char buffer_orig[PATHMAX]; - char buffer_new[PATHMAX]; - size_t size1; - size_t size2; - int err; - - size1 = sizeof buffer_orig; - err = uv_cwd(buffer_orig, &size1); - ASSERT(err == 0); - - err = uv_chdir(buffer_orig); - ASSERT(err == 0); - - size2 = sizeof buffer_new; - err = uv_cwd(buffer_new, &size2); - ASSERT(err == 0); - - ASSERT(size1 == size2); - ASSERT(strcmp(buffer_orig, buffer_new) == 0); - - return 0; -} diff --git a/libuv/test/test-default-loop-close.c b/libuv/test/test-default-loop-close.c deleted file mode 100644 index fd11cfa..0000000 --- a/libuv/test/test-default-loop-close.c +++ /dev/null @@ -1,59 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - - -static int timer_cb_called; - - -static void timer_cb(uv_timer_t* timer) { - timer_cb_called++; - uv_close((uv_handle_t*) timer, NULL); -} - - -TEST_IMPL(default_loop_close) { - uv_loop_t* loop; - uv_timer_t timer_handle; - - loop = uv_default_loop(); - ASSERT(loop != NULL); - - ASSERT(0 == uv_timer_init(loop, &timer_handle)); - ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 1, 0)); - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - ASSERT(1 == timer_cb_called); - ASSERT(0 == uv_loop_close(loop)); - - loop = uv_default_loop(); - ASSERT(loop != NULL); - - ASSERT(0 == uv_timer_init(loop, &timer_handle)); - ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 1, 0)); - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - ASSERT(2 == timer_cb_called); - ASSERT(0 == uv_loop_close(loop)); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-delayed-accept.c b/libuv/test/test-delayed-accept.c deleted file mode 100644 index 4a79989..0000000 --- a/libuv/test/test-delayed-accept.c +++ /dev/null @@ -1,189 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" -#include -#include - -static int connection_cb_called = 0; -static int do_accept_called = 0; -static int close_cb_called = 0; -static int connect_cb_called = 0; - - -static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) { - buf->base = malloc(size); - buf->len = size; -} - - -static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); - - free(handle); - - close_cb_called++; -} - - -static void do_accept(uv_timer_t* timer_handle) { - uv_tcp_t* server; - uv_tcp_t* accepted_handle = (uv_tcp_t*)malloc(sizeof *accepted_handle); - int r; - - ASSERT(timer_handle != NULL); - ASSERT(accepted_handle != NULL); - - r = uv_tcp_init(uv_default_loop(), accepted_handle); - ASSERT(r == 0); - - server = (uv_tcp_t*)timer_handle->data; - r = uv_accept((uv_stream_t*)server, (uv_stream_t*)accepted_handle); - ASSERT(r == 0); - - do_accept_called++; - - /* Immediately close the accepted handle. */ - uv_close((uv_handle_t*)accepted_handle, close_cb); - - /* After accepting the two clients close the server handle */ - if (do_accept_called == 2) { - uv_close((uv_handle_t*)server, close_cb); - } - - /* Dispose the timer. */ - uv_close((uv_handle_t*)timer_handle, close_cb); -} - - -static void connection_cb(uv_stream_t* tcp, int status) { - int r; - uv_timer_t* timer_handle; - - ASSERT(status == 0); - - timer_handle = (uv_timer_t*)malloc(sizeof *timer_handle); - ASSERT(timer_handle != NULL); - - /* Accept the client after 1 second */ - r = uv_timer_init(uv_default_loop(), timer_handle); - ASSERT(r == 0); - - timer_handle->data = tcp; - - r = uv_timer_start(timer_handle, do_accept, 1000, 0); - ASSERT(r == 0); - - connection_cb_called++; -} - - -static void start_server(void) { - struct sockaddr_in addr; - uv_tcp_t* server = (uv_tcp_t*)malloc(sizeof *server); - int r; - - ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); - ASSERT(server != NULL); - - r = uv_tcp_init(uv_default_loop(), server); - ASSERT(r == 0); - r = uv_tcp_bind(server, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - - r = uv_listen((uv_stream_t*)server, 128, connection_cb); - ASSERT(r == 0); -} - - -static void read_cb(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { - /* The server will not send anything, it should close gracefully. */ - - if (buf->base) { - free(buf->base); - } - - if (nread >= 0) { - ASSERT(nread == 0); - } else { - ASSERT(tcp != NULL); - ASSERT(nread == UV_EOF); - uv_close((uv_handle_t*)tcp, close_cb); - } -} - - -static void connect_cb(uv_connect_t* req, int status) { - int r; - - ASSERT(req != NULL); - ASSERT(status == 0); - - /* Not that the server will send anything, but otherwise we'll never know */ - /* when the server closes the connection. */ - r = uv_read_start((uv_stream_t*)(req->handle), alloc_cb, read_cb); - ASSERT(r == 0); - - connect_cb_called++; - - free(req); -} - - -static void client_connect(void) { - struct sockaddr_in addr; - uv_tcp_t* client = (uv_tcp_t*)malloc(sizeof *client); - uv_connect_t* connect_req = malloc(sizeof *connect_req); - int r; - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - ASSERT(client != NULL); - ASSERT(connect_req != NULL); - - r = uv_tcp_init(uv_default_loop(), client); - ASSERT(r == 0); - - r = uv_tcp_connect(connect_req, - client, - (const struct sockaddr*) &addr, - connect_cb); - ASSERT(r == 0); -} - - - -TEST_IMPL(delayed_accept) { - start_server(); - - client_connect(); - client_connect(); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(connection_cb_called == 2); - ASSERT(do_accept_called == 2); - ASSERT(connect_cb_called == 2); - ASSERT(close_cb_called == 7); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-dlerror.c b/libuv/test/test-dlerror.c deleted file mode 100644 index 091200e..0000000 --- a/libuv/test/test-dlerror.c +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" -#include - - -TEST_IMPL(dlerror) { - const char* path = "test/fixtures/load_error.node"; - const char* dlerror_no_error = "no error"; - const char* msg; - uv_lib_t lib; - int r; - - lib.errmsg = NULL; - lib.handle = NULL; - msg = uv_dlerror(&lib); - ASSERT(msg != NULL); - ASSERT(strstr(msg, dlerror_no_error) != NULL); - - r = uv_dlopen(path, &lib); - ASSERT(r == -1); - - msg = uv_dlerror(&lib); - ASSERT(msg != NULL); - ASSERT(strstr(msg, dlerror_no_error) == NULL); - - /* Should return the same error twice in a row. */ - msg = uv_dlerror(&lib); - ASSERT(msg != NULL); - ASSERT(strstr(msg, dlerror_no_error) == NULL); - - uv_dlclose(&lib); - - return 0; -} diff --git a/libuv/test/test-embed.c b/libuv/test/test-embed.c deleted file mode 100644 index 0613745..0000000 --- a/libuv/test/test-embed.c +++ /dev/null @@ -1,138 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" -#include -#include -#include - -#ifndef HAVE_KQUEUE -# if defined(__APPLE__) || \ - defined(__DragonFly__) || \ - defined(__FreeBSD__) || \ - defined(__OpenBSD__) || \ - defined(__NetBSD__) -# define HAVE_KQUEUE 1 -# endif -#endif - -#ifndef HAVE_EPOLL -# if defined(__linux__) -# define HAVE_EPOLL 1 -# endif -#endif - -#if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL) - -#if defined(HAVE_KQUEUE) -# include -# include -# include -#endif - -#if defined(HAVE_EPOLL) -# include -#endif - -static uv_thread_t embed_thread; -static uv_sem_t embed_sem; -static uv_timer_t embed_timer; -static uv_async_t embed_async; -static volatile int embed_closed; - -static int embed_timer_called; - - -static void embed_thread_runner(void* arg) { - int r; - int fd; - int timeout; - - while (!embed_closed) { - fd = uv_backend_fd(uv_default_loop()); - timeout = uv_backend_timeout(uv_default_loop()); - - do { -#if defined(HAVE_KQUEUE) - struct timespec ts; - ts.tv_sec = timeout / 1000; - ts.tv_nsec = (timeout % 1000) * 1000000; - r = kevent(fd, NULL, 0, NULL, 0, &ts); -#elif defined(HAVE_EPOLL) - { - struct epoll_event ev; - r = epoll_wait(fd, &ev, 1, timeout); - } -#endif - } while (r == -1 && errno == EINTR); - uv_async_send(&embed_async); - uv_sem_wait(&embed_sem); - } -} - - -static void embed_cb(uv_async_t* async) { - uv_run(uv_default_loop(), UV_RUN_ONCE); - - uv_sem_post(&embed_sem); -} - - -static void embed_timer_cb(uv_timer_t* timer) { - embed_timer_called++; - embed_closed = 1; - - uv_close((uv_handle_t*) &embed_async, NULL); -} -#endif - - -TEST_IMPL(embed) { -#if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL) - uv_loop_t external; - - ASSERT(0 == uv_loop_init(&external)); - - embed_timer_called = 0; - embed_closed = 0; - - uv_async_init(&external, &embed_async, embed_cb); - - /* Start timer in default loop */ - uv_timer_init(uv_default_loop(), &embed_timer); - uv_timer_start(&embed_timer, embed_timer_cb, 250, 0); - - /* Start worker that will interrupt external loop */ - uv_sem_init(&embed_sem, 0); - uv_thread_create(&embed_thread, embed_thread_runner, NULL); - - /* But run external loop */ - uv_run(&external, UV_RUN_DEFAULT); - - uv_thread_join(&embed_thread); - uv_loop_close(&external); - - ASSERT(embed_timer_called == 1); -#endif - - return 0; -} diff --git a/libuv/test/test-emfile.c b/libuv/test/test-emfile.c deleted file mode 100644 index 453bfe4..0000000 --- a/libuv/test/test-emfile.c +++ /dev/null @@ -1,111 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#if !defined(_WIN32) - -#include "uv.h" -#include "task.h" - -#include -#include -#include -#include - -static void connection_cb(uv_stream_t* server_handle, int status); -static void connect_cb(uv_connect_t* req, int status); - -static const int maxfd = 31; -static unsigned connect_cb_called; -static uv_tcp_t server_handle; -static uv_tcp_t client_handle; - - -TEST_IMPL(emfile) { - struct sockaddr_in addr; - struct rlimit limits; - uv_connect_t connect_req; - uv_loop_t* loop; - int first_fd; - - loop = uv_default_loop(); - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - ASSERT(0 == uv_tcp_init(loop, &server_handle)); - ASSERT(0 == uv_tcp_init(loop, &client_handle)); - ASSERT(0 == uv_tcp_bind(&server_handle, (const struct sockaddr*) &addr, 0)); - ASSERT(0 == uv_listen((uv_stream_t*) &server_handle, 8, connection_cb)); - - /* Lower the file descriptor limit and use up all fds save one. */ - limits.rlim_cur = limits.rlim_max = maxfd + 1; - if (setrlimit(RLIMIT_NOFILE, &limits)) { - perror("setrlimit(RLIMIT_NOFILE)"); - ASSERT(0); - } - - /* Remember the first one so we can clean up afterwards. */ - do - first_fd = dup(0); - while (first_fd == -1 && errno == EINTR); - ASSERT(first_fd > 0); - - while (dup(0) != -1 || errno == EINTR); - ASSERT(errno == EMFILE); - close(maxfd); - - /* Now connect and use up the last available file descriptor. The EMFILE - * handling logic in src/unix/stream.c should ensure that connect_cb() runs - * whereas connection_cb() should *not* run. - */ - ASSERT(0 == uv_tcp_connect(&connect_req, - &client_handle, - (const struct sockaddr*) &addr, - connect_cb)); - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - ASSERT(1 == connect_cb_called); - - /* Close the dups again. Ignore errors in the unlikely event that the - * file descriptors were not contiguous. - */ - while (first_fd < maxfd) { - close(first_fd); - first_fd += 1; - } - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -static void connection_cb(uv_stream_t* server_handle, int status) { - ASSERT(0 && "connection_cb should not be called."); -} - - -static void connect_cb(uv_connect_t* req, int status) { - /* |status| should equal 0 because the connection should have been accepted, - * it's just that the server immediately closes it again. - */ - ASSERT(0 == status); - connect_cb_called += 1; - uv_close((uv_handle_t*) &server_handle, NULL); - uv_close((uv_handle_t*) &client_handle, NULL); -} - -#endif /* !defined(_WIN32) */ diff --git a/libuv/test/test-error.c b/libuv/test/test-error.c deleted file mode 100644 index eb337e6..0000000 --- a/libuv/test/test-error.c +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include -#include - - -/* - * Synthetic errors (errors that originate from within libuv, not the system) - * should produce sensible error messages when run through uv_strerror(). - * - * See https://github.com/joyent/libuv/issues/210 - */ -TEST_IMPL(error_message) { - /* Cop out. Can't do proper checks on systems with - * i18n-ized error messages... - */ - if (strcmp(uv_strerror(0), "Success") != 0) { - printf("i18n error messages detected, skipping test.\n"); - return 0; - } - - ASSERT(strstr(uv_strerror(UV_EINVAL), "Success") == NULL); - ASSERT(strcmp(uv_strerror(1337), "Unknown error") == 0); - ASSERT(strcmp(uv_strerror(-1337), "Unknown error") == 0); - - return 0; -} diff --git a/libuv/test/test-fail-always.c b/libuv/test/test-fail-always.c deleted file mode 100644 index 0008459..0000000 --- a/libuv/test/test-fail-always.c +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "task.h" - - -TEST_IMPL(fail_always) { - /* This test always fails. It is used to test the test runner. */ - FATAL("Yes, it always fails"); - return 2; -} diff --git a/libuv/test/test-fs-event.c b/libuv/test/test-fs-event.c deleted file mode 100644 index 0a2ba33..0000000 --- a/libuv/test/test-fs-event.c +++ /dev/null @@ -1,758 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include - -#ifndef HAVE_KQUEUE -# if defined(__APPLE__) || \ - defined(__DragonFly__) || \ - defined(__FreeBSD__) || \ - defined(__OpenBSD__) || \ - defined(__NetBSD__) -# define HAVE_KQUEUE 1 -# endif -#endif - -static uv_fs_event_t fs_event; -static const char file_prefix[] = "fsevent-"; -static uv_timer_t timer; -static int timer_cb_called; -static int close_cb_called; -static const int fs_event_file_count = 128; -static int fs_event_created; -static int fs_event_cb_called; -#if defined(PATH_MAX) -static char fs_event_filename[PATH_MAX]; -#else -static char fs_event_filename[1024]; -#endif /* defined(PATH_MAX) */ -static int timer_cb_touch_called; - -static void fs_event_unlink_files(uv_timer_t* handle); - -static void create_dir(uv_loop_t* loop, const char* name) { - int r; - uv_fs_t req; - r = uv_fs_mkdir(loop, &req, name, 0755, NULL); - ASSERT(r == 0 || r == UV_EEXIST); - uv_fs_req_cleanup(&req); -} - -static void create_file(uv_loop_t* loop, const char* name) { - int r; - uv_file file; - uv_fs_t req; - - r = uv_fs_open(loop, &req, name, O_WRONLY | O_CREAT, - S_IWUSR | S_IRUSR, NULL); - ASSERT(r >= 0); - file = r; - uv_fs_req_cleanup(&req); - r = uv_fs_close(loop, &req, file, NULL); - ASSERT(r == 0); - uv_fs_req_cleanup(&req); -} - -static void touch_file(uv_loop_t* loop, const char* name) { - int r; - uv_file file; - uv_fs_t req; - uv_buf_t buf; - - r = uv_fs_open(loop, &req, name, O_RDWR, 0, NULL); - ASSERT(r >= 0); - file = r; - uv_fs_req_cleanup(&req); - - buf = uv_buf_init("foo", 4); - r = uv_fs_write(loop, &req, file, &buf, 1, -1, NULL); - ASSERT(r >= 0); - uv_fs_req_cleanup(&req); - - r = uv_fs_close(loop, &req, file, NULL); - ASSERT(r == 0); - uv_fs_req_cleanup(&req); -} - -static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); - close_cb_called++; -} - -static void fail_cb(uv_fs_event_t* handle, - const char* path, - int events, - int status) { - ASSERT(0 && "fail_cb called"); -} - -static void fs_event_cb_dir(uv_fs_event_t* handle, const char* filename, - int events, int status) { - ++fs_event_cb_called; - ASSERT(handle == &fs_event); - ASSERT(status == 0); - ASSERT(events == UV_RENAME); - ASSERT(filename == NULL || strcmp(filename, "file1") == 0); - ASSERT(0 == uv_fs_event_stop(handle)); - uv_close((uv_handle_t*)handle, close_cb); -} - -static void fs_event_cb_dir_multi_file(uv_fs_event_t* handle, - const char* filename, - int events, - int status) { - fs_event_cb_called++; - ASSERT(handle == &fs_event); - ASSERT(status == 0); - ASSERT(events == UV_RENAME); - ASSERT(filename == NULL || - strncmp(filename, file_prefix, sizeof(file_prefix) - 1) == 0); - - /* Stop watching dir when received events about all files: - * both create and close events */ - if (fs_event_cb_called == 2 * fs_event_file_count) { - ASSERT(0 == uv_fs_event_stop(handle)); - uv_close((uv_handle_t*) handle, close_cb); - } -} - -static const char* fs_event_get_filename(int i) { - snprintf(fs_event_filename, - sizeof(fs_event_filename), - "watch_dir/%s%d", - file_prefix, - i); - return fs_event_filename; -} - -static void fs_event_create_files(uv_timer_t* handle) { - int i; - - /* Already created all files */ - if (fs_event_created == fs_event_file_count) { - uv_close((uv_handle_t*) &timer, close_cb); - return; - } - - /* Create all files */ - for (i = 0; i < 16; i++, fs_event_created++) - create_file(handle->loop, fs_event_get_filename(i)); - - /* And unlink them */ - ASSERT(0 == uv_timer_start(&timer, fs_event_unlink_files, 50, 0)); -} - -void fs_event_unlink_files(uv_timer_t* handle) { - int r; - int i; - - /* NOTE: handle might be NULL if invoked not as timer callback */ - - /* Unlink all files */ - for (i = 0; i < 16; i++) { - r = remove(fs_event_get_filename(i)); - if (handle != NULL) - ASSERT(r == 0); - } - - /* And create them again */ - if (handle != NULL) - ASSERT(0 == uv_timer_start(&timer, fs_event_create_files, 50, 0)); -} - -static void fs_event_cb_file(uv_fs_event_t* handle, const char* filename, - int events, int status) { - ++fs_event_cb_called; - ASSERT(handle == &fs_event); - ASSERT(status == 0); - ASSERT(events == UV_CHANGE); - ASSERT(filename == NULL || strcmp(filename, "file2") == 0); - ASSERT(0 == uv_fs_event_stop(handle)); - uv_close((uv_handle_t*)handle, close_cb); -} - -static void timer_cb_close_handle(uv_timer_t* timer) { - uv_handle_t* handle; - - ASSERT(timer != NULL); - handle = timer->data; - - uv_close((uv_handle_t*)timer, NULL); - uv_close((uv_handle_t*)handle, close_cb); -} - -static void fs_event_cb_file_current_dir(uv_fs_event_t* handle, - const char* filename, int events, int status) { - ASSERT(fs_event_cb_called == 0); - ++fs_event_cb_called; - - ASSERT(handle == &fs_event); - ASSERT(status == 0); - ASSERT(events == UV_CHANGE); - ASSERT(filename == NULL || strcmp(filename, "watch_file") == 0); - - /* Regression test for SunOS: touch should generate just one event. */ - { - static uv_timer_t timer; - uv_timer_init(handle->loop, &timer); - timer.data = handle; - uv_timer_start(&timer, timer_cb_close_handle, 250, 0); - } -} - -static void timer_cb_file(uv_timer_t* handle) { - ++timer_cb_called; - - if (timer_cb_called == 1) { - touch_file(handle->loop, "watch_dir/file1"); - } else { - touch_file(handle->loop, "watch_dir/file2"); - uv_close((uv_handle_t*)handle, close_cb); - } -} - -static void timer_cb_touch(uv_timer_t* timer) { - uv_close((uv_handle_t*)timer, NULL); - touch_file(timer->loop, "watch_file"); - timer_cb_touch_called++; -} - -static void timer_cb_watch_twice(uv_timer_t* handle) { - uv_fs_event_t* handles = handle->data; - uv_close((uv_handle_t*) (handles + 0), NULL); - uv_close((uv_handle_t*) (handles + 1), NULL); - uv_close((uv_handle_t*) handle, NULL); -} - -TEST_IMPL(fs_event_watch_dir) { - uv_loop_t* loop = uv_default_loop(); - int r; - - /* Setup */ - fs_event_unlink_files(NULL); - remove("watch_dir/file2"); - remove("watch_dir/file1"); - remove("watch_dir/"); - create_dir(loop, "watch_dir"); - - r = uv_fs_event_init(loop, &fs_event); - ASSERT(r == 0); - r = uv_fs_event_start(&fs_event, fs_event_cb_dir_multi_file, "watch_dir", 0); - ASSERT(r == 0); - r = uv_timer_init(loop, &timer); - ASSERT(r == 0); - r = uv_timer_start(&timer, fs_event_create_files, 100, 0); - ASSERT(r == 0); - - uv_run(loop, UV_RUN_DEFAULT); - - ASSERT(fs_event_cb_called == 2 * fs_event_file_count); - ASSERT(fs_event_created == fs_event_file_count); - ASSERT(close_cb_called == 2); - - /* Cleanup */ - fs_event_unlink_files(NULL); - remove("watch_dir/file2"); - remove("watch_dir/file1"); - remove("watch_dir/"); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -TEST_IMPL(fs_event_watch_file) { - uv_loop_t* loop = uv_default_loop(); - int r; - - /* Setup */ - remove("watch_dir/file2"); - remove("watch_dir/file1"); - remove("watch_dir/"); - create_dir(loop, "watch_dir"); - create_file(loop, "watch_dir/file1"); - create_file(loop, "watch_dir/file2"); - - r = uv_fs_event_init(loop, &fs_event); - ASSERT(r == 0); - r = uv_fs_event_start(&fs_event, fs_event_cb_file, "watch_dir/file2", 0); - ASSERT(r == 0); - r = uv_timer_init(loop, &timer); - ASSERT(r == 0); - r = uv_timer_start(&timer, timer_cb_file, 100, 100); - ASSERT(r == 0); - - uv_run(loop, UV_RUN_DEFAULT); - - ASSERT(fs_event_cb_called == 1); - ASSERT(timer_cb_called == 2); - ASSERT(close_cb_called == 2); - - /* Cleanup */ - remove("watch_dir/file2"); - remove("watch_dir/file1"); - remove("watch_dir/"); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -TEST_IMPL(fs_event_watch_file_twice) { - const char path[] = "test/fixtures/empty_file"; - uv_fs_event_t watchers[2]; - uv_timer_t timer; - uv_loop_t* loop; - - loop = uv_default_loop(); - timer.data = watchers; - - ASSERT(0 == uv_fs_event_init(loop, watchers + 0)); - ASSERT(0 == uv_fs_event_start(watchers + 0, fail_cb, path, 0)); - ASSERT(0 == uv_fs_event_init(loop, watchers + 1)); - ASSERT(0 == uv_fs_event_start(watchers + 1, fail_cb, path, 0)); - ASSERT(0 == uv_timer_init(loop, &timer)); - ASSERT(0 == uv_timer_start(&timer, timer_cb_watch_twice, 10, 0)); - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -TEST_IMPL(fs_event_watch_file_current_dir) { - uv_timer_t timer; - uv_loop_t* loop; - int r; - - loop = uv_default_loop(); - - /* Setup */ - remove("watch_file"); - create_file(loop, "watch_file"); - - r = uv_fs_event_init(loop, &fs_event); - ASSERT(r == 0); - r = uv_fs_event_start(&fs_event, - fs_event_cb_file_current_dir, - "watch_file", - 0); - ASSERT(r == 0); - - - r = uv_timer_init(loop, &timer); - ASSERT(r == 0); - - r = uv_timer_start(&timer, timer_cb_touch, 1, 0); - ASSERT(r == 0); - - ASSERT(timer_cb_touch_called == 0); - ASSERT(fs_event_cb_called == 0); - ASSERT(close_cb_called == 0); - - uv_run(loop, UV_RUN_DEFAULT); - - ASSERT(timer_cb_touch_called == 1); - ASSERT(fs_event_cb_called == 1); - ASSERT(close_cb_called == 1); - - /* Cleanup */ - remove("watch_file"); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -TEST_IMPL(fs_event_no_callback_after_close) { - uv_loop_t* loop = uv_default_loop(); - int r; - - /* Setup */ - remove("watch_dir/file1"); - remove("watch_dir/"); - create_dir(loop, "watch_dir"); - create_file(loop, "watch_dir/file1"); - - r = uv_fs_event_init(loop, &fs_event); - ASSERT(r == 0); - r = uv_fs_event_start(&fs_event, - fs_event_cb_file, - "watch_dir/file1", - 0); - ASSERT(r == 0); - - - uv_close((uv_handle_t*)&fs_event, close_cb); - touch_file(loop, "watch_dir/file1"); - uv_run(loop, UV_RUN_DEFAULT); - - ASSERT(fs_event_cb_called == 0); - ASSERT(close_cb_called == 1); - - /* Cleanup */ - remove("watch_dir/file1"); - remove("watch_dir/"); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -TEST_IMPL(fs_event_no_callback_on_close) { - uv_loop_t* loop = uv_default_loop(); - int r; - - /* Setup */ - remove("watch_dir/file1"); - remove("watch_dir/"); - create_dir(loop, "watch_dir"); - create_file(loop, "watch_dir/file1"); - - r = uv_fs_event_init(loop, &fs_event); - ASSERT(r == 0); - r = uv_fs_event_start(&fs_event, - fs_event_cb_file, - "watch_dir/file1", - 0); - ASSERT(r == 0); - - uv_close((uv_handle_t*)&fs_event, close_cb); - - uv_run(loop, UV_RUN_DEFAULT); - - ASSERT(fs_event_cb_called == 0); - ASSERT(close_cb_called == 1); - - /* Cleanup */ - remove("watch_dir/file1"); - remove("watch_dir/"); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -static void fs_event_fail(uv_fs_event_t* handle, const char* filename, - int events, int status) { - ASSERT(0 && "should never be called"); -} - - -static void timer_cb(uv_timer_t* handle) { - int r; - - r = uv_fs_event_init(handle->loop, &fs_event); - ASSERT(r == 0); - r = uv_fs_event_start(&fs_event, fs_event_fail, ".", 0); - ASSERT(r == 0); - - uv_close((uv_handle_t*)&fs_event, close_cb); - uv_close((uv_handle_t*)handle, close_cb); -} - - -TEST_IMPL(fs_event_immediate_close) { - uv_timer_t timer; - uv_loop_t* loop; - int r; - - loop = uv_default_loop(); - - r = uv_timer_init(loop, &timer); - ASSERT(r == 0); - - r = uv_timer_start(&timer, timer_cb, 1, 0); - ASSERT(r == 0); - - uv_run(loop, UV_RUN_DEFAULT); - - ASSERT(close_cb_called == 2); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(fs_event_close_with_pending_event) { - uv_loop_t* loop; - int r; - - loop = uv_default_loop(); - - create_dir(loop, "watch_dir"); - create_file(loop, "watch_dir/file"); - - r = uv_fs_event_init(loop, &fs_event); - ASSERT(r == 0); - r = uv_fs_event_start(&fs_event, fs_event_fail, "watch_dir", 0); - ASSERT(r == 0); - - /* Generate an fs event. */ - touch_file(loop, "watch_dir/file"); - - uv_close((uv_handle_t*)&fs_event, close_cb); - - uv_run(loop, UV_RUN_DEFAULT); - - ASSERT(close_cb_called == 1); - - /* Clean up */ - remove("watch_dir/file"); - remove("watch_dir/"); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -#if defined(HAVE_KQUEUE) - -/* kqueue doesn't register fs events if you don't have an active watcher. - * The file descriptor needs to be part of the kqueue set of interest and - * that's not the case until we actually enter the event loop. - */ -TEST_IMPL(fs_event_close_in_callback) { - fprintf(stderr, "Skipping test, doesn't work with kqueue.\n"); - return 0; -} - -#else /* !HAVE_KQUEUE */ - -static void fs_event_cb_close(uv_fs_event_t* handle, const char* filename, - int events, int status) { - ASSERT(status == 0); - - ASSERT(fs_event_cb_called < 3); - ++fs_event_cb_called; - - if (fs_event_cb_called == 3) { - uv_close((uv_handle_t*) handle, close_cb); - } -} - - -TEST_IMPL(fs_event_close_in_callback) { - uv_loop_t* loop; - int r; - - loop = uv_default_loop(); - - create_dir(loop, "watch_dir"); - create_file(loop, "watch_dir/file1"); - create_file(loop, "watch_dir/file2"); - create_file(loop, "watch_dir/file3"); - create_file(loop, "watch_dir/file4"); - create_file(loop, "watch_dir/file5"); - - r = uv_fs_event_init(loop, &fs_event); - ASSERT(r == 0); - r = uv_fs_event_start(&fs_event, fs_event_cb_close, "watch_dir", 0); - ASSERT(r == 0); - - /* Generate a couple of fs events. */ - touch_file(loop, "watch_dir/file1"); - touch_file(loop, "watch_dir/file2"); - touch_file(loop, "watch_dir/file3"); - touch_file(loop, "watch_dir/file4"); - touch_file(loop, "watch_dir/file5"); - - uv_run(loop, UV_RUN_DEFAULT); - - ASSERT(close_cb_called == 1); - ASSERT(fs_event_cb_called == 3); - - /* Clean up */ - remove("watch_dir/file1"); - remove("watch_dir/file2"); - remove("watch_dir/file3"); - remove("watch_dir/file4"); - remove("watch_dir/file5"); - remove("watch_dir/"); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -#endif /* HAVE_KQUEUE */ - -TEST_IMPL(fs_event_start_and_close) { - uv_loop_t* loop; - uv_fs_event_t fs_event1; - uv_fs_event_t fs_event2; - int r; - - loop = uv_default_loop(); - - create_dir(loop, "watch_dir"); - - r = uv_fs_event_init(loop, &fs_event1); - ASSERT(r == 0); - r = uv_fs_event_start(&fs_event1, fs_event_cb_dir, "watch_dir", 0); - ASSERT(r == 0); - - r = uv_fs_event_init(loop, &fs_event2); - ASSERT(r == 0); - r = uv_fs_event_start(&fs_event2, fs_event_cb_dir, "watch_dir", 0); - ASSERT(r == 0); - - uv_close((uv_handle_t*) &fs_event2, close_cb); - uv_close((uv_handle_t*) &fs_event1, close_cb); - - uv_run(loop, UV_RUN_DEFAULT); - - ASSERT(close_cb_called == 2); - - remove("watch_dir/"); - MAKE_VALGRIND_HAPPY(); - return 0; -} - -TEST_IMPL(fs_event_getpath) { - uv_loop_t* loop = uv_default_loop(); - int r; - char buf[1024]; - size_t len; - - create_dir(loop, "watch_dir"); - - r = uv_fs_event_init(loop, &fs_event); - ASSERT(r == 0); - len = sizeof buf; - r = uv_fs_event_getpath(&fs_event, buf, &len); - ASSERT(r == UV_EINVAL); - r = uv_fs_event_start(&fs_event, fail_cb, "watch_dir", 0); - ASSERT(r == 0); - len = sizeof buf; - r = uv_fs_event_getpath(&fs_event, buf, &len); - ASSERT(r == 0); - ASSERT(buf[len - 1] != 0); - ASSERT(memcmp(buf, "watch_dir", len) == 0); - r = uv_fs_event_stop(&fs_event); - ASSERT(r == 0); - uv_close((uv_handle_t*) &fs_event, close_cb); - - uv_run(loop, UV_RUN_DEFAULT); - - ASSERT(close_cb_called == 1); - - remove("watch_dir/"); - MAKE_VALGRIND_HAPPY(); - return 0; -} - -#if defined(__APPLE__) - -static int fs_event_error_reported; - -static void fs_event_error_report_cb(uv_fs_event_t* handle, - const char* filename, - int events, - int status) { - if (status != 0) - fs_event_error_reported = status; -} - -static void timer_cb_nop(uv_timer_t* handle) { - ++timer_cb_called; - uv_close((uv_handle_t*) handle, close_cb); -} - -static void fs_event_error_report_close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); - close_cb_called++; - - /* handle is allocated on-stack, no need to free it */ -} - - -TEST_IMPL(fs_event_error_reporting) { - unsigned int i; - uv_loop_t loops[1024]; - uv_fs_event_t events[ARRAY_SIZE(loops)]; - uv_loop_t* loop; - uv_fs_event_t* event; - - TEST_FILE_LIMIT(ARRAY_SIZE(loops) * 3); - - remove("watch_dir/"); - create_dir(uv_default_loop(), "watch_dir"); - - /* Create a lot of loops, and start FSEventStream in each of them. - * Eventually, this should create enough streams to make FSEventStreamStart() - * fail. - */ - for (i = 0; i < ARRAY_SIZE(loops); i++) { - loop = &loops[i]; - ASSERT(0 == uv_loop_init(loop)); - event = &events[i]; - - timer_cb_called = 0; - close_cb_called = 0; - ASSERT(0 == uv_fs_event_init(loop, event)); - ASSERT(0 == uv_fs_event_start(event, - fs_event_error_report_cb, - "watch_dir", - 0)); - uv_unref((uv_handle_t*) event); - - /* Let loop run for some time */ - ASSERT(0 == uv_timer_init(loop, &timer)); - ASSERT(0 == uv_timer_start(&timer, timer_cb_nop, 2, 0)); - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(1 == timer_cb_called); - ASSERT(1 == close_cb_called); - if (fs_event_error_reported != 0) - break; - } - - /* At least one loop should fail */ - ASSERT(fs_event_error_reported == UV_EMFILE); - - /* Stop and close all events, and destroy loops */ - do { - loop = &loops[i]; - event = &events[i]; - - ASSERT(0 == uv_fs_event_stop(event)); - uv_ref((uv_handle_t*) event); - uv_close((uv_handle_t*) event, fs_event_error_report_close_cb); - - close_cb_called = 0; - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(close_cb_called == 1); - - uv_loop_close(loop); - } while (i-- != 0); - - remove("watch_dir/"); - MAKE_VALGRIND_HAPPY(); - return 0; -} - -#else /* !defined(__APPLE__) */ - -TEST_IMPL(fs_event_error_reporting) { - /* No-op, needed only for FSEvents backend */ - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -#endif /* defined(__APPLE__) */ diff --git a/libuv/test/test-fs-poll.c b/libuv/test/test-fs-poll.c deleted file mode 100644 index dbc1515..0000000 --- a/libuv/test/test-fs-poll.c +++ /dev/null @@ -1,186 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include - -#define FIXTURE "testfile" - -static void timer_cb(uv_timer_t* handle); -static void close_cb(uv_handle_t* handle); -static void poll_cb(uv_fs_poll_t* handle, - int status, - const uv_stat_t* prev, - const uv_stat_t* curr); - -static void poll_cb_fail(uv_fs_poll_t* handle, - int status, - const uv_stat_t* prev, - const uv_stat_t* curr); - -static uv_fs_poll_t poll_handle; -static uv_timer_t timer_handle; -static uv_loop_t* loop; - -static int poll_cb_called; -static int timer_cb_called; -static int close_cb_called; - - -static void touch_file(const char* path) { - static int count; - FILE* fp; - int i; - - ASSERT((fp = fopen(FIXTURE, "w+"))); - - /* Need to change the file size because the poller may not pick up - * sub-second mtime changes. - */ - i = ++count; - - while (i--) - fputc('*', fp); - - fclose(fp); -} - - -static void close_cb(uv_handle_t* handle) { - close_cb_called++; -} - - -static void timer_cb(uv_timer_t* handle) { - touch_file(FIXTURE); - timer_cb_called++; -} - - -static void poll_cb_fail(uv_fs_poll_t* handle, - int status, - const uv_stat_t* prev, - const uv_stat_t* curr) { - ASSERT(0 && "fail_cb called"); -} - - -static void poll_cb(uv_fs_poll_t* handle, - int status, - const uv_stat_t* prev, - const uv_stat_t* curr) { - uv_stat_t zero_statbuf; - - memset(&zero_statbuf, 0, sizeof(zero_statbuf)); - - ASSERT(handle == &poll_handle); - ASSERT(1 == uv_is_active((uv_handle_t*) handle)); - ASSERT(prev != NULL); - ASSERT(curr != NULL); - - switch (poll_cb_called++) { - case 0: - ASSERT(status == UV_ENOENT); - ASSERT(0 == memcmp(prev, &zero_statbuf, sizeof(zero_statbuf))); - ASSERT(0 == memcmp(curr, &zero_statbuf, sizeof(zero_statbuf))); - touch_file(FIXTURE); - break; - - case 1: - ASSERT(status == 0); - ASSERT(0 == memcmp(prev, &zero_statbuf, sizeof(zero_statbuf))); - ASSERT(0 != memcmp(curr, &zero_statbuf, sizeof(zero_statbuf))); - ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 20, 0)); - break; - - case 2: - ASSERT(status == 0); - ASSERT(0 != memcmp(prev, &zero_statbuf, sizeof(zero_statbuf))); - ASSERT(0 != memcmp(curr, &zero_statbuf, sizeof(zero_statbuf))); - ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 200, 0)); - break; - - case 3: - ASSERT(status == 0); - ASSERT(0 != memcmp(prev, &zero_statbuf, sizeof(zero_statbuf))); - ASSERT(0 != memcmp(curr, &zero_statbuf, sizeof(zero_statbuf))); - remove(FIXTURE); - break; - - case 4: - ASSERT(status == UV_ENOENT); - ASSERT(0 != memcmp(prev, &zero_statbuf, sizeof(zero_statbuf))); - ASSERT(0 == memcmp(curr, &zero_statbuf, sizeof(zero_statbuf))); - uv_close((uv_handle_t*)handle, close_cb); - break; - - default: - ASSERT(0); - } -} - - -TEST_IMPL(fs_poll) { - loop = uv_default_loop(); - - remove(FIXTURE); - - ASSERT(0 == uv_timer_init(loop, &timer_handle)); - ASSERT(0 == uv_fs_poll_init(loop, &poll_handle)); - ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb, FIXTURE, 100)); - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - - ASSERT(poll_cb_called == 5); - ASSERT(timer_cb_called == 2); - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(fs_poll_getpath) { - char buf[1024]; - size_t len; - loop = uv_default_loop(); - - remove(FIXTURE); - - ASSERT(0 == uv_fs_poll_init(loop, &poll_handle)); - len = sizeof buf; - ASSERT(UV_EINVAL == uv_fs_poll_getpath(&poll_handle, buf, &len)); - ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100)); - len = sizeof buf; - ASSERT(0 == uv_fs_poll_getpath(&poll_handle, buf, &len)); - ASSERT(buf[len - 1] != 0); - ASSERT(0 == memcmp(buf, FIXTURE, len)); - - uv_close((uv_handle_t*) &poll_handle, close_cb); - - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-fs.c b/libuv/test/test-fs.c deleted file mode 100644 index 2c39225..0000000 --- a/libuv/test/test-fs.c +++ /dev/null @@ -1,2242 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include /* memset */ -#include -#include - -/* FIXME we shouldn't need to branch in this file */ -#if defined(__unix__) || defined(__POSIX__) || \ - defined(__APPLE__) || defined(_AIX) -#include /* unlink, rmdir, etc. */ -#else -# include -# include -# define unlink _unlink -# define rmdir _rmdir -# define open _open -# define write _write -# define close _close -# ifndef stat -# define stat _stati64 -# endif -# ifndef lseek -# define lseek _lseek -# endif -#endif - -#define TOO_LONG_NAME_LENGTH 65536 -#define PATHMAX 1024 - -typedef struct { - const char* path; - double atime; - double mtime; -} utime_check_t; - - -static int dummy_cb_count; -static int close_cb_count; -static int create_cb_count; -static int open_cb_count; -static int read_cb_count; -static int write_cb_count; -static int unlink_cb_count; -static int mkdir_cb_count; -static int mkdtemp_cb_count; -static int rmdir_cb_count; -static int scandir_cb_count; -static int stat_cb_count; -static int rename_cb_count; -static int fsync_cb_count; -static int fdatasync_cb_count; -static int ftruncate_cb_count; -static int sendfile_cb_count; -static int fstat_cb_count; -static int access_cb_count; -static int chmod_cb_count; -static int fchmod_cb_count; -static int chown_cb_count; -static int fchown_cb_count; -static int link_cb_count; -static int symlink_cb_count; -static int readlink_cb_count; -static int utime_cb_count; -static int futime_cb_count; - -static uv_loop_t* loop; - -static uv_fs_t open_req1; -static uv_fs_t open_req2; -static uv_fs_t read_req; -static uv_fs_t write_req; -static uv_fs_t unlink_req; -static uv_fs_t close_req; -static uv_fs_t mkdir_req; -static uv_fs_t mkdtemp_req1; -static uv_fs_t mkdtemp_req2; -static uv_fs_t rmdir_req; -static uv_fs_t scandir_req; -static uv_fs_t stat_req; -static uv_fs_t rename_req; -static uv_fs_t fsync_req; -static uv_fs_t fdatasync_req; -static uv_fs_t ftruncate_req; -static uv_fs_t sendfile_req; -static uv_fs_t utime_req; -static uv_fs_t futime_req; - -static char buf[32]; -static char buf2[32]; -static char test_buf[] = "test-buffer\n"; -static char test_buf2[] = "second-buffer\n"; -static uv_buf_t iov; - -static void check_permission(const char* filename, unsigned int mode) { - int r; - uv_fs_t req; - uv_stat_t* s; - - r = uv_fs_stat(uv_default_loop(), &req, filename, NULL); - ASSERT(r == 0); - ASSERT(req.result == 0); - - s = &req.statbuf; -#ifdef _WIN32 - /* - * On Windows, chmod can only modify S_IWUSR (_S_IWRITE) bit, - * so only testing for the specified flags. - */ - ASSERT((s->st_mode & 0777) & mode); -#else - ASSERT((s->st_mode & 0777) == mode); -#endif - - uv_fs_req_cleanup(&req); -} - - -static void dummy_cb(uv_fs_t* req) { - (void) req; - dummy_cb_count++; -} - - -static void link_cb(uv_fs_t* req) { - ASSERT(req->fs_type == UV_FS_LINK); - ASSERT(req->result == 0); - link_cb_count++; - uv_fs_req_cleanup(req); -} - - -static void symlink_cb(uv_fs_t* req) { - ASSERT(req->fs_type == UV_FS_SYMLINK); - ASSERT(req->result == 0); - symlink_cb_count++; - uv_fs_req_cleanup(req); -} - -static void readlink_cb(uv_fs_t* req) { - ASSERT(req->fs_type == UV_FS_READLINK); - ASSERT(req->result == 0); - ASSERT(strcmp(req->ptr, "test_file_symlink2") == 0); - readlink_cb_count++; - uv_fs_req_cleanup(req); -} - - -static void access_cb(uv_fs_t* req) { - ASSERT(req->fs_type == UV_FS_ACCESS); - access_cb_count++; - uv_fs_req_cleanup(req); -} - - -static void fchmod_cb(uv_fs_t* req) { - ASSERT(req->fs_type == UV_FS_FCHMOD); - ASSERT(req->result == 0); - fchmod_cb_count++; - uv_fs_req_cleanup(req); - check_permission("test_file", *(int*)req->data); -} - - -static void chmod_cb(uv_fs_t* req) { - ASSERT(req->fs_type == UV_FS_CHMOD); - ASSERT(req->result == 0); - chmod_cb_count++; - uv_fs_req_cleanup(req); - check_permission("test_file", *(int*)req->data); -} - - -static void fchown_cb(uv_fs_t* req) { - ASSERT(req->fs_type == UV_FS_FCHOWN); - ASSERT(req->result == 0); - fchown_cb_count++; - uv_fs_req_cleanup(req); -} - - -static void chown_cb(uv_fs_t* req) { - ASSERT(req->fs_type == UV_FS_CHOWN); - ASSERT(req->result == 0); - chown_cb_count++; - uv_fs_req_cleanup(req); -} - -static void chown_root_cb(uv_fs_t* req) { - ASSERT(req->fs_type == UV_FS_CHOWN); -#ifdef _WIN32 - /* On windows, chown is a no-op and always succeeds. */ - ASSERT(req->result == 0); -#else - /* On unix, chown'ing the root directory is not allowed - - * unless you're root, of course. - */ - if (geteuid() == 0) - ASSERT(req->result == 0); - else - ASSERT(req->result == UV_EPERM); -#endif - chown_cb_count++; - uv_fs_req_cleanup(req); -} - -static void unlink_cb(uv_fs_t* req) { - ASSERT(req == &unlink_req); - ASSERT(req->fs_type == UV_FS_UNLINK); - ASSERT(req->result == 0); - unlink_cb_count++; - uv_fs_req_cleanup(req); -} - -static void fstat_cb(uv_fs_t* req) { - uv_stat_t* s = req->ptr; - ASSERT(req->fs_type == UV_FS_FSTAT); - ASSERT(req->result == 0); - ASSERT(s->st_size == sizeof(test_buf)); - uv_fs_req_cleanup(req); - fstat_cb_count++; -} - - -static void close_cb(uv_fs_t* req) { - int r; - ASSERT(req == &close_req); - ASSERT(req->fs_type == UV_FS_CLOSE); - ASSERT(req->result == 0); - close_cb_count++; - uv_fs_req_cleanup(req); - if (close_cb_count == 3) { - r = uv_fs_unlink(loop, &unlink_req, "test_file2", unlink_cb); - ASSERT(r == 0); - } -} - - -static void ftruncate_cb(uv_fs_t* req) { - int r; - ASSERT(req == &ftruncate_req); - ASSERT(req->fs_type == UV_FS_FTRUNCATE); - ASSERT(req->result == 0); - ftruncate_cb_count++; - uv_fs_req_cleanup(req); - r = uv_fs_close(loop, &close_req, open_req1.result, close_cb); - ASSERT(r == 0); -} - - -static void read_cb(uv_fs_t* req) { - int r; - ASSERT(req == &read_req); - ASSERT(req->fs_type == UV_FS_READ); - ASSERT(req->result >= 0); /* FIXME(bnoordhuis) Check if requested size? */ - read_cb_count++; - uv_fs_req_cleanup(req); - if (read_cb_count == 1) { - ASSERT(strcmp(buf, test_buf) == 0); - r = uv_fs_ftruncate(loop, &ftruncate_req, open_req1.result, 7, - ftruncate_cb); - } else { - ASSERT(strcmp(buf, "test-bu") == 0); - r = uv_fs_close(loop, &close_req, open_req1.result, close_cb); - } - ASSERT(r == 0); -} - - -static void open_cb(uv_fs_t* req) { - int r; - ASSERT(req == &open_req1); - ASSERT(req->fs_type == UV_FS_OPEN); - if (req->result < 0) { - fprintf(stderr, "async open error: %d\n", (int) req->result); - ASSERT(0); - } - open_cb_count++; - ASSERT(req->path); - ASSERT(memcmp(req->path, "test_file2\0", 11) == 0); - uv_fs_req_cleanup(req); - memset(buf, 0, sizeof(buf)); - iov = uv_buf_init(buf, sizeof(buf)); - r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1, - read_cb); - ASSERT(r == 0); -} - - -static void open_cb_simple(uv_fs_t* req) { - ASSERT(req->fs_type == UV_FS_OPEN); - if (req->result < 0) { - fprintf(stderr, "async open error: %d\n", (int) req->result); - ASSERT(0); - } - open_cb_count++; - ASSERT(req->path); - uv_fs_req_cleanup(req); -} - - -static void fsync_cb(uv_fs_t* req) { - int r; - ASSERT(req == &fsync_req); - ASSERT(req->fs_type == UV_FS_FSYNC); - ASSERT(req->result == 0); - fsync_cb_count++; - uv_fs_req_cleanup(req); - r = uv_fs_close(loop, &close_req, open_req1.result, close_cb); - ASSERT(r == 0); -} - - -static void fdatasync_cb(uv_fs_t* req) { - int r; - ASSERT(req == &fdatasync_req); - ASSERT(req->fs_type == UV_FS_FDATASYNC); - ASSERT(req->result == 0); - fdatasync_cb_count++; - uv_fs_req_cleanup(req); - r = uv_fs_fsync(loop, &fsync_req, open_req1.result, fsync_cb); - ASSERT(r == 0); -} - - -static void write_cb(uv_fs_t* req) { - int r; - ASSERT(req == &write_req); - ASSERT(req->fs_type == UV_FS_WRITE); - ASSERT(req->result >= 0); /* FIXME(bnoordhuis) Check if requested size? */ - write_cb_count++; - uv_fs_req_cleanup(req); - r = uv_fs_fdatasync(loop, &fdatasync_req, open_req1.result, fdatasync_cb); - ASSERT(r == 0); -} - - -static void create_cb(uv_fs_t* req) { - int r; - ASSERT(req == &open_req1); - ASSERT(req->fs_type == UV_FS_OPEN); - ASSERT(req->result >= 0); - create_cb_count++; - uv_fs_req_cleanup(req); - iov = uv_buf_init(test_buf, sizeof(test_buf)); - r = uv_fs_write(loop, &write_req, req->result, &iov, 1, -1, write_cb); - ASSERT(r == 0); -} - - -static void rename_cb(uv_fs_t* req) { - ASSERT(req == &rename_req); - ASSERT(req->fs_type == UV_FS_RENAME); - ASSERT(req->result == 0); - rename_cb_count++; - uv_fs_req_cleanup(req); -} - - -static void mkdir_cb(uv_fs_t* req) { - ASSERT(req == &mkdir_req); - ASSERT(req->fs_type == UV_FS_MKDIR); - ASSERT(req->result == 0); - mkdir_cb_count++; - ASSERT(req->path); - ASSERT(memcmp(req->path, "test_dir\0", 9) == 0); - uv_fs_req_cleanup(req); -} - - -static void check_mkdtemp_result(uv_fs_t* req) { - int r; - - ASSERT(req->fs_type == UV_FS_MKDTEMP); - ASSERT(req->result == 0); - ASSERT(req->path); - ASSERT(strlen(req->path) == 15); - ASSERT(memcmp(req->path, "test_dir_", 9) == 0); - ASSERT(memcmp(req->path + 9, "XXXXXX", 6) != 0); - check_permission(req->path, 0700); - - /* Check if req->path is actually a directory */ - r = uv_fs_stat(uv_default_loop(), &stat_req, req->path, NULL); - ASSERT(r == 0); - ASSERT(((uv_stat_t*)stat_req.ptr)->st_mode & S_IFDIR); - uv_fs_req_cleanup(&stat_req); -} - - -static void mkdtemp_cb(uv_fs_t* req) { - ASSERT(req == &mkdtemp_req1); - check_mkdtemp_result(req); - mkdtemp_cb_count++; -} - - -static void rmdir_cb(uv_fs_t* req) { - ASSERT(req == &rmdir_req); - ASSERT(req->fs_type == UV_FS_RMDIR); - ASSERT(req->result == 0); - rmdir_cb_count++; - ASSERT(req->path); - ASSERT(memcmp(req->path, "test_dir\0", 9) == 0); - uv_fs_req_cleanup(req); -} - - -static void scandir_cb(uv_fs_t* req) { - uv_dirent_t dent; - ASSERT(req == &scandir_req); - ASSERT(req->fs_type == UV_FS_SCANDIR); - ASSERT(req->result == 2); - ASSERT(req->ptr); - - while (UV_EOF != uv_fs_scandir_next(req, &dent)) { - ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0); - ASSERT(dent.type == UV_DIRENT_FILE || dent.type == UV_DIRENT_UNKNOWN); - } - scandir_cb_count++; - ASSERT(req->path); - ASSERT(memcmp(req->path, "test_dir\0", 9) == 0); - uv_fs_req_cleanup(req); - ASSERT(!req->ptr); -} - - -static void empty_scandir_cb(uv_fs_t* req) { - uv_dirent_t dent; - - ASSERT(req == &scandir_req); - ASSERT(req->fs_type == UV_FS_SCANDIR); - ASSERT(req->result == 0); - ASSERT(req->ptr == NULL); - ASSERT(UV_EOF == uv_fs_scandir_next(req, &dent)); - uv_fs_req_cleanup(req); - scandir_cb_count++; -} - - -static void file_scandir_cb(uv_fs_t* req) { - ASSERT(req == &scandir_req); - ASSERT(req->fs_type == UV_FS_SCANDIR); - ASSERT(req->result == UV_ENOTDIR); - ASSERT(req->ptr == NULL); - uv_fs_req_cleanup(req); - scandir_cb_count++; -} - - -static void stat_cb(uv_fs_t* req) { - ASSERT(req == &stat_req); - ASSERT(req->fs_type == UV_FS_STAT || req->fs_type == UV_FS_LSTAT); - ASSERT(req->result == 0); - ASSERT(req->ptr); - stat_cb_count++; - uv_fs_req_cleanup(req); - ASSERT(!req->ptr); -} - - -static void sendfile_cb(uv_fs_t* req) { - ASSERT(req == &sendfile_req); - ASSERT(req->fs_type == UV_FS_SENDFILE); - ASSERT(req->result == 65546); - sendfile_cb_count++; - uv_fs_req_cleanup(req); -} - - -static void open_noent_cb(uv_fs_t* req) { - ASSERT(req->fs_type == UV_FS_OPEN); - ASSERT(req->result == UV_ENOENT); - open_cb_count++; - uv_fs_req_cleanup(req); -} - -static void open_nametoolong_cb(uv_fs_t* req) { - ASSERT(req->fs_type == UV_FS_OPEN); - ASSERT(req->result == UV_ENAMETOOLONG); - open_cb_count++; - uv_fs_req_cleanup(req); -} - -static void open_loop_cb(uv_fs_t* req) { - ASSERT(req->fs_type == UV_FS_OPEN); - ASSERT(req->result == UV_ELOOP); - open_cb_count++; - uv_fs_req_cleanup(req); -} - - -TEST_IMPL(fs_file_noent) { - uv_fs_t req; - int r; - - loop = uv_default_loop(); - - r = uv_fs_open(loop, &req, "does_not_exist", O_RDONLY, 0, NULL); - ASSERT(r == UV_ENOENT); - ASSERT(req.result == UV_ENOENT); - uv_fs_req_cleanup(&req); - - r = uv_fs_open(loop, &req, "does_not_exist", O_RDONLY, 0, open_noent_cb); - ASSERT(r == 0); - - ASSERT(open_cb_count == 0); - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(open_cb_count == 1); - - /* TODO add EACCES test */ - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -TEST_IMPL(fs_file_nametoolong) { - uv_fs_t req; - int r; - char name[TOO_LONG_NAME_LENGTH + 1]; - - loop = uv_default_loop(); - - memset(name, 'a', TOO_LONG_NAME_LENGTH); - name[TOO_LONG_NAME_LENGTH] = 0; - - r = uv_fs_open(loop, &req, name, O_RDONLY, 0, NULL); - ASSERT(r == UV_ENAMETOOLONG); - ASSERT(req.result == UV_ENAMETOOLONG); - uv_fs_req_cleanup(&req); - - r = uv_fs_open(loop, &req, name, O_RDONLY, 0, open_nametoolong_cb); - ASSERT(r == 0); - - ASSERT(open_cb_count == 0); - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(open_cb_count == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -TEST_IMPL(fs_file_loop) { - uv_fs_t req; - int r; - - loop = uv_default_loop(); - - unlink("test_symlink"); - r = uv_fs_symlink(loop, &req, "test_symlink", "test_symlink", 0, NULL); -#ifdef _WIN32 - /* - * Windows XP and Server 2003 don't support symlinks; we'll get UV_ENOTSUP. - * Starting with vista they are supported, but only when elevated, otherwise - * we'll see UV_EPERM. - */ - if (r == UV_ENOTSUP || r == UV_EPERM) - return 0; -#endif - ASSERT(r == 0); - uv_fs_req_cleanup(&req); - - r = uv_fs_open(loop, &req, "test_symlink", O_RDONLY, 0, NULL); - ASSERT(r == UV_ELOOP); - ASSERT(req.result == UV_ELOOP); - uv_fs_req_cleanup(&req); - - r = uv_fs_open(loop, &req, "test_symlink", O_RDONLY, 0, open_loop_cb); - ASSERT(r == 0); - - ASSERT(open_cb_count == 0); - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(open_cb_count == 1); - - unlink("test_symlink"); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -static void check_utime(const char* path, double atime, double mtime) { - uv_stat_t* s; - uv_fs_t req; - int r; - - r = uv_fs_stat(loop, &req, path, NULL); - ASSERT(r == 0); - - ASSERT(req.result == 0); - s = &req.statbuf; - - ASSERT(s->st_atim.tv_sec == atime); - ASSERT(s->st_mtim.tv_sec == mtime); - - uv_fs_req_cleanup(&req); -} - - -static void utime_cb(uv_fs_t* req) { - utime_check_t* c; - - ASSERT(req == &utime_req); - ASSERT(req->result == 0); - ASSERT(req->fs_type == UV_FS_UTIME); - - c = req->data; - check_utime(c->path, c->atime, c->mtime); - - uv_fs_req_cleanup(req); - utime_cb_count++; -} - - -static void futime_cb(uv_fs_t* req) { - utime_check_t* c; - - ASSERT(req == &futime_req); - ASSERT(req->result == 0); - ASSERT(req->fs_type == UV_FS_FUTIME); - - c = req->data; - check_utime(c->path, c->atime, c->mtime); - - uv_fs_req_cleanup(req); - futime_cb_count++; -} - - -TEST_IMPL(fs_file_async) { - int r; - - /* Setup. */ - unlink("test_file"); - unlink("test_file2"); - - loop = uv_default_loop(); - - r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT, - S_IRUSR | S_IWUSR, create_cb); - ASSERT(r == 0); - uv_run(loop, UV_RUN_DEFAULT); - - ASSERT(create_cb_count == 1); - ASSERT(write_cb_count == 1); - ASSERT(fsync_cb_count == 1); - ASSERT(fdatasync_cb_count == 1); - ASSERT(close_cb_count == 1); - - r = uv_fs_rename(loop, &rename_req, "test_file", "test_file2", rename_cb); - ASSERT(r == 0); - - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(create_cb_count == 1); - ASSERT(write_cb_count == 1); - ASSERT(close_cb_count == 1); - ASSERT(rename_cb_count == 1); - - r = uv_fs_open(loop, &open_req1, "test_file2", O_RDWR, 0, open_cb); - ASSERT(r == 0); - - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(open_cb_count == 1); - ASSERT(read_cb_count == 1); - ASSERT(close_cb_count == 2); - ASSERT(rename_cb_count == 1); - ASSERT(create_cb_count == 1); - ASSERT(write_cb_count == 1); - ASSERT(ftruncate_cb_count == 1); - - r = uv_fs_open(loop, &open_req1, "test_file2", O_RDONLY, 0, open_cb); - ASSERT(r == 0); - - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(open_cb_count == 2); - ASSERT(read_cb_count == 2); - ASSERT(close_cb_count == 3); - ASSERT(rename_cb_count == 1); - ASSERT(unlink_cb_count == 1); - ASSERT(create_cb_count == 1); - ASSERT(write_cb_count == 1); - ASSERT(ftruncate_cb_count == 1); - - /* Cleanup. */ - unlink("test_file"); - unlink("test_file2"); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(fs_file_sync) { - int r; - - /* Setup. */ - unlink("test_file"); - unlink("test_file2"); - - loop = uv_default_loop(); - - r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT, - S_IWUSR | S_IRUSR, NULL); - ASSERT(r >= 0); - ASSERT(open_req1.result >= 0); - uv_fs_req_cleanup(&open_req1); - - iov = uv_buf_init(test_buf, sizeof(test_buf)); - r = uv_fs_write(loop, &write_req, open_req1.result, &iov, 1, -1, NULL); - ASSERT(r >= 0); - ASSERT(write_req.result >= 0); - uv_fs_req_cleanup(&write_req); - - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); - ASSERT(r == 0); - ASSERT(close_req.result == 0); - uv_fs_req_cleanup(&close_req); - - r = uv_fs_open(loop, &open_req1, "test_file", O_RDWR, 0, NULL); - ASSERT(r >= 0); - ASSERT(open_req1.result >= 0); - uv_fs_req_cleanup(&open_req1); - - iov = uv_buf_init(buf, sizeof(buf)); - r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1, NULL); - ASSERT(r >= 0); - ASSERT(read_req.result >= 0); - ASSERT(strcmp(buf, test_buf) == 0); - uv_fs_req_cleanup(&read_req); - - r = uv_fs_ftruncate(loop, &ftruncate_req, open_req1.result, 7, NULL); - ASSERT(r == 0); - ASSERT(ftruncate_req.result == 0); - uv_fs_req_cleanup(&ftruncate_req); - - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); - ASSERT(r == 0); - ASSERT(close_req.result == 0); - uv_fs_req_cleanup(&close_req); - - r = uv_fs_rename(loop, &rename_req, "test_file", "test_file2", NULL); - ASSERT(r == 0); - ASSERT(rename_req.result == 0); - uv_fs_req_cleanup(&rename_req); - - r = uv_fs_open(loop, &open_req1, "test_file2", O_RDONLY, 0, NULL); - ASSERT(r >= 0); - ASSERT(open_req1.result >= 0); - uv_fs_req_cleanup(&open_req1); - - memset(buf, 0, sizeof(buf)); - iov = uv_buf_init(buf, sizeof(buf)); - r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1, - NULL); - ASSERT(r >= 0); - ASSERT(read_req.result >= 0); - ASSERT(strcmp(buf, "test-bu") == 0); - uv_fs_req_cleanup(&read_req); - - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); - ASSERT(r == 0); - ASSERT(close_req.result == 0); - uv_fs_req_cleanup(&close_req); - - r = uv_fs_unlink(loop, &unlink_req, "test_file2", NULL); - ASSERT(r == 0); - ASSERT(unlink_req.result == 0); - uv_fs_req_cleanup(&unlink_req); - - /* Cleanup */ - unlink("test_file"); - unlink("test_file2"); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(fs_file_write_null_buffer) { - int r; - - /* Setup. */ - unlink("test_file"); - - loop = uv_default_loop(); - - r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT, - S_IWUSR | S_IRUSR, NULL); - ASSERT(r >= 0); - ASSERT(open_req1.result >= 0); - uv_fs_req_cleanup(&open_req1); - - iov = uv_buf_init(NULL, 0); - r = uv_fs_write(loop, &write_req, open_req1.result, &iov, 1, -1, NULL); - ASSERT(r == 0); - ASSERT(write_req.result == 0); - uv_fs_req_cleanup(&write_req); - - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); - ASSERT(r == 0); - ASSERT(close_req.result == 0); - uv_fs_req_cleanup(&close_req); - - unlink("test_file"); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(fs_async_dir) { - int r; - uv_dirent_t dent; - - /* Setup */ - unlink("test_dir/file1"); - unlink("test_dir/file2"); - rmdir("test_dir"); - - loop = uv_default_loop(); - - r = uv_fs_mkdir(loop, &mkdir_req, "test_dir", 0755, mkdir_cb); - ASSERT(r == 0); - - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(mkdir_cb_count == 1); - - /* Create 2 files synchronously. */ - r = uv_fs_open(loop, &open_req1, "test_dir/file1", O_WRONLY | O_CREAT, - S_IWUSR | S_IRUSR, NULL); - ASSERT(r >= 0); - uv_fs_req_cleanup(&open_req1); - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); - ASSERT(r == 0); - uv_fs_req_cleanup(&close_req); - - r = uv_fs_open(loop, &open_req1, "test_dir/file2", O_WRONLY | O_CREAT, - S_IWUSR | S_IRUSR, NULL); - ASSERT(r >= 0); - uv_fs_req_cleanup(&open_req1); - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); - ASSERT(r == 0); - uv_fs_req_cleanup(&close_req); - - r = uv_fs_scandir(loop, &scandir_req, "test_dir", 0, scandir_cb); - ASSERT(r == 0); - - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(scandir_cb_count == 1); - - /* sync uv_fs_scandir */ - r = uv_fs_scandir(loop, &scandir_req, "test_dir", 0, NULL); - ASSERT(r == 2); - ASSERT(scandir_req.result == 2); - ASSERT(scandir_req.ptr); - while (UV_EOF != uv_fs_scandir_next(&scandir_req, &dent)) { - ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0); - ASSERT(dent.type == UV_DIRENT_FILE || dent.type == UV_DIRENT_UNKNOWN); - } - uv_fs_req_cleanup(&scandir_req); - ASSERT(!scandir_req.ptr); - - r = uv_fs_stat(loop, &stat_req, "test_dir", stat_cb); - ASSERT(r == 0); - uv_run(loop, UV_RUN_DEFAULT); - - r = uv_fs_stat(loop, &stat_req, "test_dir/", stat_cb); - ASSERT(r == 0); - uv_run(loop, UV_RUN_DEFAULT); - - r = uv_fs_lstat(loop, &stat_req, "test_dir", stat_cb); - ASSERT(r == 0); - uv_run(loop, UV_RUN_DEFAULT); - - r = uv_fs_lstat(loop, &stat_req, "test_dir/", stat_cb); - ASSERT(r == 0); - uv_run(loop, UV_RUN_DEFAULT); - - ASSERT(stat_cb_count == 4); - - r = uv_fs_unlink(loop, &unlink_req, "test_dir/file1", unlink_cb); - ASSERT(r == 0); - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(unlink_cb_count == 1); - - r = uv_fs_unlink(loop, &unlink_req, "test_dir/file2", unlink_cb); - ASSERT(r == 0); - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(unlink_cb_count == 2); - - r = uv_fs_rmdir(loop, &rmdir_req, "test_dir", rmdir_cb); - ASSERT(r == 0); - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(rmdir_cb_count == 1); - - /* Cleanup */ - unlink("test_dir/file1"); - unlink("test_dir/file2"); - rmdir("test_dir"); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(fs_async_sendfile) { - int f, r; - struct stat s1, s2; - - loop = uv_default_loop(); - - /* Setup. */ - unlink("test_file"); - unlink("test_file2"); - - f = open("test_file", O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR); - ASSERT(f != -1); - - r = write(f, "begin\n", 6); - ASSERT(r == 6); - - r = lseek(f, 65536, SEEK_CUR); - ASSERT(r == 65542); - - r = write(f, "end\n", 4); - ASSERT(r != -1); - - r = close(f); - ASSERT(r == 0); - - /* Test starts here. */ - r = uv_fs_open(loop, &open_req1, "test_file", O_RDWR, 0, NULL); - ASSERT(r >= 0); - ASSERT(open_req1.result >= 0); - uv_fs_req_cleanup(&open_req1); - - r = uv_fs_open(loop, &open_req2, "test_file2", O_WRONLY | O_CREAT, - S_IWUSR | S_IRUSR, NULL); - ASSERT(r >= 0); - ASSERT(open_req2.result >= 0); - uv_fs_req_cleanup(&open_req2); - - r = uv_fs_sendfile(loop, &sendfile_req, open_req2.result, open_req1.result, - 0, 131072, sendfile_cb); - ASSERT(r == 0); - uv_run(loop, UV_RUN_DEFAULT); - - ASSERT(sendfile_cb_count == 1); - - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); - ASSERT(r == 0); - uv_fs_req_cleanup(&close_req); - r = uv_fs_close(loop, &close_req, open_req2.result, NULL); - ASSERT(r == 0); - uv_fs_req_cleanup(&close_req); - - stat("test_file", &s1); - stat("test_file2", &s2); - ASSERT(65546 == s2.st_size && s1.st_size == s2.st_size); - - /* Cleanup. */ - unlink("test_file"); - unlink("test_file2"); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(fs_mkdtemp) { - int r; - const char* path_template = "test_dir_XXXXXX"; - - loop = uv_default_loop(); - - r = uv_fs_mkdtemp(loop, &mkdtemp_req1, path_template, mkdtemp_cb); - ASSERT(r == 0); - - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(mkdtemp_cb_count == 1); - - /* sync mkdtemp */ - r = uv_fs_mkdtemp(loop, &mkdtemp_req2, path_template, NULL); - ASSERT(r == 0); - check_mkdtemp_result(&mkdtemp_req2); - - /* mkdtemp return different values on subsequent calls */ - ASSERT(strcmp(mkdtemp_req1.path, mkdtemp_req2.path) != 0); - - /* Cleanup */ - rmdir(mkdtemp_req1.path); - rmdir(mkdtemp_req2.path); - uv_fs_req_cleanup(&mkdtemp_req1); - uv_fs_req_cleanup(&mkdtemp_req2); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(fs_fstat) { - int r; - uv_fs_t req; - uv_file file; - uv_stat_t* s; -#ifndef _WIN32 - struct stat t; -#endif - - /* Setup. */ - unlink("test_file"); - - loop = uv_default_loop(); - - r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT, - S_IWUSR | S_IRUSR, NULL); - ASSERT(r >= 0); - ASSERT(req.result >= 0); - file = req.result; - uv_fs_req_cleanup(&req); - - iov = uv_buf_init(test_buf, sizeof(test_buf)); - r = uv_fs_write(loop, &req, file, &iov, 1, -1, NULL); - ASSERT(r == sizeof(test_buf)); - ASSERT(req.result == sizeof(test_buf)); - uv_fs_req_cleanup(&req); - - r = uv_fs_fstat(loop, &req, file, NULL); - ASSERT(r == 0); - ASSERT(req.result == 0); - s = req.ptr; - ASSERT(s->st_size == sizeof(test_buf)); - -#ifndef _WIN32 - r = fstat(file, &t); - ASSERT(r == 0); - - ASSERT(s->st_dev == (uint64_t) t.st_dev); - ASSERT(s->st_mode == (uint64_t) t.st_mode); - ASSERT(s->st_nlink == (uint64_t) t.st_nlink); - ASSERT(s->st_uid == (uint64_t) t.st_uid); - ASSERT(s->st_gid == (uint64_t) t.st_gid); - ASSERT(s->st_rdev == (uint64_t) t.st_rdev); - ASSERT(s->st_ino == (uint64_t) t.st_ino); - ASSERT(s->st_size == (uint64_t) t.st_size); - ASSERT(s->st_blksize == (uint64_t) t.st_blksize); - ASSERT(s->st_blocks == (uint64_t) t.st_blocks); -#if defined(__APPLE__) - ASSERT(s->st_atim.tv_sec == t.st_atimespec.tv_sec); - ASSERT(s->st_atim.tv_nsec == t.st_atimespec.tv_nsec); - ASSERT(s->st_mtim.tv_sec == t.st_mtimespec.tv_sec); - ASSERT(s->st_mtim.tv_nsec == t.st_mtimespec.tv_nsec); - ASSERT(s->st_ctim.tv_sec == t.st_ctimespec.tv_sec); - ASSERT(s->st_ctim.tv_nsec == t.st_ctimespec.tv_nsec); - ASSERT(s->st_birthtim.tv_sec == t.st_birthtimespec.tv_sec); - ASSERT(s->st_birthtim.tv_nsec == t.st_birthtimespec.tv_nsec); - ASSERT(s->st_flags == t.st_flags); - ASSERT(s->st_gen == t.st_gen); -#elif defined(_AIX) - ASSERT(s->st_atim.tv_sec == t.st_atime); - ASSERT(s->st_atim.tv_nsec == 0); - ASSERT(s->st_mtim.tv_sec == t.st_mtime); - ASSERT(s->st_mtim.tv_nsec == 0); - ASSERT(s->st_ctim.tv_sec == t.st_ctime); - ASSERT(s->st_ctim.tv_nsec == 0); -#elif defined(__sun) || \ - defined(_BSD_SOURCE) || \ - defined(_SVID_SOURCE) || \ - defined(_XOPEN_SOURCE) - ASSERT(s->st_atim.tv_sec == t.st_atim.tv_sec); - ASSERT(s->st_atim.tv_nsec == t.st_atim.tv_nsec); - ASSERT(s->st_mtim.tv_sec == t.st_mtim.tv_sec); - ASSERT(s->st_mtim.tv_nsec == t.st_mtim.tv_nsec); - ASSERT(s->st_ctim.tv_sec == t.st_ctim.tv_sec); - ASSERT(s->st_ctim.tv_nsec == t.st_ctim.tv_nsec); -# if defined(__DragonFly__) || \ - defined(__FreeBSD__) || \ - defined(__OpenBSD__) || \ - defined(__NetBSD__) - ASSERT(s->st_birthtim.tv_sec == t.st_birthtim.tv_sec); - ASSERT(s->st_birthtim.tv_nsec == t.st_birthtim.tv_nsec); - ASSERT(s->st_flags == t.st_flags); - ASSERT(s->st_gen == t.st_gen); -# endif -#else - ASSERT(s->st_atim.tv_sec == t.st_atime); - ASSERT(s->st_atim.tv_nsec == 0); - ASSERT(s->st_mtim.tv_sec == t.st_mtime); - ASSERT(s->st_mtim.tv_nsec == 0); - ASSERT(s->st_ctim.tv_sec == t.st_ctime); - ASSERT(s->st_ctim.tv_nsec == 0); -#endif -#endif - - uv_fs_req_cleanup(&req); - - /* Now do the uv_fs_fstat call asynchronously */ - r = uv_fs_fstat(loop, &req, file, fstat_cb); - ASSERT(r == 0); - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(fstat_cb_count == 1); - - - r = uv_fs_close(loop, &req, file, NULL); - ASSERT(r == 0); - ASSERT(req.result == 0); - uv_fs_req_cleanup(&req); - - /* - * Run the loop just to check we don't have make any extraneous uv_ref() - * calls. This should drop out immediately. - */ - uv_run(loop, UV_RUN_DEFAULT); - - /* Cleanup. */ - unlink("test_file"); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(fs_access) { - int r; - uv_fs_t req; - uv_file file; - - /* Setup. */ - unlink("test_file"); - - loop = uv_default_loop(); - - /* File should not exist */ - r = uv_fs_access(loop, &req, "test_file", F_OK, NULL); - ASSERT(r < 0); - ASSERT(req.result < 0); - uv_fs_req_cleanup(&req); - - /* File should not exist */ - r = uv_fs_access(loop, &req, "test_file", F_OK, access_cb); - ASSERT(r == 0); - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(access_cb_count == 1); - access_cb_count = 0; /* reset for the next test */ - - /* Create file */ - r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT, - S_IWUSR | S_IRUSR, NULL); - ASSERT(r >= 0); - ASSERT(req.result >= 0); - file = req.result; - uv_fs_req_cleanup(&req); - - /* File should exist */ - r = uv_fs_access(loop, &req, "test_file", F_OK, NULL); - ASSERT(r == 0); - ASSERT(req.result == 0); - uv_fs_req_cleanup(&req); - - /* File should exist */ - r = uv_fs_access(loop, &req, "test_file", F_OK, access_cb); - ASSERT(r == 0); - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(access_cb_count == 1); - access_cb_count = 0; /* reset for the next test */ - - /* Close file */ - r = uv_fs_close(loop, &req, file, NULL); - ASSERT(r == 0); - ASSERT(req.result == 0); - uv_fs_req_cleanup(&req); - - /* - * Run the loop just to check we don't have make any extraneous uv_ref() - * calls. This should drop out immediately. - */ - uv_run(loop, UV_RUN_DEFAULT); - - /* Cleanup. */ - unlink("test_file"); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(fs_chmod) { - int r; - uv_fs_t req; - uv_file file; - - /* Setup. */ - unlink("test_file"); - - loop = uv_default_loop(); - - r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT, - S_IWUSR | S_IRUSR, NULL); - ASSERT(r >= 0); - ASSERT(req.result >= 0); - file = req.result; - uv_fs_req_cleanup(&req); - - iov = uv_buf_init(test_buf, sizeof(test_buf)); - r = uv_fs_write(loop, &req, file, &iov, 1, -1, NULL); - ASSERT(r == sizeof(test_buf)); - ASSERT(req.result == sizeof(test_buf)); - uv_fs_req_cleanup(&req); - -#ifndef _WIN32 - /* Make the file write-only */ - r = uv_fs_chmod(loop, &req, "test_file", 0200, NULL); - ASSERT(r == 0); - ASSERT(req.result == 0); - uv_fs_req_cleanup(&req); - - check_permission("test_file", 0200); -#endif - - /* Make the file read-only */ - r = uv_fs_chmod(loop, &req, "test_file", 0400, NULL); - ASSERT(r == 0); - ASSERT(req.result == 0); - uv_fs_req_cleanup(&req); - - check_permission("test_file", 0400); - - /* Make the file read+write with sync uv_fs_fchmod */ - r = uv_fs_fchmod(loop, &req, file, 0600, NULL); - ASSERT(r == 0); - ASSERT(req.result == 0); - uv_fs_req_cleanup(&req); - - check_permission("test_file", 0600); - -#ifndef _WIN32 - /* async chmod */ - { - static int mode = 0200; - req.data = &mode; - } - r = uv_fs_chmod(loop, &req, "test_file", 0200, chmod_cb); - ASSERT(r == 0); - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(chmod_cb_count == 1); - chmod_cb_count = 0; /* reset for the next test */ -#endif - - /* async chmod */ - { - static int mode = 0400; - req.data = &mode; - } - r = uv_fs_chmod(loop, &req, "test_file", 0400, chmod_cb); - ASSERT(r == 0); - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(chmod_cb_count == 1); - - /* async fchmod */ - { - static int mode = 0600; - req.data = &mode; - } - r = uv_fs_fchmod(loop, &req, file, 0600, fchmod_cb); - ASSERT(r == 0); - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(fchmod_cb_count == 1); - - close(file); - - /* - * Run the loop just to check we don't have make any extraneous uv_ref() - * calls. This should drop out immediately. - */ - uv_run(loop, UV_RUN_DEFAULT); - - /* Cleanup. */ - unlink("test_file"); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(fs_chown) { - int r; - uv_fs_t req; - uv_file file; - - /* Setup. */ - unlink("test_file"); - - loop = uv_default_loop(); - - r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT, - S_IWUSR | S_IRUSR, NULL); - ASSERT(r >= 0); - ASSERT(req.result >= 0); - file = req.result; - uv_fs_req_cleanup(&req); - - /* sync chown */ - r = uv_fs_chown(loop, &req, "test_file", -1, -1, NULL); - ASSERT(r == 0); - ASSERT(req.result == 0); - uv_fs_req_cleanup(&req); - - /* sync fchown */ - r = uv_fs_fchown(loop, &req, file, -1, -1, NULL); - ASSERT(r == 0); - ASSERT(req.result == 0); - uv_fs_req_cleanup(&req); - - /* async chown */ - r = uv_fs_chown(loop, &req, "test_file", -1, -1, chown_cb); - ASSERT(r == 0); - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(chown_cb_count == 1); - - /* chown to root (fail) */ - chown_cb_count = 0; - r = uv_fs_chown(loop, &req, "test_file", 0, 0, chown_root_cb); - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(chown_cb_count == 1); - - /* async fchown */ - r = uv_fs_fchown(loop, &req, file, -1, -1, fchown_cb); - ASSERT(r == 0); - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(fchown_cb_count == 1); - - close(file); - - /* - * Run the loop just to check we don't have make any extraneous uv_ref() - * calls. This should drop out immediately. - */ - uv_run(loop, UV_RUN_DEFAULT); - - /* Cleanup. */ - unlink("test_file"); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(fs_link) { - int r; - uv_fs_t req; - uv_file file; - uv_file link; - - /* Setup. */ - unlink("test_file"); - unlink("test_file_link"); - unlink("test_file_link2"); - - loop = uv_default_loop(); - - r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT, - S_IWUSR | S_IRUSR, NULL); - ASSERT(r >= 0); - ASSERT(req.result >= 0); - file = req.result; - uv_fs_req_cleanup(&req); - - iov = uv_buf_init(test_buf, sizeof(test_buf)); - r = uv_fs_write(loop, &req, file, &iov, 1, -1, NULL); - ASSERT(r == sizeof(test_buf)); - ASSERT(req.result == sizeof(test_buf)); - uv_fs_req_cleanup(&req); - - close(file); - - /* sync link */ - r = uv_fs_link(loop, &req, "test_file", "test_file_link", NULL); - ASSERT(r == 0); - ASSERT(req.result == 0); - uv_fs_req_cleanup(&req); - - r = uv_fs_open(loop, &req, "test_file_link", O_RDWR, 0, NULL); - ASSERT(r >= 0); - ASSERT(req.result >= 0); - link = req.result; - uv_fs_req_cleanup(&req); - - memset(buf, 0, sizeof(buf)); - iov = uv_buf_init(buf, sizeof(buf)); - r = uv_fs_read(loop, &req, link, &iov, 1, 0, NULL); - ASSERT(r >= 0); - ASSERT(req.result >= 0); - ASSERT(strcmp(buf, test_buf) == 0); - - close(link); - - /* async link */ - r = uv_fs_link(loop, &req, "test_file", "test_file_link2", link_cb); - ASSERT(r == 0); - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(link_cb_count == 1); - - r = uv_fs_open(loop, &req, "test_file_link2", O_RDWR, 0, NULL); - ASSERT(r >= 0); - ASSERT(req.result >= 0); - link = req.result; - uv_fs_req_cleanup(&req); - - memset(buf, 0, sizeof(buf)); - iov = uv_buf_init(buf, sizeof(buf)); - r = uv_fs_read(loop, &req, link, &iov, 1, 0, NULL); - ASSERT(r >= 0); - ASSERT(req.result >= 0); - ASSERT(strcmp(buf, test_buf) == 0); - - close(link); - - /* - * Run the loop just to check we don't have make any extraneous uv_ref() - * calls. This should drop out immediately. - */ - uv_run(loop, UV_RUN_DEFAULT); - - /* Cleanup. */ - unlink("test_file"); - unlink("test_file_link"); - unlink("test_file_link2"); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(fs_readlink) { - uv_fs_t req; - - loop = uv_default_loop(); - ASSERT(0 == uv_fs_readlink(loop, &req, "no_such_file", dummy_cb)); - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - ASSERT(dummy_cb_count == 1); - ASSERT(req.ptr == NULL); - ASSERT(req.result == UV_ENOENT); - uv_fs_req_cleanup(&req); - - ASSERT(UV_ENOENT == uv_fs_readlink(loop, &req, "no_such_file", NULL)); - ASSERT(req.ptr == NULL); - ASSERT(req.result == UV_ENOENT); - uv_fs_req_cleanup(&req); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(fs_symlink) { - int r; - uv_fs_t req; - uv_file file; - uv_file link; - - /* Setup. */ - unlink("test_file"); - unlink("test_file_symlink"); - unlink("test_file_symlink2"); - unlink("test_file_symlink_symlink"); - unlink("test_file_symlink2_symlink"); - - loop = uv_default_loop(); - - r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT, - S_IWUSR | S_IRUSR, NULL); - ASSERT(r >= 0); - ASSERT(req.result >= 0); - file = req.result; - uv_fs_req_cleanup(&req); - - iov = uv_buf_init(test_buf, sizeof(test_buf)); - r = uv_fs_write(loop, &req, file, &iov, 1, -1, NULL); - ASSERT(r == sizeof(test_buf)); - ASSERT(req.result == sizeof(test_buf)); - uv_fs_req_cleanup(&req); - - close(file); - - /* sync symlink */ - r = uv_fs_symlink(loop, &req, "test_file", "test_file_symlink", 0, NULL); -#ifdef _WIN32 - if (r < 0) { - if (r == UV_ENOTSUP) { - /* - * Windows doesn't support symlinks on older versions. - * We just pass the test and bail out early if we get ENOTSUP. - */ - return 0; - } else if (r == UV_EPERM) { - /* - * Creating a symlink is only allowed when running elevated. - * We pass the test and bail out early if we get UV_EPERM. - */ - return 0; - } - } -#endif - ASSERT(r == 0); - ASSERT(req.result == 0); - uv_fs_req_cleanup(&req); - - r = uv_fs_open(loop, &req, "test_file_symlink", O_RDWR, 0, NULL); - ASSERT(r >= 0); - ASSERT(req.result >= 0); - link = req.result; - uv_fs_req_cleanup(&req); - - memset(buf, 0, sizeof(buf)); - iov = uv_buf_init(buf, sizeof(buf)); - r = uv_fs_read(loop, &req, link, &iov, 1, 0, NULL); - ASSERT(r >= 0); - ASSERT(req.result >= 0); - ASSERT(strcmp(buf, test_buf) == 0); - - close(link); - - r = uv_fs_symlink(loop, - &req, - "test_file_symlink", - "test_file_symlink_symlink", - 0, - NULL); - ASSERT(r == 0); - uv_fs_req_cleanup(&req); - - r = uv_fs_readlink(loop, &req, "test_file_symlink_symlink", NULL); - ASSERT(r == 0); - ASSERT(strcmp(req.ptr, "test_file_symlink") == 0); - uv_fs_req_cleanup(&req); - - /* async link */ - r = uv_fs_symlink(loop, - &req, - "test_file", - "test_file_symlink2", - 0, - symlink_cb); - ASSERT(r == 0); - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(symlink_cb_count == 1); - - r = uv_fs_open(loop, &req, "test_file_symlink2", O_RDWR, 0, NULL); - ASSERT(r >= 0); - ASSERT(req.result >= 0); - link = req.result; - uv_fs_req_cleanup(&req); - - memset(buf, 0, sizeof(buf)); - iov = uv_buf_init(buf, sizeof(buf)); - r = uv_fs_read(loop, &req, link, &iov, 1, 0, NULL); - ASSERT(r >= 0); - ASSERT(req.result >= 0); - ASSERT(strcmp(buf, test_buf) == 0); - - close(link); - - r = uv_fs_symlink(loop, - &req, - "test_file_symlink2", - "test_file_symlink2_symlink", - 0, - NULL); - ASSERT(r == 0); - uv_fs_req_cleanup(&req); - - r = uv_fs_readlink(loop, &req, "test_file_symlink2_symlink", readlink_cb); - ASSERT(r == 0); - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(readlink_cb_count == 1); - - /* - * Run the loop just to check we don't have make any extraneous uv_ref() - * calls. This should drop out immediately. - */ - uv_run(loop, UV_RUN_DEFAULT); - - /* Cleanup. */ - unlink("test_file"); - unlink("test_file_symlink"); - unlink("test_file_symlink_symlink"); - unlink("test_file_symlink2"); - unlink("test_file_symlink2_symlink"); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(fs_symlink_dir) { - uv_fs_t req; - int r; - char* test_dir; - uv_dirent_t dent; - - /* set-up */ - unlink("test_dir/file1"); - unlink("test_dir/file2"); - rmdir("test_dir"); - rmdir("test_dir_symlink"); - - loop = uv_default_loop(); - - uv_fs_mkdir(loop, &req, "test_dir", 0777, NULL); - uv_fs_req_cleanup(&req); - -#ifdef _WIN32 - { - static char src_path_buf[PATHMAX]; - size_t size; - size = sizeof(src_path_buf); - strcpy(src_path_buf, "\\\\?\\"); - uv_cwd(src_path_buf + 4, &size); - strcat(src_path_buf, "\\test_dir\\"); - test_dir = src_path_buf; - } -#else - test_dir = "test_dir"; -#endif - - r = uv_fs_symlink(loop, &req, test_dir, "test_dir_symlink", - UV_FS_SYMLINK_JUNCTION, NULL); - ASSERT(r == 0); - ASSERT(req.result == 0); - uv_fs_req_cleanup(&req); - - r = uv_fs_stat(loop, &req, "test_dir_symlink", NULL); - ASSERT(r == 0); - ASSERT(((uv_stat_t*)req.ptr)->st_mode & S_IFDIR); - uv_fs_req_cleanup(&req); - - r = uv_fs_lstat(loop, &req, "test_dir_symlink", NULL); - ASSERT(r == 0); - ASSERT(((uv_stat_t*)req.ptr)->st_mode & S_IFLNK); -#ifdef _WIN32 - ASSERT(((uv_stat_t*)req.ptr)->st_size == strlen(test_dir + 4)); -#else - ASSERT(((uv_stat_t*)req.ptr)->st_size == strlen(test_dir)); -#endif - uv_fs_req_cleanup(&req); - - r = uv_fs_readlink(loop, &req, "test_dir_symlink", NULL); - ASSERT(r == 0); -#ifdef _WIN32 - ASSERT(strcmp(req.ptr, test_dir + 4) == 0); -#else - ASSERT(strcmp(req.ptr, test_dir) == 0); -#endif - uv_fs_req_cleanup(&req); - - r = uv_fs_open(loop, &open_req1, "test_dir/file1", O_WRONLY | O_CREAT, - S_IWUSR | S_IRUSR, NULL); - ASSERT(r >= 0); - uv_fs_req_cleanup(&open_req1); - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); - ASSERT(r == 0); - uv_fs_req_cleanup(&close_req); - - r = uv_fs_open(loop, &open_req1, "test_dir/file2", O_WRONLY | O_CREAT, - S_IWUSR | S_IRUSR, NULL); - ASSERT(r >= 0); - uv_fs_req_cleanup(&open_req1); - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); - ASSERT(r == 0); - uv_fs_req_cleanup(&close_req); - - r = uv_fs_scandir(loop, &scandir_req, "test_dir_symlink", 0, NULL); - ASSERT(r == 2); - ASSERT(scandir_req.result == 2); - ASSERT(scandir_req.ptr); - while (UV_EOF != uv_fs_scandir_next(&scandir_req, &dent)) { - ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0); - ASSERT(dent.type == UV_DIRENT_FILE || dent.type == UV_DIRENT_UNKNOWN); - } - uv_fs_req_cleanup(&scandir_req); - ASSERT(!scandir_req.ptr); - - /* unlink will remove the directory symlink */ - r = uv_fs_unlink(loop, &req, "test_dir_symlink", NULL); - ASSERT(r == 0); - uv_fs_req_cleanup(&req); - - r = uv_fs_scandir(loop, &scandir_req, "test_dir_symlink", 0, NULL); - ASSERT(r == UV_ENOENT); - uv_fs_req_cleanup(&scandir_req); - - r = uv_fs_scandir(loop, &scandir_req, "test_dir", 0, NULL); - ASSERT(r == 2); - ASSERT(scandir_req.result == 2); - ASSERT(scandir_req.ptr); - while (UV_EOF != uv_fs_scandir_next(&scandir_req, &dent)) { - ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0); - ASSERT(dent.type == UV_DIRENT_FILE || dent.type == UV_DIRENT_UNKNOWN); - } - uv_fs_req_cleanup(&scandir_req); - ASSERT(!scandir_req.ptr); - - /* clean-up */ - unlink("test_dir/file1"); - unlink("test_dir/file2"); - rmdir("test_dir"); - rmdir("test_dir_symlink"); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(fs_utime) { - utime_check_t checkme; - const char* path = "test_file"; - double atime; - double mtime; - uv_fs_t req; - int r; - - /* Setup. */ - loop = uv_default_loop(); - unlink(path); - r = uv_fs_open(loop, &req, path, O_RDWR | O_CREAT, - S_IWUSR | S_IRUSR, NULL); - ASSERT(r >= 0); - ASSERT(req.result >= 0); - uv_fs_req_cleanup(&req); - close(r); - - atime = mtime = 400497753; /* 1982-09-10 11:22:33 */ - - r = uv_fs_utime(loop, &req, path, atime, mtime, NULL); - ASSERT(r == 0); - ASSERT(req.result == 0); - uv_fs_req_cleanup(&req); - - r = uv_fs_stat(loop, &req, path, NULL); - ASSERT(r == 0); - ASSERT(req.result == 0); - check_utime(path, atime, mtime); - uv_fs_req_cleanup(&req); - - atime = mtime = 1291404900; /* 2010-12-03 20:35:00 - mees <3 */ - checkme.path = path; - checkme.atime = atime; - checkme.mtime = mtime; - - /* async utime */ - utime_req.data = &checkme; - r = uv_fs_utime(loop, &utime_req, path, atime, mtime, utime_cb); - ASSERT(r == 0); - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(utime_cb_count == 1); - - /* Cleanup. */ - unlink(path); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -#ifdef _WIN32 -TEST_IMPL(fs_stat_root) { - int r; - uv_loop_t* loop = uv_default_loop(); - - r = uv_fs_stat(loop, &stat_req, "\\", NULL); - ASSERT(r == 0); - - r = uv_fs_stat(loop, &stat_req, "..\\..\\..\\..\\..\\..\\..", NULL); - ASSERT(r == 0); - - r = uv_fs_stat(loop, &stat_req, "..", NULL); - ASSERT(r == 0); - - r = uv_fs_stat(loop, &stat_req, "..\\", NULL); - ASSERT(r == 0); - - /* stats the current directory on c: */ - r = uv_fs_stat(loop, &stat_req, "c:", NULL); - ASSERT(r == 0); - - r = uv_fs_stat(loop, &stat_req, "c:\\", NULL); - ASSERT(r == 0); - - r = uv_fs_stat(loop, &stat_req, "\\\\?\\C:\\", NULL); - ASSERT(r == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} -#endif - - -TEST_IMPL(fs_futime) { - utime_check_t checkme; - const char* path = "test_file"; - double atime; - double mtime; - uv_file file; - uv_fs_t req; - int r; - - /* Setup. */ - loop = uv_default_loop(); - unlink(path); - r = uv_fs_open(loop, &req, path, O_RDWR | O_CREAT, - S_IWUSR | S_IRUSR, NULL); - ASSERT(r >= 0); - ASSERT(req.result >= 0); - uv_fs_req_cleanup(&req); - close(r); - - atime = mtime = 400497753; /* 1982-09-10 11:22:33 */ - - r = uv_fs_open(loop, &req, path, O_RDWR, 0, NULL); - ASSERT(r >= 0); - ASSERT(req.result >= 0); - file = req.result; /* FIXME probably not how it's supposed to be used */ - uv_fs_req_cleanup(&req); - - r = uv_fs_futime(loop, &req, file, atime, mtime, NULL); - ASSERT(r == 0); - ASSERT(req.result == 0); - uv_fs_req_cleanup(&req); - - r = uv_fs_stat(loop, &req, path, NULL); - ASSERT(r == 0); - ASSERT(req.result == 0); - check_utime(path, atime, mtime); - uv_fs_req_cleanup(&req); - - atime = mtime = 1291404900; /* 2010-12-03 20:35:00 - mees <3 */ - - checkme.atime = atime; - checkme.mtime = mtime; - checkme.path = path; - - /* async futime */ - futime_req.data = &checkme; - r = uv_fs_futime(loop, &futime_req, file, atime, mtime, futime_cb); - ASSERT(r == 0); - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(futime_cb_count == 1); - - /* Cleanup. */ - unlink(path); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(fs_stat_missing_path) { - uv_fs_t req; - int r; - - loop = uv_default_loop(); - - r = uv_fs_stat(loop, &req, "non_existent_file", NULL); - ASSERT(r == UV_ENOENT); - ASSERT(req.result == UV_ENOENT); - uv_fs_req_cleanup(&req); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(fs_scandir_empty_dir) { - const char* path; - uv_fs_t req; - uv_dirent_t dent; - int r; - - path = "./empty_dir/"; - loop = uv_default_loop(); - - uv_fs_mkdir(loop, &req, path, 0777, NULL); - uv_fs_req_cleanup(&req); - - /* Fill the req to ensure that required fields are cleaned up */ - memset(&req, 0xdb, sizeof(req)); - - r = uv_fs_scandir(loop, &req, path, 0, NULL); - ASSERT(r == 0); - ASSERT(req.result == 0); - ASSERT(req.ptr == NULL); - ASSERT(UV_EOF == uv_fs_scandir_next(&req, &dent)); - uv_fs_req_cleanup(&req); - - r = uv_fs_scandir(loop, &scandir_req, path, 0, empty_scandir_cb); - ASSERT(r == 0); - - ASSERT(scandir_cb_count == 0); - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(scandir_cb_count == 1); - - uv_fs_rmdir(loop, &req, path, NULL); - uv_fs_req_cleanup(&req); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(fs_scandir_file) { - const char* path; - int r; - - path = "test/fixtures/empty_file"; - loop = uv_default_loop(); - - r = uv_fs_scandir(loop, &scandir_req, path, 0, NULL); - ASSERT(r == UV_ENOTDIR); - uv_fs_req_cleanup(&scandir_req); - - r = uv_fs_scandir(loop, &scandir_req, path, 0, file_scandir_cb); - ASSERT(r == 0); - - ASSERT(scandir_cb_count == 0); - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(scandir_cb_count == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(fs_open_dir) { - const char* path; - uv_fs_t req; - int r, file; - - path = "."; - loop = uv_default_loop(); - - r = uv_fs_open(loop, &req, path, O_RDONLY, 0, NULL); - ASSERT(r >= 0); - ASSERT(req.result >= 0); - ASSERT(req.ptr == NULL); - file = r; - uv_fs_req_cleanup(&req); - - r = uv_fs_close(loop, &req, file, NULL); - ASSERT(r == 0); - - r = uv_fs_open(loop, &req, path, O_RDONLY, 0, open_cb_simple); - ASSERT(r == 0); - - ASSERT(open_cb_count == 0); - uv_run(loop, UV_RUN_DEFAULT); - ASSERT(open_cb_count == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(fs_file_open_append) { - int r; - - /* Setup. */ - unlink("test_file"); - - loop = uv_default_loop(); - - r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT, - S_IWUSR | S_IRUSR, NULL); - ASSERT(r >= 0); - ASSERT(open_req1.result >= 0); - uv_fs_req_cleanup(&open_req1); - - iov = uv_buf_init(test_buf, sizeof(test_buf)); - r = uv_fs_write(loop, &write_req, open_req1.result, &iov, 1, -1, NULL); - ASSERT(r >= 0); - ASSERT(write_req.result >= 0); - uv_fs_req_cleanup(&write_req); - - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); - ASSERT(r == 0); - ASSERT(close_req.result == 0); - uv_fs_req_cleanup(&close_req); - - r = uv_fs_open(loop, &open_req1, "test_file", O_RDWR | O_APPEND, 0, NULL); - ASSERT(r >= 0); - ASSERT(open_req1.result >= 0); - uv_fs_req_cleanup(&open_req1); - - iov = uv_buf_init(test_buf, sizeof(test_buf)); - r = uv_fs_write(loop, &write_req, open_req1.result, &iov, 1, -1, NULL); - ASSERT(r >= 0); - ASSERT(write_req.result >= 0); - uv_fs_req_cleanup(&write_req); - - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); - ASSERT(r == 0); - ASSERT(close_req.result == 0); - uv_fs_req_cleanup(&close_req); - - r = uv_fs_open(loop, &open_req1, "test_file", O_RDONLY, S_IRUSR, NULL); - ASSERT(r >= 0); - ASSERT(open_req1.result >= 0); - uv_fs_req_cleanup(&open_req1); - - iov = uv_buf_init(buf, sizeof(buf)); - r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1, - NULL); - printf("read = %d\n", r); - ASSERT(r == 26); - ASSERT(read_req.result == 26); - ASSERT(memcmp(buf, - "test-buffer\n\0test-buffer\n\0", - sizeof("test-buffer\n\0test-buffer\n\0") - 1) == 0); - uv_fs_req_cleanup(&read_req); - - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); - ASSERT(r == 0); - ASSERT(close_req.result == 0); - uv_fs_req_cleanup(&close_req); - - /* Cleanup */ - unlink("test_file"); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(fs_rename_to_existing_file) { - int r; - - /* Setup. */ - unlink("test_file"); - unlink("test_file2"); - - loop = uv_default_loop(); - - r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT, - S_IWUSR | S_IRUSR, NULL); - ASSERT(r >= 0); - ASSERT(open_req1.result >= 0); - uv_fs_req_cleanup(&open_req1); - - iov = uv_buf_init(test_buf, sizeof(test_buf)); - r = uv_fs_write(loop, &write_req, open_req1.result, &iov, 1, -1, NULL); - ASSERT(r >= 0); - ASSERT(write_req.result >= 0); - uv_fs_req_cleanup(&write_req); - - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); - ASSERT(r == 0); - ASSERT(close_req.result == 0); - uv_fs_req_cleanup(&close_req); - - r = uv_fs_open(loop, &open_req1, "test_file2", O_WRONLY | O_CREAT, - S_IWUSR | S_IRUSR, NULL); - ASSERT(r >= 0); - ASSERT(open_req1.result >= 0); - uv_fs_req_cleanup(&open_req1); - - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); - ASSERT(r == 0); - ASSERT(close_req.result == 0); - uv_fs_req_cleanup(&close_req); - - r = uv_fs_rename(loop, &rename_req, "test_file", "test_file2", NULL); - ASSERT(r == 0); - ASSERT(rename_req.result == 0); - uv_fs_req_cleanup(&rename_req); - - r = uv_fs_open(loop, &open_req1, "test_file2", O_RDONLY, 0, NULL); - ASSERT(r >= 0); - ASSERT(open_req1.result >= 0); - uv_fs_req_cleanup(&open_req1); - - memset(buf, 0, sizeof(buf)); - iov = uv_buf_init(buf, sizeof(buf)); - r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1, - NULL); - ASSERT(r >= 0); - ASSERT(read_req.result >= 0); - ASSERT(strcmp(buf, test_buf) == 0); - uv_fs_req_cleanup(&read_req); - - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); - ASSERT(r == 0); - ASSERT(close_req.result == 0); - uv_fs_req_cleanup(&close_req); - - /* Cleanup */ - unlink("test_file"); - unlink("test_file2"); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(fs_read_file_eof) { - int r; - - /* Setup. */ - unlink("test_file"); - - loop = uv_default_loop(); - - r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT, - S_IWUSR | S_IRUSR, NULL); - ASSERT(r >= 0); - ASSERT(open_req1.result >= 0); - uv_fs_req_cleanup(&open_req1); - - iov = uv_buf_init(test_buf, sizeof(test_buf)); - r = uv_fs_write(loop, &write_req, open_req1.result, &iov, 1, -1, NULL); - ASSERT(r >= 0); - ASSERT(write_req.result >= 0); - uv_fs_req_cleanup(&write_req); - - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); - ASSERT(r == 0); - ASSERT(close_req.result == 0); - uv_fs_req_cleanup(&close_req); - - r = uv_fs_open(loop, &open_req1, "test_file", O_RDONLY, 0, NULL); - ASSERT(r >= 0); - ASSERT(open_req1.result >= 0); - uv_fs_req_cleanup(&open_req1); - - memset(buf, 0, sizeof(buf)); - iov = uv_buf_init(buf, sizeof(buf)); - r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1, NULL); - ASSERT(r >= 0); - ASSERT(read_req.result >= 0); - ASSERT(strcmp(buf, test_buf) == 0); - uv_fs_req_cleanup(&read_req); - - iov = uv_buf_init(buf, sizeof(buf)); - r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, - read_req.result, NULL); - ASSERT(r == 0); - ASSERT(read_req.result == 0); - uv_fs_req_cleanup(&read_req); - - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); - ASSERT(r == 0); - ASSERT(close_req.result == 0); - uv_fs_req_cleanup(&close_req); - - /* Cleanup */ - unlink("test_file"); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(fs_write_multiple_bufs) { - uv_buf_t iovs[2]; - int r; - - /* Setup. */ - unlink("test_file"); - - loop = uv_default_loop(); - - r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT, - S_IWUSR | S_IRUSR, NULL); - ASSERT(r >= 0); - ASSERT(open_req1.result >= 0); - uv_fs_req_cleanup(&open_req1); - - iovs[0] = uv_buf_init(test_buf, sizeof(test_buf)); - iovs[1] = uv_buf_init(test_buf2, sizeof(test_buf2)); - r = uv_fs_write(loop, &write_req, open_req1.result, iovs, 2, 0, NULL); - ASSERT(r >= 0); - ASSERT(write_req.result >= 0); - uv_fs_req_cleanup(&write_req); - - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); - ASSERT(r == 0); - ASSERT(close_req.result == 0); - uv_fs_req_cleanup(&close_req); - - r = uv_fs_open(loop, &open_req1, "test_file", O_RDONLY, 0, NULL); - ASSERT(r >= 0); - ASSERT(open_req1.result >= 0); - uv_fs_req_cleanup(&open_req1); - - memset(buf, 0, sizeof(buf)); - memset(buf2, 0, sizeof(buf2)); - /* Read the strings back to separate buffers. */ - iovs[0] = uv_buf_init(buf, sizeof(test_buf)); - iovs[1] = uv_buf_init(buf2, sizeof(test_buf2)); - r = uv_fs_read(loop, &read_req, open_req1.result, iovs, 2, 0, NULL); - ASSERT(r >= 0); - ASSERT(read_req.result >= 0); - ASSERT(strcmp(buf, test_buf) == 0); - ASSERT(strcmp(buf2, test_buf2) == 0); - uv_fs_req_cleanup(&read_req); - - iov = uv_buf_init(buf, sizeof(buf)); - r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, - read_req.result, NULL); - ASSERT(r == 0); - ASSERT(read_req.result == 0); - uv_fs_req_cleanup(&read_req); - - r = uv_fs_close(loop, &close_req, open_req1.result, NULL); - ASSERT(r == 0); - ASSERT(close_req.result == 0); - uv_fs_req_cleanup(&close_req); - - /* Cleanup */ - unlink("test_file"); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-get-currentexe.c b/libuv/test/test-get-currentexe.c deleted file mode 100644 index 0e9d696..0000000 --- a/libuv/test/test-get-currentexe.c +++ /dev/null @@ -1,86 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" -#include - -#define PATHMAX 1024 -extern char executable_path[]; - -TEST_IMPL(get_currentexe) { - char buffer[PATHMAX]; - size_t size; - char* match; - char* path; - int r; - - size = sizeof(buffer) / sizeof(buffer[0]); - r = uv_exepath(buffer, &size); - ASSERT(!r); - - /* uv_exepath can return an absolute path on darwin, so if the test runner - * was run with a relative prefix of "./", we need to strip that prefix off - * executable_path or we'll fail. */ - if (executable_path[0] == '.' && executable_path[1] == '/') { - path = executable_path + 2; - } else { - path = executable_path; - } - - match = strstr(buffer, path); - /* Verify that the path returned from uv_exepath is a subdirectory of - * executable_path. - */ - ASSERT(match && !strcmp(match, path)); - ASSERT(size == strlen(buffer)); - - /* Negative tests */ - size = sizeof(buffer) / sizeof(buffer[0]); - r = uv_exepath(NULL, &size); - ASSERT(r == UV_EINVAL); - - r = uv_exepath(buffer, NULL); - ASSERT(r == UV_EINVAL); - - size = 0; - r = uv_exepath(buffer, &size); - ASSERT(r == UV_EINVAL); - - memset(buffer, -1, sizeof(buffer)); - - size = 1; - r = uv_exepath(buffer, &size); - ASSERT(r == 0); - ASSERT(size == 0); - ASSERT(buffer[0] == '\0'); - - memset(buffer, -1, sizeof(buffer)); - - size = 2; - r = uv_exepath(buffer, &size); - ASSERT(r == 0); - ASSERT(size == 1); - ASSERT(buffer[0] != '\0'); - ASSERT(buffer[1] == '\0'); - - return 0; -} diff --git a/libuv/test/test-get-loadavg.c b/libuv/test/test-get-loadavg.c deleted file mode 100644 index 7465e18..0000000 --- a/libuv/test/test-get-loadavg.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -TEST_IMPL(get_loadavg) { - - double avg[3]; - uv_loadavg(avg); - - ASSERT(avg != NULL); - ASSERT(avg[0] >= 0); - ASSERT(avg[1] >= 0); - ASSERT(avg[2] >= 0); - - return 0; -} diff --git a/libuv/test/test-get-memory.c b/libuv/test/test-get-memory.c deleted file mode 100644 index 2396939..0000000 --- a/libuv/test/test-get-memory.c +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -TEST_IMPL(get_memory) { - uint64_t free_mem = uv_get_free_memory(); - uint64_t total_mem = uv_get_total_memory(); - - printf("free_mem=%llu, total_mem=%llu\n", - (unsigned long long) free_mem, - (unsigned long long) total_mem); - - ASSERT(free_mem > 0); - ASSERT(total_mem > 0); - ASSERT(total_mem > free_mem); - - return 0; -} diff --git a/libuv/test/test-getaddrinfo.c b/libuv/test/test-getaddrinfo.c deleted file mode 100644 index 45813c3..0000000 --- a/libuv/test/test-getaddrinfo.c +++ /dev/null @@ -1,182 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" -#include - -#define CONCURRENT_COUNT 10 - -static const char* name = "localhost"; - -static int getaddrinfo_cbs = 0; - -/* data used for running multiple calls concurrently */ -static uv_getaddrinfo_t* getaddrinfo_handle; -static uv_getaddrinfo_t getaddrinfo_handles[CONCURRENT_COUNT]; -static int callback_counts[CONCURRENT_COUNT]; -static int fail_cb_called; - - -static void getaddrinfo_fail_cb(uv_getaddrinfo_t* req, - int status, - struct addrinfo* res) { - ASSERT(fail_cb_called == 0); - ASSERT(status < 0); - ASSERT(res == NULL); - uv_freeaddrinfo(res); /* Should not crash. */ - fail_cb_called++; -} - - -static void getaddrinfo_basic_cb(uv_getaddrinfo_t* handle, - int status, - struct addrinfo* res) { - ASSERT(handle == getaddrinfo_handle); - getaddrinfo_cbs++; - free(handle); - uv_freeaddrinfo(res); -} - - -static void getaddrinfo_cuncurrent_cb(uv_getaddrinfo_t* handle, - int status, - struct addrinfo* res) { - int i; - int* data = (int*)handle->data; - - for (i = 0; i < CONCURRENT_COUNT; i++) { - if (&getaddrinfo_handles[i] == handle) { - ASSERT(i == *data); - - callback_counts[i]++; - break; - } - } - ASSERT (i < CONCURRENT_COUNT); - - free(data); - uv_freeaddrinfo(res); - - getaddrinfo_cbs++; -} - - -TEST_IMPL(getaddrinfo_fail) { - uv_getaddrinfo_t req; - - ASSERT(0 == uv_getaddrinfo(uv_default_loop(), - &req, - getaddrinfo_fail_cb, - "xyzzy.xyzzy.xyzzy", - NULL, - NULL)); - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); - ASSERT(fail_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(getaddrinfo_fail_sync) { - uv_getaddrinfo_t req; - - ASSERT(0 > uv_getaddrinfo(uv_default_loop(), - &req, - NULL, - "xyzzy.xyzzy.xyzzy", - NULL, - NULL)); - uv_freeaddrinfo(req.addrinfo); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(getaddrinfo_basic) { - int r; - getaddrinfo_handle = (uv_getaddrinfo_t*)malloc(sizeof(uv_getaddrinfo_t)); - - r = uv_getaddrinfo(uv_default_loop(), - getaddrinfo_handle, - &getaddrinfo_basic_cb, - name, - NULL, - NULL); - ASSERT(r == 0); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(getaddrinfo_cbs == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(getaddrinfo_basic_sync) { - uv_getaddrinfo_t req; - - ASSERT(0 == uv_getaddrinfo(uv_default_loop(), - &req, - NULL, - name, - NULL, - NULL)); - uv_freeaddrinfo(req.addrinfo); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(getaddrinfo_concurrent) { - int i, r; - int* data; - - for (i = 0; i < CONCURRENT_COUNT; i++) { - callback_counts[i] = 0; - - data = (int*)malloc(sizeof(int)); - ASSERT(data != NULL); - *data = i; - getaddrinfo_handles[i].data = data; - - r = uv_getaddrinfo(uv_default_loop(), - &getaddrinfo_handles[i], - &getaddrinfo_cuncurrent_cb, - name, - NULL, - NULL); - ASSERT(r == 0); - } - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - for (i = 0; i < CONCURRENT_COUNT; i++) { - ASSERT(callback_counts[i] == 1); - } - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-getnameinfo.c b/libuv/test/test-getnameinfo.c deleted file mode 100644 index ebe9246..0000000 --- a/libuv/test/test-getnameinfo.c +++ /dev/null @@ -1,101 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to -* deal in the Software without restriction, including without limitation the -* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -* sell copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -* IN THE SOFTWARE. -*/ - -#include "uv.h" -#include "task.h" -#include -#include -#include - - -static const char* address_ip4 = "127.0.0.1"; -static const char* address_ip6 = "::1"; -static const int port = 80; - -static struct sockaddr_in addr4; -static struct sockaddr_in6 addr6; -static uv_getnameinfo_t req; - -static void getnameinfo_req(uv_getnameinfo_t* handle, - int status, - const char* hostname, - const char* service) { - ASSERT(handle != NULL); - ASSERT(status == 0); - ASSERT(hostname != NULL); - ASSERT(service != NULL); -} - - -TEST_IMPL(getnameinfo_basic_ip4) { - int r; - - r = uv_ip4_addr(address_ip4, port, &addr4); - ASSERT(r == 0); - - r = uv_getnameinfo(uv_default_loop(), - &req, - &getnameinfo_req, - (const struct sockaddr*)&addr4, - 0); - ASSERT(r == 0); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(getnameinfo_basic_ip4_sync) { - ASSERT(0 == uv_ip4_addr(address_ip4, port, &addr4)); - - ASSERT(0 == uv_getnameinfo(uv_default_loop(), - &req, - NULL, - (const struct sockaddr*)&addr4, - 0)); - ASSERT(req.host != NULL); - ASSERT(req.service != NULL); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(getnameinfo_basic_ip6) { - int r; - - r = uv_ip6_addr(address_ip6, port, &addr6); - ASSERT(r == 0); - - r = uv_getnameinfo(uv_default_loop(), - &req, - &getnameinfo_req, - (const struct sockaddr*)&addr6, - 0); - ASSERT(r == 0); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-getsockname.c b/libuv/test/test-getsockname.c deleted file mode 100644 index 565c17f..0000000 --- a/libuv/test/test-getsockname.c +++ /dev/null @@ -1,361 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include -#include - -static const int server_port = TEST_PORT; -/* Will be updated right after making the uv_connect_call */ -static int connect_port = -1; - -static int getsocknamecount = 0; -static int getpeernamecount = 0; - -static uv_loop_t* loop; -static uv_tcp_t tcp; -static uv_udp_t udp; -static uv_connect_t connect_req; -static uv_tcp_t tcpServer; -static uv_udp_t udpServer; -static uv_udp_send_t send_req; - - -static void alloc(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { - buf->base = malloc(suggested_size); - buf->len = suggested_size; -} - - -static void on_close(uv_handle_t* peer) { - free(peer); - uv_close((uv_handle_t*)&tcpServer, NULL); -} - - -static void after_shutdown(uv_shutdown_t* req, int status) { - uv_close((uv_handle_t*) req->handle, on_close); - free(req); -} - - -static void after_read(uv_stream_t* handle, - ssize_t nread, - const uv_buf_t* buf) { - uv_shutdown_t* req; - int r; - - if (buf->base) { - free(buf->base); - } - - req = (uv_shutdown_t*) malloc(sizeof *req); - r = uv_shutdown(req, handle, after_shutdown); - ASSERT(r == 0); -} - - -static void check_sockname(struct sockaddr* addr, const char* compare_ip, - int compare_port, const char* context) { - struct sockaddr_in check_addr = *(struct sockaddr_in*) addr; - struct sockaddr_in compare_addr; - char check_ip[17]; - int r; - - ASSERT(0 == uv_ip4_addr(compare_ip, compare_port, &compare_addr)); - - /* Both addresses should be ipv4 */ - ASSERT(check_addr.sin_family == AF_INET); - ASSERT(compare_addr.sin_family == AF_INET); - - /* Check if the ip matches */ - ASSERT(memcmp(&check_addr.sin_addr, - &compare_addr.sin_addr, - sizeof compare_addr.sin_addr) == 0); - - /* Check if the port matches. If port == 0 anything goes. */ - ASSERT(compare_port == 0 || check_addr.sin_port == compare_addr.sin_port); - - r = uv_ip4_name(&check_addr, (char*) check_ip, sizeof check_ip); - ASSERT(r == 0); - - printf("%s: %s:%d\n", context, check_ip, ntohs(check_addr.sin_port)); -} - - -static void on_connection(uv_stream_t* server, int status) { - struct sockaddr sockname, peername; - int namelen; - uv_tcp_t* handle; - int r; - - if (status != 0) { - fprintf(stderr, "Connect error %s\n", uv_err_name(status)); - } - ASSERT(status == 0); - - handle = malloc(sizeof(*handle)); - ASSERT(handle != NULL); - - r = uv_tcp_init(loop, handle); - ASSERT(r == 0); - - /* associate server with stream */ - handle->data = server; - - r = uv_accept(server, (uv_stream_t*)handle); - ASSERT(r == 0); - - namelen = sizeof sockname; - r = uv_tcp_getsockname(handle, &sockname, &namelen); - ASSERT(r == 0); - check_sockname(&sockname, "127.0.0.1", server_port, "accepted socket"); - getsocknamecount++; - - namelen = sizeof peername; - r = uv_tcp_getpeername(handle, &peername, &namelen); - ASSERT(r == 0); - check_sockname(&peername, "127.0.0.1", connect_port, "accepted socket peer"); - getpeernamecount++; - - r = uv_read_start((uv_stream_t*)handle, alloc, after_read); - ASSERT(r == 0); -} - - -static void on_connect(uv_connect_t* req, int status) { - struct sockaddr sockname, peername; - int r, namelen; - - ASSERT(status == 0); - - namelen = sizeof sockname; - r = uv_tcp_getsockname((uv_tcp_t*) req->handle, &sockname, &namelen); - ASSERT(r == 0); - check_sockname(&sockname, "127.0.0.1", 0, "connected socket"); - getsocknamecount++; - - namelen = sizeof peername; - r = uv_tcp_getpeername((uv_tcp_t*) req->handle, &peername, &namelen); - ASSERT(r == 0); - check_sockname(&peername, "127.0.0.1", server_port, "connected socket peer"); - getpeernamecount++; - - uv_close((uv_handle_t*)&tcp, NULL); -} - - -static int tcp_listener(void) { - struct sockaddr_in addr; - struct sockaddr sockname, peername; - int namelen; - int r; - - ASSERT(0 == uv_ip4_addr("0.0.0.0", server_port, &addr)); - - r = uv_tcp_init(loop, &tcpServer); - if (r) { - fprintf(stderr, "Socket creation error\n"); - return 1; - } - - r = uv_tcp_bind(&tcpServer, (const struct sockaddr*) &addr, 0); - if (r) { - fprintf(stderr, "Bind error\n"); - return 1; - } - - r = uv_listen((uv_stream_t*)&tcpServer, 128, on_connection); - if (r) { - fprintf(stderr, "Listen error\n"); - return 1; - } - - memset(&sockname, -1, sizeof sockname); - namelen = sizeof sockname; - r = uv_tcp_getsockname(&tcpServer, &sockname, &namelen); - ASSERT(r == 0); - check_sockname(&sockname, "0.0.0.0", server_port, "server socket"); - getsocknamecount++; - - namelen = sizeof sockname; - r = uv_tcp_getpeername(&tcpServer, &peername, &namelen); - ASSERT(r == UV_ENOTCONN); - getpeernamecount++; - - return 0; -} - - -static void tcp_connector(void) { - struct sockaddr_in server_addr; - struct sockaddr sockname; - int r, namelen; - - ASSERT(0 == uv_ip4_addr("127.0.0.1", server_port, &server_addr)); - - r = uv_tcp_init(loop, &tcp); - tcp.data = &connect_req; - ASSERT(!r); - - r = uv_tcp_connect(&connect_req, - &tcp, - (const struct sockaddr*) &server_addr, - on_connect); - ASSERT(!r); - - /* Fetch the actual port used by the connecting socket. */ - namelen = sizeof sockname; - r = uv_tcp_getsockname(&tcp, &sockname, &namelen); - ASSERT(!r); - ASSERT(sockname.sa_family == AF_INET); - connect_port = ntohs(((struct sockaddr_in*) &sockname)->sin_port); - ASSERT(connect_port > 0); -} - - -static void udp_recv(uv_udp_t* handle, - ssize_t nread, - const uv_buf_t* buf, - const struct sockaddr* addr, - unsigned flags) { - struct sockaddr sockname; - int namelen; - int r; - - ASSERT(nread >= 0); - free(buf->base); - - if (nread == 0) { - return; - } - - memset(&sockname, -1, sizeof sockname); - namelen = sizeof(sockname); - r = uv_udp_getsockname(&udp, &sockname, &namelen); - ASSERT(r == 0); - check_sockname(&sockname, "0.0.0.0", 0, "udp receiving socket"); - getsocknamecount++; - - uv_close((uv_handle_t*) &udp, NULL); - uv_close((uv_handle_t*) handle, NULL); -} - - -static void udp_send(uv_udp_send_t* req, int status) { - -} - - -static int udp_listener(void) { - struct sockaddr_in addr; - struct sockaddr sockname; - int namelen; - int r; - - ASSERT(0 == uv_ip4_addr("0.0.0.0", server_port, &addr)); - - r = uv_udp_init(loop, &udpServer); - if (r) { - fprintf(stderr, "Socket creation error\n"); - return 1; - } - - r = uv_udp_bind(&udpServer, (const struct sockaddr*) &addr, 0); - if (r) { - fprintf(stderr, "Bind error\n"); - return 1; - } - - memset(&sockname, -1, sizeof sockname); - namelen = sizeof sockname; - r = uv_udp_getsockname(&udpServer, &sockname, &namelen); - ASSERT(r == 0); - check_sockname(&sockname, "0.0.0.0", server_port, "udp listener socket"); - getsocknamecount++; - - r = uv_udp_recv_start(&udpServer, alloc, udp_recv); - ASSERT(r == 0); - - return 0; -} - - -static void udp_sender(void) { - struct sockaddr_in server_addr; - uv_buf_t buf; - int r; - - r = uv_udp_init(loop, &udp); - ASSERT(!r); - - buf = uv_buf_init("PING", 4); - ASSERT(0 == uv_ip4_addr("127.0.0.1", server_port, &server_addr)); - - r = uv_udp_send(&send_req, - &udp, - &buf, - 1, - (const struct sockaddr*) &server_addr, - udp_send); - ASSERT(!r); -} - - -TEST_IMPL(getsockname_tcp) { - loop = uv_default_loop(); - - if (tcp_listener()) - return 1; - - tcp_connector(); - - uv_run(loop, UV_RUN_DEFAULT); - - ASSERT(getsocknamecount == 3); - ASSERT(getpeernamecount == 3); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(getsockname_udp) { - loop = uv_default_loop(); - - if (udp_listener()) - return 1; - - udp_sender(); - - uv_run(loop, UV_RUN_DEFAULT); - - ASSERT(getsocknamecount == 2); - - ASSERT(udp.send_queue_size == 0); - ASSERT(udpServer.send_queue_size == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-handle-fileno.c b/libuv/test/test-handle-fileno.c deleted file mode 100644 index df5e984..0000000 --- a/libuv/test/test-handle-fileno.c +++ /dev/null @@ -1,120 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - - -static int get_tty_fd(void) { - /* Make sure we have an FD that refers to a tty */ -#ifdef _WIN32 - HANDLE handle; - handle = CreateFileA("conout$", - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - if (handle == INVALID_HANDLE_VALUE) - return -1; - return _open_osfhandle((intptr_t) handle, 0); -#else /* unix */ - return open("/dev/tty", O_RDONLY, 0); -#endif -} - - -TEST_IMPL(handle_fileno) { - int r; - int tty_fd; - struct sockaddr_in addr; - uv_os_fd_t fd; - uv_tcp_t tcp; - uv_udp_t udp; - uv_pipe_t pipe; - uv_tty_t tty; - uv_idle_t idle; - uv_loop_t* loop; - - loop = uv_default_loop(); - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - - r = uv_idle_init(loop, &idle); - ASSERT(r == 0); - r = uv_fileno((uv_handle_t*) &idle, &fd); - ASSERT(r == UV_EINVAL); - uv_close((uv_handle_t*) &idle, NULL); - - r = uv_tcp_init(loop, &tcp); - ASSERT(r == 0); - r = uv_fileno((uv_handle_t*) &tcp, &fd); - ASSERT(r == UV_EBADF); - r = uv_tcp_bind(&tcp, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - r = uv_fileno((uv_handle_t*) &tcp, &fd); - ASSERT(r == 0); - uv_close((uv_handle_t*) &tcp, NULL); - r = uv_fileno((uv_handle_t*) &tcp, &fd); - ASSERT(r == UV_EBADF); - - r = uv_udp_init(loop, &udp); - ASSERT(r == 0); - r = uv_fileno((uv_handle_t*) &udp, &fd); - ASSERT(r == UV_EBADF); - r = uv_udp_bind(&udp, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - r = uv_fileno((uv_handle_t*) &udp, &fd); - ASSERT(r == 0); - uv_close((uv_handle_t*) &udp, NULL); - r = uv_fileno((uv_handle_t*) &udp, &fd); - ASSERT(r == UV_EBADF); - - r = uv_pipe_init(loop, &pipe, 0); - ASSERT(r == 0); - r = uv_fileno((uv_handle_t*) &pipe, &fd); - ASSERT(r == UV_EBADF); - r = uv_pipe_bind(&pipe, TEST_PIPENAME); - ASSERT(r == 0); - r = uv_fileno((uv_handle_t*) &pipe, &fd); - ASSERT(r == 0); - uv_close((uv_handle_t*) &pipe, NULL); - r = uv_fileno((uv_handle_t*) &pipe, &fd); - ASSERT(r == UV_EBADF); - - tty_fd = get_tty_fd(); - if (tty_fd < 0) { - LOGF("Cannot open a TTY fd"); - } else { - r = uv_tty_init(loop, &tty, tty_fd, 0); - ASSERT(r == 0); - r = uv_fileno((uv_handle_t*) &tty, &fd); - ASSERT(r == 0); - uv_close((uv_handle_t*) &tty, NULL); - r = uv_fileno((uv_handle_t*) &tty, &fd); - ASSERT(r == UV_EBADF); - } - - uv_run(loop, UV_RUN_DEFAULT); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-hrtime.c b/libuv/test/test-hrtime.c deleted file mode 100644 index 72a4d4b..0000000 --- a/libuv/test/test-hrtime.c +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#ifndef MILLISEC -# define MILLISEC 1000 -#endif - -#ifndef NANOSEC -# define NANOSEC ((uint64_t) 1e9) -#endif - - -TEST_IMPL(hrtime) { - uint64_t a, b, diff; - int i = 75; - while (i > 0) { - a = uv_hrtime(); - uv_sleep(45); - b = uv_hrtime(); - - diff = b - a; - - /* printf("i= %d diff = %llu\n", i, (unsigned long long int) diff); */ - - /* The windows Sleep() function has only a resolution of 10-20 ms. */ - /* Check that the difference between the two hrtime values is somewhat in */ - /* the range we expect it to be. */ - ASSERT(diff > (uint64_t) 25 * NANOSEC / MILLISEC); - ASSERT(diff < (uint64_t) 80 * NANOSEC / MILLISEC); - --i; - } - return 0; -} diff --git a/libuv/test/test-idle.c b/libuv/test/test-idle.c deleted file mode 100644 index 0e991c3..0000000 --- a/libuv/test/test-idle.c +++ /dev/null @@ -1,96 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - - -static uv_idle_t idle_handle; -static uv_check_t check_handle; -static uv_timer_t timer_handle; - -static int idle_cb_called = 0; -static int check_cb_called = 0; -static int timer_cb_called = 0; -static int close_cb_called = 0; - - -static void close_cb(uv_handle_t* handle) { - close_cb_called++; -} - - -static void timer_cb(uv_timer_t* handle) { - ASSERT(handle == &timer_handle); - - uv_close((uv_handle_t*) &idle_handle, close_cb); - uv_close((uv_handle_t*) &check_handle, close_cb); - uv_close((uv_handle_t*) &timer_handle, close_cb); - - timer_cb_called++; - LOGF("timer_cb %d\n", timer_cb_called); -} - - -static void idle_cb(uv_idle_t* handle) { - ASSERT(handle == &idle_handle); - - idle_cb_called++; - LOGF("idle_cb %d\n", idle_cb_called); -} - - -static void check_cb(uv_check_t* handle) { - ASSERT(handle == &check_handle); - - check_cb_called++; - LOGF("check_cb %d\n", check_cb_called); -} - - -TEST_IMPL(idle_starvation) { - int r; - - r = uv_idle_init(uv_default_loop(), &idle_handle); - ASSERT(r == 0); - r = uv_idle_start(&idle_handle, idle_cb); - ASSERT(r == 0); - - r = uv_check_init(uv_default_loop(), &check_handle); - ASSERT(r == 0); - r = uv_check_start(&check_handle, check_cb); - ASSERT(r == 0); - - r = uv_timer_init(uv_default_loop(), &timer_handle); - ASSERT(r == 0); - r = uv_timer_start(&timer_handle, timer_cb, 50, 0); - ASSERT(r == 0); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(idle_cb_called > 0); - ASSERT(timer_cb_called == 1); - ASSERT(close_cb_called == 3); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-ip4-addr.c b/libuv/test/test-ip4-addr.c deleted file mode 100644 index 3d6e0cf..0000000 --- a/libuv/test/test-ip4-addr.c +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include - - -TEST_IMPL(ip4_addr) { - - struct sockaddr_in addr; - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - ASSERT(0 == uv_ip4_addr("255.255.255.255", TEST_PORT, &addr)); - ASSERT(UV_EINVAL == uv_ip4_addr("255.255.255*000", TEST_PORT, &addr)); - ASSERT(UV_EINVAL == uv_ip4_addr("255.255.255.256", TEST_PORT, &addr)); - ASSERT(UV_EINVAL == uv_ip4_addr("2555.0.0.0", TEST_PORT, &addr)); - ASSERT(UV_EINVAL == uv_ip4_addr("255", TEST_PORT, &addr)); - - /* for broken address family */ - ASSERT(UV_EAFNOSUPPORT == uv_inet_pton(42, "127.0.0.1", - &addr.sin_addr.s_addr)); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-ip6-addr.c b/libuv/test/test-ip6-addr.c deleted file mode 100644 index cf8491f..0000000 --- a/libuv/test/test-ip6-addr.c +++ /dev/null @@ -1,139 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include - -#ifdef __linux__ -# include -# include -#endif - - -TEST_IMPL(ip6_addr_link_local) { - char string_address[INET6_ADDRSTRLEN]; - uv_interface_address_t* addresses; - uv_interface_address_t* address; - struct sockaddr_in6 addr; - unsigned int iface_index; - const char* device_name; - /* 40 bytes address, 16 bytes device name, plus reserve. */ - char scoped_addr[128]; - int count; - int ix; - - ASSERT(0 == uv_interface_addresses(&addresses, &count)); - - for (ix = 0; ix < count; ix++) { - address = addresses + ix; - - if (address->address.address6.sin6_family != AF_INET6) - continue; - - ASSERT(0 == uv_inet_ntop(AF_INET6, - &address->address.address6.sin6_addr, - string_address, - sizeof(string_address))); - - /* Skip addresses that are not link-local. */ - if (strncmp(string_address, "fe80::", 6) != 0) - continue; - - iface_index = address->address.address6.sin6_scope_id; - device_name = address->name; - -#ifdef _WIN32 - snprintf(scoped_addr, - sizeof(scoped_addr), - "%s%%%d", - string_address, - iface_index); -#else - snprintf(scoped_addr, - sizeof(scoped_addr), - "%s%%%s", - string_address, - device_name); -#endif - - LOGF("Testing link-local address %s " - "(iface_index: 0x%02x, device_name: %s)\n", - scoped_addr, - iface_index, - device_name); - - ASSERT(0 == uv_ip6_addr(scoped_addr, TEST_PORT, &addr)); - LOGF("Got scope_id 0x%02x\n", addr.sin6_scope_id); - ASSERT(iface_index == addr.sin6_scope_id); - } - - uv_free_interface_addresses(addresses, count); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -#define GOOD_ADDR_LIST(X) \ - X("::") \ - X("::1") \ - X("fe80::1") \ - X("fe80::") \ - X("fe80::2acf:daff:fedd:342a") \ - X("fe80:0:0:0:2acf:daff:fedd:342a") \ - X("fe80:0:0:0:2acf:daff:1.2.3.4") \ - X("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") \ - -#define BAD_ADDR_LIST(X) \ - X(":::1") \ - X("abcde::1") \ - X("fe80:0:0:0:2acf:daff:fedd:342a:5678") \ - X("fe80:0:0:0:2acf:daff:abcd:1.2.3.4") \ - X("fe80:0:0:2acf:daff:1.2.3.4.5") \ - X("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255.255") \ - -#define TEST_GOOD(ADDR) \ - ASSERT(0 == uv_inet_pton(AF_INET6, ADDR, &addr)); \ - ASSERT(0 == uv_inet_pton(AF_INET6, ADDR "%en1", &addr)); \ - ASSERT(0 == uv_inet_pton(AF_INET6, ADDR "%%%%", &addr)); \ - ASSERT(0 == uv_inet_pton(AF_INET6, ADDR "%en1:1.2.3.4", &addr)); \ - -#define TEST_BAD(ADDR) \ - ASSERT(0 != uv_inet_pton(AF_INET6, ADDR, &addr)); \ - ASSERT(0 != uv_inet_pton(AF_INET6, ADDR "%en1", &addr)); \ - ASSERT(0 != uv_inet_pton(AF_INET6, ADDR "%%%%", &addr)); \ - ASSERT(0 != uv_inet_pton(AF_INET6, ADDR "%en1:1.2.3.4", &addr)); \ - -TEST_IMPL(ip6_pton) { - struct in6_addr addr; - - GOOD_ADDR_LIST(TEST_GOOD) - BAD_ADDR_LIST(TEST_BAD) - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -#undef GOOD_ADDR_LIST -#undef BAD_ADDR_LIST diff --git a/libuv/test/test-ipc-send-recv.c b/libuv/test/test-ipc-send-recv.c deleted file mode 100644 index d9b9133..0000000 --- a/libuv/test/test-ipc-send-recv.c +++ /dev/null @@ -1,236 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include - -/* See test-ipc.ctx */ -void spawn_helper(uv_pipe_t* channel, - uv_process_t* process, - const char* helper); - -union handles { - uv_handle_t handle; - uv_stream_t stream; - uv_pipe_t pipe; - uv_tcp_t tcp; - uv_tty_t tty; -}; - -struct echo_ctx { - uv_pipe_t channel; - uv_write_t write_req; - uv_handle_type expected_type; - union handles send; - union handles recv; -}; - -static struct echo_ctx ctx; -static int num_recv_handles; - - -static void alloc_cb(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf) { - /* we're not actually reading anything so a small buffer is okay */ - static char slab[8]; - buf->base = slab; - buf->len = sizeof(slab); -} - - -static void recv_cb(uv_stream_t* handle, - ssize_t nread, - const uv_buf_t* buf) { - uv_handle_type pending; - uv_pipe_t* pipe; - int r; - - pipe = (uv_pipe_t*) handle; - ASSERT(pipe == &ctx.channel); - ASSERT(nread >= 0); - ASSERT(1 == uv_pipe_pending_count(pipe)); - - pending = uv_pipe_pending_type(pipe); - ASSERT(pending == ctx.expected_type); - - if (pending == UV_NAMED_PIPE) - r = uv_pipe_init(ctx.channel.loop, &ctx.recv.pipe, 0); - else if (pending == UV_TCP) - r = uv_tcp_init(ctx.channel.loop, &ctx.recv.tcp); - else - abort(); - ASSERT(r == 0); - - r = uv_accept(handle, &ctx.recv.stream); - ASSERT(r == 0); - - uv_close((uv_handle_t*)&ctx.channel, NULL); - uv_close(&ctx.send.handle, NULL); - uv_close(&ctx.recv.handle, NULL); - num_recv_handles++; -} - - -static int run_test(void) { - uv_process_t process; - uv_buf_t buf; - int r; - - spawn_helper(&ctx.channel, &process, "ipc_send_recv_helper"); - - buf = uv_buf_init(".", 1); - r = uv_write2(&ctx.write_req, - (uv_stream_t*)&ctx.channel, - &buf, 1, - &ctx.send.stream, - NULL); - ASSERT(r == 0); - - r = uv_read_start((uv_stream_t*)&ctx.channel, alloc_cb, recv_cb); - ASSERT(r == 0); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(num_recv_handles == 1); - - return 0; -} - - -TEST_IMPL(ipc_send_recv_pipe) { - int r; - - ctx.expected_type = UV_NAMED_PIPE; - - r = uv_pipe_init(uv_default_loop(), &ctx.send.pipe, 1); - ASSERT(r == 0); - - r = uv_pipe_bind(&ctx.send.pipe, TEST_PIPENAME); - ASSERT(r == 0); - - r = run_test(); - ASSERT(r == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(ipc_send_recv_tcp) { - struct sockaddr_in addr; - int r; - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - - ctx.expected_type = UV_TCP; - - r = uv_tcp_init(uv_default_loop(), &ctx.send.tcp); - ASSERT(r == 0); - - r = uv_tcp_bind(&ctx.send.tcp, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - - r = run_test(); - ASSERT(r == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -/* Everything here runs in a child process. */ - -static void write2_cb(uv_write_t* req, int status) { - ASSERT(status == 0); - uv_close(&ctx.recv.handle, NULL); - uv_close((uv_handle_t*)&ctx.channel, NULL); -} - - -static void read_cb(uv_stream_t* handle, - ssize_t nread, - const uv_buf_t* rdbuf) { - uv_buf_t wrbuf; - uv_pipe_t* pipe; - uv_handle_type pending; - int r; - - pipe = (uv_pipe_t*) handle; - ASSERT(pipe == &ctx.channel); - ASSERT(nread >= 0); - ASSERT(1 == uv_pipe_pending_count(pipe)); - - pending = uv_pipe_pending_type(pipe); - ASSERT(pending == UV_NAMED_PIPE || pending == UV_TCP); - - wrbuf = uv_buf_init(".", 1); - - if (pending == UV_NAMED_PIPE) - r = uv_pipe_init(ctx.channel.loop, &ctx.recv.pipe, 0); - else if (pending == UV_TCP) - r = uv_tcp_init(ctx.channel.loop, &ctx.recv.tcp); - else - abort(); - ASSERT(r == 0); - - r = uv_accept(handle, &ctx.recv.stream); - ASSERT(r == 0); - - r = uv_write2(&ctx.write_req, - (uv_stream_t*)&ctx.channel, - &wrbuf, - 1, - &ctx.recv.stream, - write2_cb); - ASSERT(r == 0); -} - - -/* stdin is a duplex channel over which a handle is sent. - * We receive it and send it back where it came from. - */ -int ipc_send_recv_helper(void) { - int r; - - memset(&ctx, 0, sizeof(ctx)); - - r = uv_pipe_init(uv_default_loop(), &ctx.channel, 1); - ASSERT(r == 0); - - uv_pipe_open(&ctx.channel, 0); - ASSERT(1 == uv_is_readable((uv_stream_t*)&ctx.channel)); - ASSERT(1 == uv_is_writable((uv_stream_t*)&ctx.channel)); - ASSERT(0 == uv_is_closing((uv_handle_t*)&ctx.channel)); - - r = uv_read_start((uv_stream_t*)&ctx.channel, alloc_cb, read_cb); - ASSERT(r == 0); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-ipc.c b/libuv/test/test-ipc.c deleted file mode 100644 index ed8c4dd..0000000 --- a/libuv/test/test-ipc.c +++ /dev/null @@ -1,778 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include - -static uv_pipe_t channel; -static uv_tcp_t tcp_server; -static uv_tcp_t tcp_server2; -static uv_tcp_t tcp_connection; - -static int exit_cb_called; -static int read_cb_called; -static int tcp_write_cb_called; -static int tcp_read_cb_called; -static int on_pipe_read_called; -static int local_conn_accepted; -static int remote_conn_accepted; -static int tcp_server_listening; -static uv_write_t write_req; -static uv_write_t conn_notify_req; -static int close_cb_called; -static int connection_accepted; -static int tcp_conn_read_cb_called; -static int tcp_conn_write_cb_called; - -typedef struct { - uv_connect_t conn_req; - uv_write_t tcp_write_req; - uv_tcp_t conn; -} tcp_conn; - -#define CONN_COUNT 100 - - -static void close_server_conn_cb(uv_handle_t* handle) { - free(handle); -} - - -static void on_connection(uv_stream_t* server, int status) { - uv_tcp_t* conn; - int r; - - if (!local_conn_accepted) { - /* Accept the connection and close it. Also and close the server. */ - ASSERT(status == 0); - ASSERT((uv_stream_t*)&tcp_server == server); - - conn = malloc(sizeof(*conn)); - ASSERT(conn); - r = uv_tcp_init(server->loop, conn); - ASSERT(r == 0); - - r = uv_accept(server, (uv_stream_t*)conn); - ASSERT(r == 0); - - uv_close((uv_handle_t*)conn, close_server_conn_cb); - uv_close((uv_handle_t*)server, NULL); - local_conn_accepted = 1; - } -} - - -static void exit_cb(uv_process_t* process, - int64_t exit_status, - int term_signal) { - printf("exit_cb\n"); - exit_cb_called++; - ASSERT(exit_status == 0); - uv_close((uv_handle_t*)process, NULL); -} - - -static void on_alloc(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf) { - buf->base = malloc(suggested_size); - buf->len = suggested_size; -} - - -static void close_client_conn_cb(uv_handle_t* handle) { - tcp_conn* p = (tcp_conn*)handle->data; - free(p); -} - - -static void connect_cb(uv_connect_t* req, int status) { - uv_close((uv_handle_t*)req->handle, close_client_conn_cb); -} - - -static void make_many_connections(void) { - tcp_conn* conn; - struct sockaddr_in addr; - int r, i; - - for (i = 0; i < CONN_COUNT; i++) { - conn = malloc(sizeof(*conn)); - ASSERT(conn); - - r = uv_tcp_init(uv_default_loop(), &conn->conn); - ASSERT(r == 0); - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - - r = uv_tcp_connect(&conn->conn_req, - (uv_tcp_t*) &conn->conn, - (const struct sockaddr*) &addr, - connect_cb); - ASSERT(r == 0); - - conn->conn.data = conn; - } -} - - -static void on_read(uv_stream_t* handle, - ssize_t nread, - const uv_buf_t* buf) { - int r; - uv_pipe_t* pipe; - uv_handle_type pending; - uv_buf_t outbuf; - - pipe = (uv_pipe_t*) handle; - - if (nread == 0) { - /* Everything OK, but nothing read. */ - free(buf->base); - return; - } - - if (nread < 0) { - if (nread == UV_EOF) { - free(buf->base); - return; - } - - printf("error recving on channel: %s\n", uv_strerror(nread)); - abort(); - } - - fprintf(stderr, "got %d bytes\n", (int)nread); - - pending = uv_pipe_pending_type(pipe); - if (!tcp_server_listening) { - ASSERT(1 == uv_pipe_pending_count(pipe)); - ASSERT(nread > 0 && buf->base && pending != UV_UNKNOWN_HANDLE); - read_cb_called++; - - /* Accept the pending TCP server, and start listening on it. */ - ASSERT(pending == UV_TCP); - r = uv_tcp_init(uv_default_loop(), &tcp_server); - ASSERT(r == 0); - - r = uv_accept((uv_stream_t*)pipe, (uv_stream_t*)&tcp_server); - ASSERT(r == 0); - - r = uv_listen((uv_stream_t*)&tcp_server, 12, on_connection); - ASSERT(r == 0); - - tcp_server_listening = 1; - - /* Make sure that the expected data is correctly multiplexed. */ - ASSERT(memcmp("hello\n", buf->base, nread) == 0); - - outbuf = uv_buf_init("world\n", 6); - r = uv_write(&write_req, (uv_stream_t*)pipe, &outbuf, 1, NULL); - ASSERT(r == 0); - - /* Create a bunch of connections to get both servers to accept. */ - make_many_connections(); - } else if (memcmp("accepted_connection\n", buf->base, nread) == 0) { - /* Remote server has accepted a connection. Close the channel. */ - ASSERT(0 == uv_pipe_pending_count(pipe)); - ASSERT(pending == UV_UNKNOWN_HANDLE); - remote_conn_accepted = 1; - uv_close((uv_handle_t*)&channel, NULL); - } - - free(buf->base); -} - -#ifdef _WIN32 -static void on_read_listen_after_bound_twice(uv_stream_t* handle, - ssize_t nread, - const uv_buf_t* buf) { - int r; - uv_pipe_t* pipe; - uv_handle_type pending; - - pipe = (uv_pipe_t*) handle; - - if (nread == 0) { - /* Everything OK, but nothing read. */ - free(buf->base); - return; - } - - if (nread < 0) { - if (nread == UV_EOF) { - free(buf->base); - return; - } - - printf("error recving on channel: %s\n", uv_strerror(nread)); - abort(); - } - - fprintf(stderr, "got %d bytes\n", (int)nread); - - ASSERT(uv_pipe_pending_count(pipe) > 0); - pending = uv_pipe_pending_type(pipe); - ASSERT(nread > 0 && buf->base && pending != UV_UNKNOWN_HANDLE); - read_cb_called++; - - if (read_cb_called == 1) { - /* Accept the first TCP server, and start listening on it. */ - ASSERT(pending == UV_TCP); - r = uv_tcp_init(uv_default_loop(), &tcp_server); - ASSERT(r == 0); - - r = uv_accept((uv_stream_t*)pipe, (uv_stream_t*)&tcp_server); - ASSERT(r == 0); - - r = uv_listen((uv_stream_t*)&tcp_server, 12, on_connection); - ASSERT(r == 0); - } else if (read_cb_called == 2) { - /* Accept the second TCP server, and start listening on it. */ - ASSERT(pending == UV_TCP); - r = uv_tcp_init(uv_default_loop(), &tcp_server2); - ASSERT(r == 0); - - r = uv_accept((uv_stream_t*)pipe, (uv_stream_t*)&tcp_server2); - ASSERT(r == 0); - - r = uv_listen((uv_stream_t*)&tcp_server2, 12, on_connection); - ASSERT(r == UV_EADDRINUSE); - - uv_close((uv_handle_t*)&tcp_server, NULL); - uv_close((uv_handle_t*)&tcp_server2, NULL); - ASSERT(0 == uv_pipe_pending_count(pipe)); - uv_close((uv_handle_t*)&channel, NULL); - } - - free(buf->base); -} -#endif - -void spawn_helper(uv_pipe_t* channel, - uv_process_t* process, - const char* helper) { - uv_process_options_t options; - size_t exepath_size; - char exepath[1024]; - char* args[3]; - int r; - uv_stdio_container_t stdio[1]; - - r = uv_pipe_init(uv_default_loop(), channel, 1); - ASSERT(r == 0); - ASSERT(channel->ipc); - - exepath_size = sizeof(exepath); - r = uv_exepath(exepath, &exepath_size); - ASSERT(r == 0); - - exepath[exepath_size] = '\0'; - args[0] = exepath; - args[1] = (char*)helper; - args[2] = NULL; - - memset(&options, 0, sizeof(options)); - options.file = exepath; - options.args = args; - options.exit_cb = exit_cb; - - options.stdio = stdio; - options.stdio[0].flags = UV_CREATE_PIPE | - UV_READABLE_PIPE | UV_WRITABLE_PIPE; - options.stdio[0].data.stream = (uv_stream_t*)channel; - options.stdio_count = 1; - - r = uv_spawn(uv_default_loop(), process, &options); - ASSERT(r == 0); -} - - -static void on_tcp_write(uv_write_t* req, int status) { - ASSERT(status == 0); - ASSERT(req->handle == (uv_stream_t*)&tcp_connection); - tcp_write_cb_called++; -} - - -static void on_read_alloc(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf) { - buf->base = malloc(suggested_size); - buf->len = suggested_size; -} - - -static void on_tcp_read(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { - ASSERT(nread > 0); - ASSERT(memcmp("hello again\n", buf->base, nread) == 0); - ASSERT(tcp == (uv_stream_t*)&tcp_connection); - free(buf->base); - - tcp_read_cb_called++; - - uv_close((uv_handle_t*)tcp, NULL); - uv_close((uv_handle_t*)&channel, NULL); -} - - -static void on_read_connection(uv_stream_t* handle, - ssize_t nread, - const uv_buf_t* buf) { - int r; - uv_buf_t outbuf; - uv_pipe_t* pipe; - uv_handle_type pending; - - pipe = (uv_pipe_t*) handle; - if (nread == 0) { - /* Everything OK, but nothing read. */ - free(buf->base); - return; - } - - if (nread < 0) { - if (nread == UV_EOF) { - free(buf->base); - return; - } - - printf("error recving on channel: %s\n", uv_strerror(nread)); - abort(); - } - - fprintf(stderr, "got %d bytes\n", (int)nread); - - ASSERT(1 == uv_pipe_pending_count(pipe)); - pending = uv_pipe_pending_type(pipe); - - ASSERT(nread > 0 && buf->base && pending != UV_UNKNOWN_HANDLE); - read_cb_called++; - - /* Accept the pending TCP connection */ - ASSERT(pending == UV_TCP); - r = uv_tcp_init(uv_default_loop(), &tcp_connection); - ASSERT(r == 0); - - r = uv_accept(handle, (uv_stream_t*)&tcp_connection); - ASSERT(r == 0); - - /* Make sure that the expected data is correctly multiplexed. */ - ASSERT(memcmp("hello\n", buf->base, nread) == 0); - - /* Write/read to/from the connection */ - outbuf = uv_buf_init("world\n", 6); - r = uv_write(&write_req, (uv_stream_t*)&tcp_connection, &outbuf, 1, - on_tcp_write); - ASSERT(r == 0); - - r = uv_read_start((uv_stream_t*)&tcp_connection, on_read_alloc, on_tcp_read); - ASSERT(r == 0); - - free(buf->base); -} - - -static int run_ipc_test(const char* helper, uv_read_cb read_cb) { - uv_process_t process; - int r; - - spawn_helper(&channel, &process, helper); - uv_read_start((uv_stream_t*)&channel, on_alloc, read_cb); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(ipc_listen_before_write) { - int r = run_ipc_test("ipc_helper_listen_before_write", on_read); - ASSERT(local_conn_accepted == 1); - ASSERT(remote_conn_accepted == 1); - ASSERT(read_cb_called == 1); - ASSERT(exit_cb_called == 1); - return r; -} - - -TEST_IMPL(ipc_listen_after_write) { - int r = run_ipc_test("ipc_helper_listen_after_write", on_read); - ASSERT(local_conn_accepted == 1); - ASSERT(remote_conn_accepted == 1); - ASSERT(read_cb_called == 1); - ASSERT(exit_cb_called == 1); - return r; -} - - -TEST_IMPL(ipc_tcp_connection) { - int r = run_ipc_test("ipc_helper_tcp_connection", on_read_connection); - ASSERT(read_cb_called == 1); - ASSERT(tcp_write_cb_called == 1); - ASSERT(tcp_read_cb_called == 1); - ASSERT(exit_cb_called == 1); - return r; -} - - -#ifdef _WIN32 -TEST_IMPL(listen_with_simultaneous_accepts) { - uv_tcp_t server; - int r; - struct sockaddr_in addr; - - ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); - - r = uv_tcp_init(uv_default_loop(), &server); - ASSERT(r == 0); - - r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - - r = uv_tcp_simultaneous_accepts(&server, 1); - ASSERT(r == 0); - - r = uv_listen((uv_stream_t*)&server, SOMAXCONN, NULL); - ASSERT(r == 0); - ASSERT(server.reqs_pending == 32); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(listen_no_simultaneous_accepts) { - uv_tcp_t server; - int r; - struct sockaddr_in addr; - - ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); - - r = uv_tcp_init(uv_default_loop(), &server); - ASSERT(r == 0); - - r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - - r = uv_tcp_simultaneous_accepts(&server, 0); - ASSERT(r == 0); - - r = uv_listen((uv_stream_t*)&server, SOMAXCONN, NULL); - ASSERT(r == 0); - ASSERT(server.reqs_pending == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -TEST_IMPL(ipc_listen_after_bind_twice) { - int r = run_ipc_test("ipc_helper_bind_twice", on_read_listen_after_bound_twice); - ASSERT(read_cb_called == 2); - ASSERT(exit_cb_called == 1); - return r; -} -#endif - - -/* Everything here runs in a child process. */ - -static tcp_conn conn; - - -static void close_cb(uv_handle_t* handle) { - close_cb_called++; -} - - -static void conn_notify_write_cb(uv_write_t* req, int status) { - uv_close((uv_handle_t*)&tcp_server, close_cb); - uv_close((uv_handle_t*)&channel, close_cb); -} - - -static void tcp_connection_write_cb(uv_write_t* req, int status) { - ASSERT((uv_handle_t*)&conn.conn == (uv_handle_t*)req->handle); - uv_close((uv_handle_t*)req->handle, close_cb); - uv_close((uv_handle_t*)&channel, close_cb); - uv_close((uv_handle_t*)&tcp_server, close_cb); - tcp_conn_write_cb_called++; -} - - -static void on_tcp_child_process_read(uv_stream_t* tcp, - ssize_t nread, - const uv_buf_t* buf) { - uv_buf_t outbuf; - int r; - - if (nread < 0) { - if (nread == UV_EOF) { - free(buf->base); - return; - } - - printf("error recving on tcp connection: %s\n", uv_strerror(nread)); - abort(); - } - - ASSERT(nread > 0); - ASSERT(memcmp("world\n", buf->base, nread) == 0); - on_pipe_read_called++; - free(buf->base); - - /* Write to the socket */ - outbuf = uv_buf_init("hello again\n", 12); - r = uv_write(&conn.tcp_write_req, tcp, &outbuf, 1, tcp_connection_write_cb); - ASSERT(r == 0); - - tcp_conn_read_cb_called++; -} - - -static void connect_child_process_cb(uv_connect_t* req, int status) { - int r; - - ASSERT(status == 0); - r = uv_read_start(req->handle, on_read_alloc, on_tcp_child_process_read); - ASSERT(r == 0); -} - - -static void ipc_on_connection(uv_stream_t* server, int status) { - int r; - uv_buf_t buf; - - if (!connection_accepted) { - /* - * Accept the connection and close it. Also let the other - * side know. - */ - ASSERT(status == 0); - ASSERT((uv_stream_t*)&tcp_server == server); - - r = uv_tcp_init(server->loop, &conn.conn); - ASSERT(r == 0); - - r = uv_accept(server, (uv_stream_t*)&conn.conn); - ASSERT(r == 0); - - uv_close((uv_handle_t*)&conn.conn, close_cb); - - buf = uv_buf_init("accepted_connection\n", 20); - r = uv_write2(&conn_notify_req, (uv_stream_t*)&channel, &buf, 1, - NULL, conn_notify_write_cb); - ASSERT(r == 0); - - connection_accepted = 1; - } -} - - -static void ipc_on_connection_tcp_conn(uv_stream_t* server, int status) { - int r; - uv_buf_t buf; - uv_tcp_t* conn; - - ASSERT(status == 0); - ASSERT((uv_stream_t*)&tcp_server == server); - - conn = malloc(sizeof(*conn)); - ASSERT(conn); - - r = uv_tcp_init(server->loop, conn); - ASSERT(r == 0); - - r = uv_accept(server, (uv_stream_t*)conn); - ASSERT(r == 0); - - /* Send the accepted connection to the other process */ - buf = uv_buf_init("hello\n", 6); - r = uv_write2(&conn_notify_req, (uv_stream_t*)&channel, &buf, 1, - (uv_stream_t*)conn, NULL); - ASSERT(r == 0); - - r = uv_read_start((uv_stream_t*) conn, - on_read_alloc, - on_tcp_child_process_read); - ASSERT(r == 0); - - uv_close((uv_handle_t*)conn, close_cb); -} - - -int ipc_helper(int listen_after_write) { - /* - * This is launched from test-ipc.c. stdin is a duplex channel that we - * over which a handle will be transmitted. - */ - struct sockaddr_in addr; - uv_write_t write_req; - int r; - uv_buf_t buf; - - ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); - - r = uv_pipe_init(uv_default_loop(), &channel, 1); - ASSERT(r == 0); - - uv_pipe_open(&channel, 0); - - ASSERT(1 == uv_is_readable((uv_stream_t*) &channel)); - ASSERT(1 == uv_is_writable((uv_stream_t*) &channel)); - ASSERT(0 == uv_is_closing((uv_handle_t*) &channel)); - - r = uv_tcp_init(uv_default_loop(), &tcp_server); - ASSERT(r == 0); - - r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - - if (!listen_after_write) { - r = uv_listen((uv_stream_t*)&tcp_server, 12, ipc_on_connection); - ASSERT(r == 0); - } - - buf = uv_buf_init("hello\n", 6); - r = uv_write2(&write_req, (uv_stream_t*)&channel, &buf, 1, - (uv_stream_t*)&tcp_server, NULL); - ASSERT(r == 0); - - if (listen_after_write) { - r = uv_listen((uv_stream_t*)&tcp_server, 12, ipc_on_connection); - ASSERT(r == 0); - } - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(connection_accepted == 1); - ASSERT(close_cb_called == 3); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -int ipc_helper_tcp_connection(void) { - /* - * This is launched from test-ipc.c. stdin is a duplex channel - * over which a handle will be transmitted. - */ - - int r; - struct sockaddr_in addr; - - r = uv_pipe_init(uv_default_loop(), &channel, 1); - ASSERT(r == 0); - - uv_pipe_open(&channel, 0); - - ASSERT(1 == uv_is_readable((uv_stream_t*) &channel)); - ASSERT(1 == uv_is_writable((uv_stream_t*) &channel)); - ASSERT(0 == uv_is_closing((uv_handle_t*) &channel)); - - r = uv_tcp_init(uv_default_loop(), &tcp_server); - ASSERT(r == 0); - - ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); - - r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - - r = uv_listen((uv_stream_t*)&tcp_server, 12, ipc_on_connection_tcp_conn); - ASSERT(r == 0); - - /* Make a connection to the server */ - r = uv_tcp_init(uv_default_loop(), &conn.conn); - ASSERT(r == 0); - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - - r = uv_tcp_connect(&conn.conn_req, - (uv_tcp_t*) &conn.conn, - (const struct sockaddr*) &addr, - connect_child_process_cb); - ASSERT(r == 0); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(tcp_conn_read_cb_called == 1); - ASSERT(tcp_conn_write_cb_called == 1); - ASSERT(close_cb_called == 4); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -int ipc_helper_bind_twice(void) { - /* - * This is launched from test-ipc.c. stdin is a duplex channel - * over which two handles will be transmitted. - */ - struct sockaddr_in addr; - uv_write_t write_req; - uv_write_t write_req2; - int r; - uv_buf_t buf; - - ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); - - r = uv_pipe_init(uv_default_loop(), &channel, 1); - ASSERT(r == 0); - - uv_pipe_open(&channel, 0); - - ASSERT(1 == uv_is_readable((uv_stream_t*) &channel)); - ASSERT(1 == uv_is_writable((uv_stream_t*) &channel)); - ASSERT(0 == uv_is_closing((uv_handle_t*) &channel)); - - buf = uv_buf_init("hello\n", 6); - - r = uv_tcp_init(uv_default_loop(), &tcp_server); - ASSERT(r == 0); - r = uv_tcp_init(uv_default_loop(), &tcp_server2); - ASSERT(r == 0); - - r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - r = uv_tcp_bind(&tcp_server2, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - - r = uv_write2(&write_req, (uv_stream_t*)&channel, &buf, 1, - (uv_stream_t*)&tcp_server, NULL); - ASSERT(r == 0); - r = uv_write2(&write_req2, (uv_stream_t*)&channel, &buf, 1, - (uv_stream_t*)&tcp_server2, NULL); - ASSERT(r == 0); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-list.h b/libuv/test/test-list.h deleted file mode 100644 index d00d0f2..0000000 --- a/libuv/test/test-list.h +++ /dev/null @@ -1,657 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -TEST_DECLARE (platform_output) -TEST_DECLARE (callback_order) -TEST_DECLARE (close_order) -TEST_DECLARE (run_once) -TEST_DECLARE (run_nowait) -TEST_DECLARE (loop_alive) -TEST_DECLARE (loop_close) -TEST_DECLARE (loop_stop) -TEST_DECLARE (loop_update_time) -TEST_DECLARE (loop_backend_timeout) -TEST_DECLARE (loop_configure) -TEST_DECLARE (default_loop_close) -TEST_DECLARE (barrier_1) -TEST_DECLARE (barrier_2) -TEST_DECLARE (barrier_3) -TEST_DECLARE (condvar_1) -TEST_DECLARE (condvar_2) -TEST_DECLARE (condvar_3) -TEST_DECLARE (condvar_4) -TEST_DECLARE (condvar_5) -TEST_DECLARE (semaphore_1) -TEST_DECLARE (semaphore_2) -TEST_DECLARE (semaphore_3) -TEST_DECLARE (tty) -TEST_DECLARE (stdio_over_pipes) -TEST_DECLARE (ip6_pton) -TEST_DECLARE (ipc_listen_before_write) -TEST_DECLARE (ipc_listen_after_write) -#ifndef _WIN32 -TEST_DECLARE (ipc_send_recv_pipe) -#endif -TEST_DECLARE (ipc_send_recv_tcp) -TEST_DECLARE (ipc_tcp_connection) -TEST_DECLARE (tcp_ping_pong) -TEST_DECLARE (tcp_ping_pong_v6) -TEST_DECLARE (pipe_ping_pong) -TEST_DECLARE (delayed_accept) -TEST_DECLARE (multiple_listen) -#ifndef _WIN32 -TEST_DECLARE (tcp_write_after_connect) -#endif -TEST_DECLARE (tcp_writealot) -TEST_DECLARE (tcp_try_write) -TEST_DECLARE (tcp_write_queue_order) -TEST_DECLARE (tcp_open) -TEST_DECLARE (tcp_connect_error_after_write) -TEST_DECLARE (tcp_shutdown_after_write) -TEST_DECLARE (tcp_bind_error_addrinuse) -TEST_DECLARE (tcp_bind_error_addrnotavail_1) -TEST_DECLARE (tcp_bind_error_addrnotavail_2) -TEST_DECLARE (tcp_bind_error_fault) -TEST_DECLARE (tcp_bind_error_inval) -TEST_DECLARE (tcp_bind_localhost_ok) -TEST_DECLARE (tcp_bind_invalid_flags) -TEST_DECLARE (tcp_listen_without_bind) -TEST_DECLARE (tcp_connect_error_fault) -TEST_DECLARE (tcp_connect_timeout) -TEST_DECLARE (tcp_close_while_connecting) -TEST_DECLARE (tcp_close) -#ifndef _WIN32 -TEST_DECLARE (tcp_close_accept) -#endif -TEST_DECLARE (tcp_flags) -TEST_DECLARE (tcp_write_to_half_open_connection) -TEST_DECLARE (tcp_unexpected_read) -TEST_DECLARE (tcp_read_stop) -TEST_DECLARE (tcp_bind6_error_addrinuse) -TEST_DECLARE (tcp_bind6_error_addrnotavail) -TEST_DECLARE (tcp_bind6_error_fault) -TEST_DECLARE (tcp_bind6_error_inval) -TEST_DECLARE (tcp_bind6_localhost_ok) -TEST_DECLARE (udp_bind) -TEST_DECLARE (udp_bind_reuseaddr) -TEST_DECLARE (udp_send_and_recv) -TEST_DECLARE (udp_send_immediate) -TEST_DECLARE (udp_send_unreachable) -TEST_DECLARE (udp_multicast_join) -TEST_DECLARE (udp_multicast_join6) -TEST_DECLARE (udp_multicast_ttl) -TEST_DECLARE (udp_multicast_interface) -TEST_DECLARE (udp_multicast_interface6) -TEST_DECLARE (udp_dgram_too_big) -TEST_DECLARE (udp_dual_stack) -TEST_DECLARE (udp_ipv6_only) -TEST_DECLARE (udp_options) -TEST_DECLARE (udp_options6) -TEST_DECLARE (udp_no_autobind) -TEST_DECLARE (udp_open) -TEST_DECLARE (udp_try_send) -TEST_DECLARE (pipe_bind_error_addrinuse) -TEST_DECLARE (pipe_bind_error_addrnotavail) -TEST_DECLARE (pipe_bind_error_inval) -TEST_DECLARE (pipe_listen_without_bind) -TEST_DECLARE (pipe_connect_bad_name) -TEST_DECLARE (pipe_connect_to_file) -TEST_DECLARE (pipe_getsockname) -TEST_DECLARE (pipe_getsockname_abstract) -TEST_DECLARE (pipe_getsockname_blocking) -TEST_DECLARE (pipe_sendmsg) -TEST_DECLARE (pipe_server_close) -TEST_DECLARE (connection_fail) -TEST_DECLARE (connection_fail_doesnt_auto_close) -TEST_DECLARE (shutdown_close_tcp) -TEST_DECLARE (shutdown_close_pipe) -TEST_DECLARE (shutdown_eof) -TEST_DECLARE (shutdown_twice) -TEST_DECLARE (callback_stack) -TEST_DECLARE (error_message) -TEST_DECLARE (timer) -TEST_DECLARE (timer_init) -TEST_DECLARE (timer_again) -TEST_DECLARE (timer_start_twice) -TEST_DECLARE (timer_order) -TEST_DECLARE (timer_huge_timeout) -TEST_DECLARE (timer_huge_repeat) -TEST_DECLARE (timer_run_once) -TEST_DECLARE (timer_from_check) -TEST_DECLARE (timer_null_callback) -TEST_DECLARE (idle_starvation) -TEST_DECLARE (loop_handles) -TEST_DECLARE (get_loadavg) -TEST_DECLARE (walk_handles) -TEST_DECLARE (watcher_cross_stop) -TEST_DECLARE (ref) -TEST_DECLARE (idle_ref) -TEST_DECLARE (async_ref) -TEST_DECLARE (prepare_ref) -TEST_DECLARE (check_ref) -TEST_DECLARE (unref_in_prepare_cb) -TEST_DECLARE (timer_ref) -TEST_DECLARE (timer_ref2) -TEST_DECLARE (fs_event_ref) -TEST_DECLARE (fs_poll_ref) -TEST_DECLARE (tcp_ref) -TEST_DECLARE (tcp_ref2) -TEST_DECLARE (tcp_ref2b) -TEST_DECLARE (tcp_ref3) -TEST_DECLARE (tcp_ref4) -TEST_DECLARE (udp_ref) -TEST_DECLARE (udp_ref2) -TEST_DECLARE (udp_ref3) -TEST_DECLARE (pipe_ref) -TEST_DECLARE (pipe_ref2) -TEST_DECLARE (pipe_ref3) -TEST_DECLARE (pipe_ref4) -#ifndef _WIN32 -TEST_DECLARE (pipe_close_stdout_read_stdin) -#endif -TEST_DECLARE (process_ref) -TEST_DECLARE (has_ref) -TEST_DECLARE (active) -TEST_DECLARE (embed) -TEST_DECLARE (async) -TEST_DECLARE (async_null_cb) -TEST_DECLARE (get_currentexe) -TEST_DECLARE (process_title) -TEST_DECLARE (cwd_and_chdir) -TEST_DECLARE (get_memory) -TEST_DECLARE (handle_fileno) -TEST_DECLARE (hrtime) -TEST_DECLARE (getaddrinfo_fail) -TEST_DECLARE (getaddrinfo_fail_sync) -TEST_DECLARE (getaddrinfo_basic) -TEST_DECLARE (getaddrinfo_basic_sync) -TEST_DECLARE (getaddrinfo_concurrent) -TEST_DECLARE (getnameinfo_basic_ip4) -TEST_DECLARE (getnameinfo_basic_ip4_sync) -TEST_DECLARE (getnameinfo_basic_ip6) -TEST_DECLARE (getsockname_tcp) -TEST_DECLARE (getsockname_udp) -TEST_DECLARE (fail_always) -TEST_DECLARE (pass_always) -TEST_DECLARE (socket_buffer_size) -TEST_DECLARE (spawn_fails) -TEST_DECLARE (spawn_exit_code) -TEST_DECLARE (spawn_stdout) -TEST_DECLARE (spawn_stdin) -TEST_DECLARE (spawn_stdio_greater_than_3) -TEST_DECLARE (spawn_ignored_stdio) -TEST_DECLARE (spawn_and_kill) -TEST_DECLARE (spawn_detached) -TEST_DECLARE (spawn_and_kill_with_std) -TEST_DECLARE (spawn_and_ping) -TEST_DECLARE (spawn_preserve_env) -TEST_DECLARE (spawn_setuid_fails) -TEST_DECLARE (spawn_setgid_fails) -TEST_DECLARE (spawn_stdout_to_file) -TEST_DECLARE (spawn_stdout_and_stderr_to_file) -TEST_DECLARE (spawn_auto_unref) -TEST_DECLARE (spawn_closed_process_io) -TEST_DECLARE (spawn_reads_child_path) -TEST_DECLARE (fs_poll) -TEST_DECLARE (fs_poll_getpath) -TEST_DECLARE (kill) -TEST_DECLARE (fs_file_noent) -TEST_DECLARE (fs_file_nametoolong) -TEST_DECLARE (fs_file_loop) -TEST_DECLARE (fs_file_async) -TEST_DECLARE (fs_file_sync) -TEST_DECLARE (fs_file_write_null_buffer) -TEST_DECLARE (fs_async_dir) -TEST_DECLARE (fs_async_sendfile) -TEST_DECLARE (fs_mkdtemp) -TEST_DECLARE (fs_fstat) -TEST_DECLARE (fs_access) -TEST_DECLARE (fs_chmod) -TEST_DECLARE (fs_chown) -TEST_DECLARE (fs_link) -TEST_DECLARE (fs_readlink) -TEST_DECLARE (fs_symlink) -TEST_DECLARE (fs_symlink_dir) -TEST_DECLARE (fs_utime) -TEST_DECLARE (fs_futime) -TEST_DECLARE (fs_file_open_append) -TEST_DECLARE (fs_stat_missing_path) -TEST_DECLARE (fs_read_file_eof) -TEST_DECLARE (fs_event_watch_dir) -TEST_DECLARE (fs_event_watch_file) -TEST_DECLARE (fs_event_watch_file_twice) -TEST_DECLARE (fs_event_watch_file_current_dir) -TEST_DECLARE (fs_event_no_callback_after_close) -TEST_DECLARE (fs_event_no_callback_on_close) -TEST_DECLARE (fs_event_immediate_close) -TEST_DECLARE (fs_event_close_with_pending_event) -TEST_DECLARE (fs_event_close_in_callback) -TEST_DECLARE (fs_event_start_and_close) -TEST_DECLARE (fs_event_error_reporting) -TEST_DECLARE (fs_event_getpath) -TEST_DECLARE (fs_scandir_empty_dir) -TEST_DECLARE (fs_scandir_file) -TEST_DECLARE (fs_open_dir) -TEST_DECLARE (fs_rename_to_existing_file) -TEST_DECLARE (fs_write_multiple_bufs) -TEST_DECLARE (threadpool_queue_work_simple) -TEST_DECLARE (threadpool_queue_work_einval) -TEST_DECLARE (threadpool_multiple_event_loops) -TEST_DECLARE (threadpool_cancel_getaddrinfo) -TEST_DECLARE (threadpool_cancel_getnameinfo) -TEST_DECLARE (threadpool_cancel_work) -TEST_DECLARE (threadpool_cancel_fs) -TEST_DECLARE (threadpool_cancel_single) -TEST_DECLARE (thread_local_storage) -TEST_DECLARE (thread_mutex) -TEST_DECLARE (thread_rwlock) -TEST_DECLARE (thread_create) -TEST_DECLARE (thread_equal) -TEST_DECLARE (dlerror) -TEST_DECLARE (poll_duplex) -TEST_DECLARE (poll_unidirectional) -TEST_DECLARE (poll_close) - -TEST_DECLARE (ip4_addr) -TEST_DECLARE (ip6_addr_link_local) - -#ifdef _WIN32 -TEST_DECLARE (poll_close_doesnt_corrupt_stack) -TEST_DECLARE (poll_closesocket) -TEST_DECLARE (spawn_detect_pipe_name_collisions_on_windows) -TEST_DECLARE (argument_escaping) -TEST_DECLARE (environment_creation) -TEST_DECLARE (listen_with_simultaneous_accepts) -TEST_DECLARE (listen_no_simultaneous_accepts) -TEST_DECLARE (fs_stat_root) -TEST_DECLARE (spawn_with_an_odd_path) -TEST_DECLARE (ipc_listen_after_bind_twice) -#else -TEST_DECLARE (emfile) -TEST_DECLARE (close_fd) -TEST_DECLARE (spawn_fs_open) -TEST_DECLARE (spawn_setuid_setgid) -TEST_DECLARE (we_get_signal) -TEST_DECLARE (we_get_signals) -TEST_DECLARE (signal_multiple_loops) -TEST_DECLARE (closed_fd_events) -#endif -#ifdef __APPLE__ -TEST_DECLARE (osx_select) -TEST_DECLARE (osx_select_many_fds) -#endif -HELPER_DECLARE (tcp4_echo_server) -HELPER_DECLARE (tcp6_echo_server) -HELPER_DECLARE (udp4_echo_server) -HELPER_DECLARE (pipe_echo_server) - - -TASK_LIST_START - TEST_ENTRY_CUSTOM (platform_output, 0, 1, 5000) - -#if 0 - TEST_ENTRY (callback_order) -#endif - TEST_ENTRY (close_order) - TEST_ENTRY (run_once) - TEST_ENTRY (run_nowait) - TEST_ENTRY (loop_alive) - TEST_ENTRY (loop_close) - TEST_ENTRY (loop_stop) - TEST_ENTRY (loop_update_time) - TEST_ENTRY (loop_backend_timeout) - TEST_ENTRY (loop_configure) - TEST_ENTRY (default_loop_close) - TEST_ENTRY (barrier_1) - TEST_ENTRY (barrier_2) - TEST_ENTRY (barrier_3) - TEST_ENTRY (condvar_1) - TEST_ENTRY (condvar_2) - TEST_ENTRY (condvar_3) - TEST_ENTRY (condvar_4) - TEST_ENTRY (condvar_5) - TEST_ENTRY (semaphore_1) - TEST_ENTRY (semaphore_2) - TEST_ENTRY (semaphore_3) - - TEST_ENTRY (pipe_connect_bad_name) - TEST_ENTRY (pipe_connect_to_file) - - TEST_ENTRY (pipe_server_close) -#ifndef _WIN32 - TEST_ENTRY (pipe_close_stdout_read_stdin) -#endif - TEST_ENTRY (tty) - TEST_ENTRY (stdio_over_pipes) - TEST_ENTRY (ip6_pton) - TEST_ENTRY (ipc_listen_before_write) - TEST_ENTRY (ipc_listen_after_write) -#ifndef _WIN32 - TEST_ENTRY (ipc_send_recv_pipe) -#endif - TEST_ENTRY (ipc_send_recv_tcp) - TEST_ENTRY (ipc_tcp_connection) - - TEST_ENTRY (tcp_ping_pong) - TEST_HELPER (tcp_ping_pong, tcp4_echo_server) - - TEST_ENTRY (tcp_ping_pong_v6) - TEST_HELPER (tcp_ping_pong_v6, tcp6_echo_server) - - TEST_ENTRY (pipe_ping_pong) - TEST_HELPER (pipe_ping_pong, pipe_echo_server) - - TEST_ENTRY (delayed_accept) - TEST_ENTRY (multiple_listen) - -#ifndef _WIN32 - TEST_ENTRY (tcp_write_after_connect) -#endif - - TEST_ENTRY (tcp_writealot) - TEST_HELPER (tcp_writealot, tcp4_echo_server) - - TEST_ENTRY (tcp_try_write) - - TEST_ENTRY (tcp_write_queue_order) - - TEST_ENTRY (tcp_open) - TEST_HELPER (tcp_open, tcp4_echo_server) - - TEST_ENTRY (tcp_shutdown_after_write) - TEST_HELPER (tcp_shutdown_after_write, tcp4_echo_server) - - TEST_ENTRY (tcp_connect_error_after_write) - TEST_ENTRY (tcp_bind_error_addrinuse) - TEST_ENTRY (tcp_bind_error_addrnotavail_1) - TEST_ENTRY (tcp_bind_error_addrnotavail_2) - TEST_ENTRY (tcp_bind_error_fault) - TEST_ENTRY (tcp_bind_error_inval) - TEST_ENTRY (tcp_bind_localhost_ok) - TEST_ENTRY (tcp_bind_invalid_flags) - TEST_ENTRY (tcp_listen_without_bind) - TEST_ENTRY (tcp_connect_error_fault) - TEST_ENTRY (tcp_connect_timeout) - TEST_ENTRY (tcp_close_while_connecting) - TEST_ENTRY (tcp_close) -#ifndef _WIN32 - TEST_ENTRY (tcp_close_accept) -#endif - TEST_ENTRY (tcp_flags) - TEST_ENTRY (tcp_write_to_half_open_connection) - TEST_ENTRY (tcp_unexpected_read) - - TEST_ENTRY (tcp_read_stop) - TEST_HELPER (tcp_read_stop, tcp4_echo_server) - - TEST_ENTRY (tcp_bind6_error_addrinuse) - TEST_ENTRY (tcp_bind6_error_addrnotavail) - TEST_ENTRY (tcp_bind6_error_fault) - TEST_ENTRY (tcp_bind6_error_inval) - TEST_ENTRY (tcp_bind6_localhost_ok) - - TEST_ENTRY (udp_bind) - TEST_ENTRY (udp_bind_reuseaddr) - TEST_ENTRY (udp_send_and_recv) - TEST_ENTRY (udp_send_immediate) - TEST_ENTRY (udp_send_unreachable) - TEST_ENTRY (udp_dgram_too_big) - TEST_ENTRY (udp_dual_stack) - TEST_ENTRY (udp_ipv6_only) - TEST_ENTRY (udp_options) - TEST_ENTRY (udp_options6) - TEST_ENTRY (udp_no_autobind) - TEST_ENTRY (udp_multicast_interface) - TEST_ENTRY (udp_multicast_interface6) - TEST_ENTRY (udp_multicast_join) - TEST_ENTRY (udp_multicast_join6) - TEST_ENTRY (udp_multicast_ttl) - TEST_ENTRY (udp_try_send) - - TEST_ENTRY (udp_open) - TEST_HELPER (udp_open, udp4_echo_server) - - TEST_ENTRY (pipe_bind_error_addrinuse) - TEST_ENTRY (pipe_bind_error_addrnotavail) - TEST_ENTRY (pipe_bind_error_inval) - TEST_ENTRY (pipe_listen_without_bind) - TEST_ENTRY (pipe_getsockname) - TEST_ENTRY (pipe_getsockname_abstract) - TEST_ENTRY (pipe_getsockname_blocking) - TEST_ENTRY (pipe_sendmsg) - - TEST_ENTRY (connection_fail) - TEST_ENTRY (connection_fail_doesnt_auto_close) - - TEST_ENTRY (shutdown_close_tcp) - TEST_HELPER (shutdown_close_tcp, tcp4_echo_server) - TEST_ENTRY (shutdown_close_pipe) - TEST_HELPER (shutdown_close_pipe, pipe_echo_server) - - TEST_ENTRY (shutdown_eof) - TEST_HELPER (shutdown_eof, tcp4_echo_server) - - TEST_ENTRY (shutdown_twice) - TEST_HELPER (shutdown_twice, tcp4_echo_server) - - TEST_ENTRY (callback_stack) - TEST_HELPER (callback_stack, tcp4_echo_server) - - TEST_ENTRY (error_message) - - TEST_ENTRY (timer) - TEST_ENTRY (timer_init) - TEST_ENTRY (timer_again) - TEST_ENTRY (timer_start_twice) - TEST_ENTRY (timer_order) - TEST_ENTRY (timer_huge_timeout) - TEST_ENTRY (timer_huge_repeat) - TEST_ENTRY (timer_run_once) - TEST_ENTRY (timer_from_check) - TEST_ENTRY (timer_null_callback) - - TEST_ENTRY (idle_starvation) - - TEST_ENTRY (ref) - TEST_ENTRY (idle_ref) - TEST_ENTRY (fs_poll_ref) - TEST_ENTRY (async_ref) - TEST_ENTRY (prepare_ref) - TEST_ENTRY (check_ref) - TEST_ENTRY (unref_in_prepare_cb) - TEST_ENTRY (timer_ref) - TEST_ENTRY (timer_ref2) - TEST_ENTRY (fs_event_ref) - TEST_ENTRY (tcp_ref) - TEST_ENTRY (tcp_ref2) - TEST_ENTRY (tcp_ref2b) - TEST_ENTRY (tcp_ref3) - TEST_HELPER (tcp_ref3, tcp4_echo_server) - TEST_ENTRY (tcp_ref4) - TEST_HELPER (tcp_ref4, tcp4_echo_server) - TEST_ENTRY (udp_ref) - TEST_ENTRY (udp_ref2) - TEST_ENTRY (udp_ref3) - TEST_HELPER (udp_ref3, udp4_echo_server) - TEST_ENTRY (pipe_ref) - TEST_ENTRY (pipe_ref2) - TEST_ENTRY (pipe_ref3) - TEST_HELPER (pipe_ref3, pipe_echo_server) - TEST_ENTRY (pipe_ref4) - TEST_HELPER (pipe_ref4, pipe_echo_server) - TEST_ENTRY (process_ref) - TEST_ENTRY (has_ref) - - TEST_ENTRY (loop_handles) - TEST_ENTRY (walk_handles) - - TEST_ENTRY (watcher_cross_stop) - - TEST_ENTRY (active) - - TEST_ENTRY (embed) - - TEST_ENTRY (async) - TEST_ENTRY (async_null_cb) - - TEST_ENTRY (get_currentexe) - - TEST_ENTRY (process_title) - - TEST_ENTRY (cwd_and_chdir) - - TEST_ENTRY (get_memory) - - TEST_ENTRY (get_loadavg) - - TEST_ENTRY (handle_fileno) - - TEST_ENTRY (hrtime) - - TEST_ENTRY_CUSTOM (getaddrinfo_fail, 0, 0, 10000) - TEST_ENTRY (getaddrinfo_fail_sync) - - TEST_ENTRY (getaddrinfo_basic) - TEST_ENTRY (getaddrinfo_basic_sync) - TEST_ENTRY (getaddrinfo_concurrent) - - TEST_ENTRY (getnameinfo_basic_ip4) - TEST_ENTRY (getnameinfo_basic_ip4_sync) - TEST_ENTRY (getnameinfo_basic_ip6) - - TEST_ENTRY (getsockname_tcp) - TEST_ENTRY (getsockname_udp) - - TEST_ENTRY (poll_duplex) - TEST_ENTRY (poll_unidirectional) - TEST_ENTRY (poll_close) - - TEST_ENTRY (socket_buffer_size) - - TEST_ENTRY (spawn_fails) - TEST_ENTRY (spawn_exit_code) - TEST_ENTRY (spawn_stdout) - TEST_ENTRY (spawn_stdin) - TEST_ENTRY (spawn_stdio_greater_than_3) - TEST_ENTRY (spawn_ignored_stdio) - TEST_ENTRY (spawn_and_kill) - TEST_ENTRY (spawn_detached) - TEST_ENTRY (spawn_and_kill_with_std) - TEST_ENTRY (spawn_and_ping) - TEST_ENTRY (spawn_preserve_env) - TEST_ENTRY (spawn_setuid_fails) - TEST_ENTRY (spawn_setgid_fails) - TEST_ENTRY (spawn_stdout_to_file) - TEST_ENTRY (spawn_stdout_and_stderr_to_file) - TEST_ENTRY (spawn_auto_unref) - TEST_ENTRY (spawn_closed_process_io) - TEST_ENTRY (spawn_reads_child_path) - TEST_ENTRY (fs_poll) - TEST_ENTRY (fs_poll_getpath) - TEST_ENTRY (kill) - -#ifdef _WIN32 - TEST_ENTRY (poll_close_doesnt_corrupt_stack) - TEST_ENTRY (poll_closesocket) - TEST_ENTRY (spawn_detect_pipe_name_collisions_on_windows) - TEST_ENTRY (argument_escaping) - TEST_ENTRY (environment_creation) - TEST_ENTRY (listen_with_simultaneous_accepts) - TEST_ENTRY (listen_no_simultaneous_accepts) - TEST_ENTRY (fs_stat_root) - TEST_ENTRY (spawn_with_an_odd_path) - TEST_ENTRY (ipc_listen_after_bind_twice) -#else - TEST_ENTRY (emfile) - TEST_ENTRY (close_fd) - TEST_ENTRY (spawn_fs_open) - TEST_ENTRY (spawn_setuid_setgid) - TEST_ENTRY (we_get_signal) - TEST_ENTRY (we_get_signals) - TEST_ENTRY (signal_multiple_loops) - TEST_ENTRY (closed_fd_events) -#endif - -#ifdef __APPLE__ - TEST_ENTRY (osx_select) - TEST_ENTRY (osx_select_many_fds) -#endif - - TEST_ENTRY (fs_file_noent) - TEST_ENTRY (fs_file_nametoolong) - TEST_ENTRY (fs_file_loop) - TEST_ENTRY (fs_file_async) - TEST_ENTRY (fs_file_sync) - TEST_ENTRY (fs_file_write_null_buffer) - TEST_ENTRY (fs_async_dir) - TEST_ENTRY (fs_async_sendfile) - TEST_ENTRY (fs_mkdtemp) - TEST_ENTRY (fs_fstat) - TEST_ENTRY (fs_access) - TEST_ENTRY (fs_chmod) - TEST_ENTRY (fs_chown) - TEST_ENTRY (fs_utime) - TEST_ENTRY (fs_futime) - TEST_ENTRY (fs_readlink) - TEST_ENTRY (fs_symlink) - TEST_ENTRY (fs_symlink_dir) - TEST_ENTRY (fs_stat_missing_path) - TEST_ENTRY (fs_read_file_eof) - TEST_ENTRY (fs_file_open_append) - TEST_ENTRY (fs_event_watch_dir) - TEST_ENTRY (fs_event_watch_file) - TEST_ENTRY (fs_event_watch_file_twice) - TEST_ENTRY (fs_event_watch_file_current_dir) - TEST_ENTRY (fs_event_no_callback_after_close) - TEST_ENTRY (fs_event_no_callback_on_close) - TEST_ENTRY (fs_event_immediate_close) - TEST_ENTRY (fs_event_close_with_pending_event) - TEST_ENTRY (fs_event_close_in_callback) - TEST_ENTRY (fs_event_start_and_close) - TEST_ENTRY (fs_event_error_reporting) - TEST_ENTRY (fs_event_getpath) - TEST_ENTRY (fs_scandir_empty_dir) - TEST_ENTRY (fs_scandir_file) - TEST_ENTRY (fs_open_dir) - TEST_ENTRY (fs_rename_to_existing_file) - TEST_ENTRY (fs_write_multiple_bufs) - TEST_ENTRY (threadpool_queue_work_simple) - TEST_ENTRY (threadpool_queue_work_einval) - TEST_ENTRY (threadpool_multiple_event_loops) - TEST_ENTRY (threadpool_cancel_getaddrinfo) - TEST_ENTRY (threadpool_cancel_getnameinfo) - TEST_ENTRY (threadpool_cancel_work) - TEST_ENTRY (threadpool_cancel_fs) - TEST_ENTRY (threadpool_cancel_single) - TEST_ENTRY (thread_local_storage) - TEST_ENTRY (thread_mutex) - TEST_ENTRY (thread_rwlock) - TEST_ENTRY (thread_create) - TEST_ENTRY (thread_equal) - TEST_ENTRY (dlerror) - TEST_ENTRY (ip4_addr) - TEST_ENTRY (ip6_addr_link_local) -#if 0 - /* These are for testing the test runner. */ - TEST_ENTRY (fail_always) - TEST_ENTRY (pass_always) -#endif -TASK_LIST_END diff --git a/libuv/test/test-loop-alive.c b/libuv/test/test-loop-alive.c deleted file mode 100644 index cf4d301..0000000 --- a/libuv/test/test-loop-alive.c +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -static uv_timer_t timer_handle; - -static void timer_cb(uv_timer_t* handle) { - ASSERT(handle); -} - - -static uv_work_t work_req; - -static void work_cb(uv_work_t* req) { - ASSERT(req); -} - -static void after_work_cb(uv_work_t* req, int status) { - ASSERT(req); - ASSERT(status == 0); -} - - -TEST_IMPL(loop_alive) { - int r; - ASSERT(!uv_loop_alive(uv_default_loop())); - - /* loops with handles are alive */ - uv_timer_init(uv_default_loop(), &timer_handle); - uv_timer_start(&timer_handle, timer_cb, 100, 0); - ASSERT(uv_loop_alive(uv_default_loop())); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - ASSERT(!uv_loop_alive(uv_default_loop())); - - /* loops with requests are alive */ - r = uv_queue_work(uv_default_loop(), &work_req, work_cb, after_work_cb); - ASSERT(r == 0); - ASSERT(uv_loop_alive(uv_default_loop())); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - ASSERT(!uv_loop_alive(uv_default_loop())); - - return 0; -} diff --git a/libuv/test/test-loop-close.c b/libuv/test/test-loop-close.c deleted file mode 100644 index 5aec234..0000000 --- a/libuv/test/test-loop-close.c +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -static uv_timer_t timer_handle; - -static void timer_cb(uv_timer_t* handle) { - ASSERT(handle); - uv_stop(handle->loop); -} - - -TEST_IMPL(loop_close) { - int r; - uv_loop_t loop; - - ASSERT(0 == uv_loop_init(&loop)); - - uv_timer_init(&loop, &timer_handle); - uv_timer_start(&timer_handle, timer_cb, 100, 100); - - ASSERT(UV_EBUSY == uv_loop_close(&loop)); - - uv_run(&loop, UV_RUN_DEFAULT); - - uv_close((uv_handle_t*) &timer_handle, NULL); - r = uv_run(&loop, UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(0 == uv_loop_close(&loop)); - - return 0; -} diff --git a/libuv/test/test-loop-configure.c b/libuv/test/test-loop-configure.c deleted file mode 100644 index d057c1e..0000000 --- a/libuv/test/test-loop-configure.c +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright (c) 2014, Ben Noordhuis - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -static void timer_cb(uv_timer_t* handle) { - uv_close((uv_handle_t*) handle, NULL); -} - - -TEST_IMPL(loop_configure) { - uv_timer_t timer_handle; - uv_loop_t loop; - ASSERT(0 == uv_loop_init(&loop)); -#ifdef _WIN32 - ASSERT(UV_ENOSYS == uv_loop_configure(&loop, UV_LOOP_BLOCK_SIGNAL, 0)); -#else - ASSERT(0 == uv_loop_configure(&loop, UV_LOOP_BLOCK_SIGNAL, SIGPROF)); -#endif - ASSERT(0 == uv_timer_init(&loop, &timer_handle)); - ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 10, 0)); - ASSERT(0 == uv_run(&loop, UV_RUN_DEFAULT)); - ASSERT(0 == uv_loop_close(&loop)); - return 0; -} diff --git a/libuv/test/test-loop-handles.c b/libuv/test/test-loop-handles.c deleted file mode 100644 index 0986de5..0000000 --- a/libuv/test/test-loop-handles.c +++ /dev/null @@ -1,330 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* Tests commented out with XXX are ones that are failing on Linux */ - -/* - * Purpose of this test is to check semantics of starting and stopping - * prepare, check and idle watchers. - * - * - A watcher must be able to safely stop or close itself; - * - Once a watcher is stopped or closed its callback should never be called. - * - If a watcher is closed, it is implicitly stopped and its close_cb should - * be called exactly once. - * - A watcher can safely start and stop other watchers of the same type. - * - Prepare and check watchers are called once per event loop iterations. - * - All active idle watchers are queued when the event loop has no more work - * to do. This is done repeatedly until all idle watchers are inactive. - * - If a watcher starts another watcher of the same type its callback is not - * immediately queued. For check and prepare watchers, that means that if - * a watcher makes another of the same type active, it'll not be called until - * the next event loop iteration. For idle. watchers this means that the - * newly activated idle watcher might not be queued immediately. - * - Prepare, check, idle watchers keep the event loop alive even when they're - * not active. - * - * This is what the test globally does: - * - * - prepare_1 is always active and counts event loop iterations. It also - * creates and starts prepare_2 every other iteration. Finally it verifies - * that no idle watchers are active before polling. - * - prepare_2 is started by prepare_1 every other iteration. It immediately - * stops itself. It verifies that a watcher is not queued immediately - * if created by another watcher of the same type. - * - There's a check watcher that stops the event loop after a certain number - * of iterations. It starts a varying number of idle_1 watchers. - * - Idle_1 watchers stop themselves after being called a few times. All idle_1 - * watchers try to start the idle_2 watcher if it is not already started or - * awaiting its close callback. - * - The idle_2 watcher always exists but immediately closes itself after - * being started by a check_1 watcher. It verifies that a watcher is - * implicitly stopped when closed, and that a watcher can close itself - * safely. - * - There is a repeating timer. It does not keep the event loop alive - * (ev_unref) but makes sure that the loop keeps polling the system for - * events. - */ - - -#include "uv.h" -#include "task.h" - -#include - - -#define IDLE_COUNT 7 -#define ITERATIONS 21 -#define TIMEOUT 100 - - -static uv_prepare_t prepare_1_handle; -static uv_prepare_t prepare_2_handle; - -static uv_check_t check_handle; - -static uv_idle_t idle_1_handles[IDLE_COUNT]; -static uv_idle_t idle_2_handle; - -static uv_timer_t timer_handle; - - -static int loop_iteration = 0; - -static int prepare_1_cb_called = 0; -static int prepare_1_close_cb_called = 0; - -static int prepare_2_cb_called = 0; -static int prepare_2_close_cb_called = 0; - -static int check_cb_called = 0; -static int check_close_cb_called = 0; - -static int idle_1_cb_called = 0; -static int idle_1_close_cb_called = 0; -static int idles_1_active = 0; - -static int idle_2_cb_called = 0; -static int idle_2_close_cb_called = 0; -static int idle_2_cb_started = 0; -static int idle_2_is_active = 0; - - -static void timer_cb(uv_timer_t* handle) { - ASSERT(handle == &timer_handle); -} - - -static void idle_2_close_cb(uv_handle_t* handle) { - LOG("IDLE_2_CLOSE_CB\n"); - - ASSERT(handle == (uv_handle_t*)&idle_2_handle); - - ASSERT(idle_2_is_active); - - idle_2_close_cb_called++; - idle_2_is_active = 0; -} - - -static void idle_2_cb(uv_idle_t* handle) { - LOG("IDLE_2_CB\n"); - - ASSERT(handle == &idle_2_handle); - - idle_2_cb_called++; - - uv_close((uv_handle_t*)handle, idle_2_close_cb); -} - - -static void idle_1_cb(uv_idle_t* handle) { - int r; - - LOG("IDLE_1_CB\n"); - - ASSERT(handle != NULL); - ASSERT(idles_1_active > 0); - - /* Init idle_2 and make it active */ - if (!idle_2_is_active && !uv_is_closing((uv_handle_t*)&idle_2_handle)) { - r = uv_idle_init(uv_default_loop(), &idle_2_handle); - ASSERT(r == 0); - r = uv_idle_start(&idle_2_handle, idle_2_cb); - ASSERT(r == 0); - idle_2_is_active = 1; - idle_2_cb_started++; - } - - idle_1_cb_called++; - - if (idle_1_cb_called % 5 == 0) { - r = uv_idle_stop((uv_idle_t*)handle); - ASSERT(r == 0); - idles_1_active--; - } -} - - -static void idle_1_close_cb(uv_handle_t* handle) { - LOG("IDLE_1_CLOSE_CB\n"); - - ASSERT(handle != NULL); - - idle_1_close_cb_called++; -} - - -static void prepare_1_close_cb(uv_handle_t* handle) { - LOG("PREPARE_1_CLOSE_CB"); - ASSERT(handle == (uv_handle_t*)&prepare_1_handle); - - prepare_1_close_cb_called++; -} - - -static void check_close_cb(uv_handle_t* handle) { - LOG("CHECK_CLOSE_CB\n"); - ASSERT(handle == (uv_handle_t*)&check_handle); - - check_close_cb_called++; -} - - -static void prepare_2_close_cb(uv_handle_t* handle) { - LOG("PREPARE_2_CLOSE_CB\n"); - ASSERT(handle == (uv_handle_t*)&prepare_2_handle); - - prepare_2_close_cb_called++; -} - - -static void check_cb(uv_check_t* handle) { - int i, r; - - LOG("CHECK_CB\n"); - - ASSERT(handle == &check_handle); - - if (loop_iteration < ITERATIONS) { - /* Make some idle watchers active */ - for (i = 0; i < 1 + (loop_iteration % IDLE_COUNT); i++) { - r = uv_idle_start(&idle_1_handles[i], idle_1_cb); - ASSERT(r == 0); - idles_1_active++; - } - - } else { - /* End of the test - close all handles */ - uv_close((uv_handle_t*)&prepare_1_handle, prepare_1_close_cb); - uv_close((uv_handle_t*)&check_handle, check_close_cb); - uv_close((uv_handle_t*)&prepare_2_handle, prepare_2_close_cb); - - for (i = 0; i < IDLE_COUNT; i++) { - uv_close((uv_handle_t*)&idle_1_handles[i], idle_1_close_cb); - } - - /* This handle is closed/recreated every time, close it only if it is */ - /* active.*/ - if (idle_2_is_active) { - uv_close((uv_handle_t*)&idle_2_handle, idle_2_close_cb); - } - } - - check_cb_called++; -} - - -static void prepare_2_cb(uv_prepare_t* handle) { - int r; - - LOG("PREPARE_2_CB\n"); - - ASSERT(handle == &prepare_2_handle); - - /* prepare_2 gets started by prepare_1 when (loop_iteration % 2 == 0), */ - /* and it stops itself immediately. A started watcher is not queued */ - /* until the next round, so when this callback is made */ - /* (loop_iteration % 2 == 0) cannot be true. */ - ASSERT(loop_iteration % 2 != 0); - - r = uv_prepare_stop((uv_prepare_t*)handle); - ASSERT(r == 0); - - prepare_2_cb_called++; -} - - -static void prepare_1_cb(uv_prepare_t* handle) { - int r; - - LOG("PREPARE_1_CB\n"); - - ASSERT(handle == &prepare_1_handle); - - if (loop_iteration % 2 == 0) { - r = uv_prepare_start(&prepare_2_handle, prepare_2_cb); - ASSERT(r == 0); - } - - prepare_1_cb_called++; - loop_iteration++; - - printf("Loop iteration %d of %d.\n", loop_iteration, ITERATIONS); -} - - -TEST_IMPL(loop_handles) { - int i; - int r; - - r = uv_prepare_init(uv_default_loop(), &prepare_1_handle); - ASSERT(r == 0); - r = uv_prepare_start(&prepare_1_handle, prepare_1_cb); - ASSERT(r == 0); - - r = uv_check_init(uv_default_loop(), &check_handle); - ASSERT(r == 0); - r = uv_check_start(&check_handle, check_cb); - ASSERT(r == 0); - - /* initialize only, prepare_2 is started by prepare_1_cb */ - r = uv_prepare_init(uv_default_loop(), &prepare_2_handle); - ASSERT(r == 0); - - for (i = 0; i < IDLE_COUNT; i++) { - /* initialize only, idle_1 handles are started by check_cb */ - r = uv_idle_init(uv_default_loop(), &idle_1_handles[i]); - ASSERT(r == 0); - } - - /* don't init or start idle_2, both is done by idle_1_cb */ - - /* the timer callback is there to keep the event loop polling */ - /* unref it as it is not supposed to keep the loop alive */ - r = uv_timer_init(uv_default_loop(), &timer_handle); - ASSERT(r == 0); - r = uv_timer_start(&timer_handle, timer_cb, TIMEOUT, TIMEOUT); - ASSERT(r == 0); - uv_unref((uv_handle_t*)&timer_handle); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(loop_iteration == ITERATIONS); - - ASSERT(prepare_1_cb_called == ITERATIONS); - ASSERT(prepare_1_close_cb_called == 1); - - ASSERT(prepare_2_cb_called == floor(ITERATIONS / 2.0)); - ASSERT(prepare_2_close_cb_called == 1); - - ASSERT(check_cb_called == ITERATIONS); - ASSERT(check_close_cb_called == 1); - - /* idle_1_cb should be called a lot */ - ASSERT(idle_1_close_cb_called == IDLE_COUNT); - - ASSERT(idle_2_close_cb_called == idle_2_cb_started); - ASSERT(idle_2_is_active == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-loop-stop.c b/libuv/test/test-loop-stop.c deleted file mode 100644 index 14b8c11..0000000 --- a/libuv/test/test-loop-stop.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -static uv_prepare_t prepare_handle; -static uv_timer_t timer_handle; -static int prepare_called = 0; -static int timer_called = 0; -static int num_ticks = 10; - - -static void prepare_cb(uv_prepare_t* handle) { - ASSERT(handle == &prepare_handle); - prepare_called++; - if (prepare_called == num_ticks) - uv_prepare_stop(handle); -} - - -static void timer_cb(uv_timer_t* handle) { - ASSERT(handle == &timer_handle); - timer_called++; - if (timer_called == 1) - uv_stop(uv_default_loop()); - else if (timer_called == num_ticks) - uv_timer_stop(handle); -} - - -TEST_IMPL(loop_stop) { - int r; - uv_prepare_init(uv_default_loop(), &prepare_handle); - uv_prepare_start(&prepare_handle, prepare_cb); - uv_timer_init(uv_default_loop(), &timer_handle); - uv_timer_start(&timer_handle, timer_cb, 100, 100); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r != 0); - ASSERT(timer_called == 1); - - r = uv_run(uv_default_loop(), UV_RUN_NOWAIT); - ASSERT(r != 0); - ASSERT(prepare_called > 1); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - ASSERT(timer_called == 10); - ASSERT(prepare_called == 10); - - return 0; -} diff --git a/libuv/test/test-loop-time.c b/libuv/test/test-loop-time.c deleted file mode 100644 index a2db42c..0000000 --- a/libuv/test/test-loop-time.c +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - - -TEST_IMPL(loop_update_time) { - uint64_t start; - - start = uv_now(uv_default_loop()); - while (uv_now(uv_default_loop()) - start < 1000) - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_NOWAIT)); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -static void cb(uv_timer_t* timer) { - uv_close((uv_handle_t*)timer, NULL); -} - -TEST_IMPL(loop_backend_timeout) { - uv_loop_t *loop = uv_default_loop(); - uv_timer_t timer; - int r; - - r = uv_timer_init(loop, &timer); - ASSERT(r == 0); - - ASSERT(!uv_loop_alive(loop)); - ASSERT(uv_backend_timeout(loop) == 0); - - r = uv_timer_start(&timer, cb, 1000, 0); /* 1 sec */ - ASSERT(r == 0); - ASSERT(uv_backend_timeout(loop) > 100); /* 0.1 sec */ - ASSERT(uv_backend_timeout(loop) <= 1000); /* 1 sec */ - - r = uv_run(loop, UV_RUN_DEFAULT); - ASSERT(r == 0); - ASSERT(uv_backend_timeout(loop) == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-multiple-listen.c b/libuv/test/test-multiple-listen.c deleted file mode 100644 index 4ae5fa6..0000000 --- a/libuv/test/test-multiple-listen.c +++ /dev/null @@ -1,109 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" -#include -#include - -static int connection_cb_called = 0; -static int close_cb_called = 0; -static int connect_cb_called = 0; -static uv_tcp_t server; -static uv_tcp_t client; - - -static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); - close_cb_called++; -} - - -static void connection_cb(uv_stream_t* tcp, int status) { - ASSERT(status == 0); - uv_close((uv_handle_t*)&server, close_cb); - connection_cb_called++; -} - - -static void start_server(void) { - struct sockaddr_in addr; - int r; - - ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); - - r = uv_tcp_init(uv_default_loop(), &server); - ASSERT(r == 0); - - r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - - r = uv_listen((uv_stream_t*)&server, 128, connection_cb); - ASSERT(r == 0); - - r = uv_listen((uv_stream_t*)&server, 128, connection_cb); - ASSERT(r == 0); -} - - -static void connect_cb(uv_connect_t* req, int status) { - ASSERT(req != NULL); - ASSERT(status == 0); - free(req); - uv_close((uv_handle_t*)&client, close_cb); - connect_cb_called++; -} - - -static void client_connect(void) { - struct sockaddr_in addr; - uv_connect_t* connect_req = malloc(sizeof *connect_req); - int r; - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - ASSERT(connect_req != NULL); - - r = uv_tcp_init(uv_default_loop(), &client); - ASSERT(r == 0); - - r = uv_tcp_connect(connect_req, - &client, - (const struct sockaddr*) &addr, - connect_cb); - ASSERT(r == 0); -} - - - -TEST_IMPL(multiple_listen) { - start_server(); - - client_connect(); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(connection_cb_called == 1); - ASSERT(connect_cb_called == 1); - ASSERT(close_cb_called == 2); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-mutexes.c b/libuv/test/test-mutexes.c deleted file mode 100644 index 896f46b..0000000 --- a/libuv/test/test-mutexes.c +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include - - -/* The mutex and rwlock tests are really poor. - * They're very basic sanity checks and nothing more. - * Apologies if that rhymes. - */ - -TEST_IMPL(thread_mutex) { - uv_mutex_t mutex; - int r; - - r = uv_mutex_init(&mutex); - ASSERT(r == 0); - - uv_mutex_lock(&mutex); - uv_mutex_unlock(&mutex); - uv_mutex_destroy(&mutex); - - return 0; -} - - -TEST_IMPL(thread_rwlock) { - uv_rwlock_t rwlock; - int r; - - r = uv_rwlock_init(&rwlock); - ASSERT(r == 0); - - uv_rwlock_rdlock(&rwlock); - uv_rwlock_rdunlock(&rwlock); - uv_rwlock_wrlock(&rwlock); - uv_rwlock_wrunlock(&rwlock); - uv_rwlock_destroy(&rwlock); - - return 0; -} diff --git a/libuv/test/test-osx-select.c b/libuv/test/test-osx-select.c deleted file mode 100644 index 6ccf603..0000000 --- a/libuv/test/test-osx-select.c +++ /dev/null @@ -1,137 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#ifdef __APPLE__ - -#include -#include - -static int read_count; - - -static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) { - static char slab[1024]; - buf->base = slab; - buf->len = sizeof(slab); -} - - -static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { - fprintf(stdout, "got data %d\n", ++read_count); - - if (read_count == 3) - uv_close((uv_handle_t*) stream, NULL); -} - - -TEST_IMPL(osx_select) { - int r; - int fd; - size_t i; - size_t len; - const char* str; - uv_tty_t tty; - - fd = open("/dev/tty", O_RDONLY); - if (fd < 0) { - LOGF("Cannot open /dev/tty as read-only: %s\n", strerror(errno)); - return TEST_SKIP; - } - - r = uv_tty_init(uv_default_loop(), &tty, fd, 1); - ASSERT(r == 0); - - uv_read_start((uv_stream_t*) &tty, alloc_cb, read_cb); - - /* Emulate user-input */ - str = "got some input\n" - "with a couple of lines\n" - "feel pretty happy\n"; - for (i = 0, len = strlen(str); i < len; i++) { - r = ioctl(fd, TIOCSTI, str + i); - ASSERT(r == 0); - } - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(read_count == 3); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(osx_select_many_fds) { - int r; - int fd; - size_t i; - size_t len; - const char* str; - struct sockaddr_in addr; - uv_tty_t tty; - uv_tcp_t tcps[1500]; - - TEST_FILE_LIMIT(ARRAY_SIZE(tcps) + 100); - - r = uv_ip4_addr("127.0.0.1", 0, &addr); - ASSERT(r == 0); - - for (i = 0; i < ARRAY_SIZE(tcps); i++) { - r = uv_tcp_init(uv_default_loop(), &tcps[i]); - ASSERT(r == 0); - r = uv_tcp_bind(&tcps[i], (const struct sockaddr *) &addr, 0); - ASSERT(r == 0); - uv_unref((uv_handle_t*) &tcps[i]); - } - - fd = open("/dev/tty", O_RDONLY); - if (fd < 0) { - LOGF("Cannot open /dev/tty as read-only: %s\n", strerror(errno)); - return TEST_SKIP; - } - - r = uv_tty_init(uv_default_loop(), &tty, fd, 1); - ASSERT(r == 0); - - r = uv_read_start((uv_stream_t*) &tty, alloc_cb, read_cb); - ASSERT(r == 0); - - /* Emulate user-input */ - str = "got some input\n" - "with a couple of lines\n" - "feel pretty happy\n"; - for (i = 0, len = strlen(str); i < len; i++) { - r = ioctl(fd, TIOCSTI, str + i); - ASSERT(r == 0); - } - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(read_count == 3); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -#endif /* __APPLE__ */ diff --git a/libuv/test/test-pass-always.c b/libuv/test/test-pass-always.c deleted file mode 100644 index 4fb58ff..0000000 --- a/libuv/test/test-pass-always.c +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "task.h" - - -TEST_IMPL(pass_always) { - /* This test always passes. It is used to test the test runner. */ - return 0; -} diff --git a/libuv/test/test-ping-pong.c b/libuv/test/test-ping-pong.c deleted file mode 100644 index c074178..0000000 --- a/libuv/test/test-ping-pong.c +++ /dev/null @@ -1,270 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include - -static int completed_pingers = 0; - -#define NUM_PINGS 1000 - -/* 64 bytes is enough for a pinger */ -#define BUFSIZE 10240 - -static char PING[] = "PING\n"; -static int pinger_on_connect_count; - - -typedef struct { - int pongs; - int state; - union { - uv_tcp_t tcp; - uv_pipe_t pipe; - } stream; - uv_connect_t connect_req; - char read_buffer[BUFSIZE]; -} pinger_t; - - -static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) { - buf->base = malloc(size); - buf->len = size; -} - - -static void pinger_on_close(uv_handle_t* handle) { - pinger_t* pinger = (pinger_t*)handle->data; - - ASSERT(NUM_PINGS == pinger->pongs); - - free(pinger); - - completed_pingers++; -} - - -static void pinger_after_write(uv_write_t *req, int status) { - ASSERT(status == 0); - free(req); -} - - -static void pinger_write_ping(pinger_t* pinger) { - uv_write_t *req; - uv_buf_t buf; - - buf = uv_buf_init(PING, sizeof(PING) - 1); - - req = malloc(sizeof(*req)); - if (uv_write(req, - (uv_stream_t*) &pinger->stream.tcp, - &buf, - 1, - pinger_after_write)) { - FATAL("uv_write failed"); - } - - puts("PING"); -} - - -static void pinger_read_cb(uv_stream_t* stream, - ssize_t nread, - const uv_buf_t* buf) { - ssize_t i; - pinger_t* pinger; - - pinger = (pinger_t*)stream->data; - - if (nread < 0) { - ASSERT(nread == UV_EOF); - - puts("got EOF"); - free(buf->base); - - uv_close((uv_handle_t*)(&pinger->stream.tcp), pinger_on_close); - - return; - } - - /* Now we count the pings */ - for (i = 0; i < nread; i++) { - ASSERT(buf->base[i] == PING[pinger->state]); - pinger->state = (pinger->state + 1) % (sizeof(PING) - 1); - - if (pinger->state != 0) - continue; - - printf("PONG %d\n", pinger->pongs); - pinger->pongs++; - - if (pinger->pongs < NUM_PINGS) { - pinger_write_ping(pinger); - } else { - uv_close((uv_handle_t*)(&pinger->stream.tcp), pinger_on_close); - break; - } - } - - free(buf->base); -} - - -static void pinger_on_connect(uv_connect_t *req, int status) { - pinger_t *pinger = (pinger_t*)req->handle->data; - - pinger_on_connect_count++; - - ASSERT(status == 0); - - ASSERT(1 == uv_is_readable(req->handle)); - ASSERT(1 == uv_is_writable(req->handle)); - ASSERT(0 == uv_is_closing((uv_handle_t *) req->handle)); - - pinger_write_ping(pinger); - - uv_read_start((uv_stream_t*)(req->handle), alloc_cb, pinger_read_cb); -} - - -/* same ping-pong test, but using IPv6 connection */ -static void tcp_pinger_v6_new(void) { - int r; - struct sockaddr_in6 server_addr; - pinger_t *pinger; - - - ASSERT(0 ==uv_ip6_addr("::1", TEST_PORT, &server_addr)); - pinger = malloc(sizeof(*pinger)); - ASSERT(pinger != NULL); - pinger->state = 0; - pinger->pongs = 0; - - /* Try to connect to the server and do NUM_PINGS ping-pongs. */ - r = uv_tcp_init(uv_default_loop(), &pinger->stream.tcp); - pinger->stream.tcp.data = pinger; - ASSERT(!r); - - /* We are never doing multiple reads/connects at a time anyway. */ - /* so these handles can be pre-initialized. */ - r = uv_tcp_connect(&pinger->connect_req, - &pinger->stream.tcp, - (const struct sockaddr*) &server_addr, - pinger_on_connect); - ASSERT(!r); - - /* Synchronous connect callbacks are not allowed. */ - ASSERT(pinger_on_connect_count == 0); -} - - -static void tcp_pinger_new(void) { - int r; - struct sockaddr_in server_addr; - pinger_t *pinger; - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &server_addr)); - pinger = malloc(sizeof(*pinger)); - ASSERT(pinger != NULL); - pinger->state = 0; - pinger->pongs = 0; - - /* Try to connect to the server and do NUM_PINGS ping-pongs. */ - r = uv_tcp_init(uv_default_loop(), &pinger->stream.tcp); - pinger->stream.tcp.data = pinger; - ASSERT(!r); - - /* We are never doing multiple reads/connects at a time anyway. */ - /* so these handles can be pre-initialized. */ - r = uv_tcp_connect(&pinger->connect_req, - &pinger->stream.tcp, - (const struct sockaddr*) &server_addr, - pinger_on_connect); - ASSERT(!r); - - /* Synchronous connect callbacks are not allowed. */ - ASSERT(pinger_on_connect_count == 0); -} - - -static void pipe_pinger_new(void) { - int r; - pinger_t *pinger; - - pinger = (pinger_t*)malloc(sizeof(*pinger)); - ASSERT(pinger != NULL); - pinger->state = 0; - pinger->pongs = 0; - - /* Try to connect to the server and do NUM_PINGS ping-pongs. */ - r = uv_pipe_init(uv_default_loop(), &pinger->stream.pipe, 0); - pinger->stream.pipe.data = pinger; - ASSERT(!r); - - /* We are never doing multiple reads/connects at a time anyway. */ - /* so these handles can be pre-initialized. */ - - uv_pipe_connect(&pinger->connect_req, &pinger->stream.pipe, TEST_PIPENAME, - pinger_on_connect); - - /* Synchronous connect callbacks are not allowed. */ - ASSERT(pinger_on_connect_count == 0); -} - - -TEST_IMPL(tcp_ping_pong) { - tcp_pinger_new(); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(completed_pingers == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(tcp_ping_pong_v6) { - if (!can_ipv6()) - RETURN_SKIP("IPv6 not supported"); - - tcp_pinger_v6_new(); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(completed_pingers == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(pipe_ping_pong) { - pipe_pinger_new(); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(completed_pingers == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-pipe-bind-error.c b/libuv/test/test-pipe-bind-error.c deleted file mode 100644 index 38b57db..0000000 --- a/libuv/test/test-pipe-bind-error.c +++ /dev/null @@ -1,136 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" -#include -#include - - -#ifdef _WIN32 -# define BAD_PIPENAME "bad-pipe" -#else -# define BAD_PIPENAME "/path/to/unix/socket/that/really/should/not/be/there" -#endif - - -static int close_cb_called = 0; - - -static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); - close_cb_called++; -} - - -TEST_IMPL(pipe_bind_error_addrinuse) { - uv_pipe_t server1, server2; - int r; - - r = uv_pipe_init(uv_default_loop(), &server1, 0); - ASSERT(r == 0); - r = uv_pipe_bind(&server1, TEST_PIPENAME); - ASSERT(r == 0); - - r = uv_pipe_init(uv_default_loop(), &server2, 0); - ASSERT(r == 0); - r = uv_pipe_bind(&server2, TEST_PIPENAME); - ASSERT(r == UV_EADDRINUSE); - - r = uv_listen((uv_stream_t*)&server1, SOMAXCONN, NULL); - ASSERT(r == 0); - r = uv_listen((uv_stream_t*)&server2, SOMAXCONN, NULL); - ASSERT(r == UV_EINVAL); - - uv_close((uv_handle_t*)&server1, close_cb); - uv_close((uv_handle_t*)&server2, close_cb); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(close_cb_called == 2); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(pipe_bind_error_addrnotavail) { - uv_pipe_t server; - int r; - - r = uv_pipe_init(uv_default_loop(), &server, 0); - ASSERT(r == 0); - - r = uv_pipe_bind(&server, BAD_PIPENAME); - ASSERT(r == UV_EACCES); - - uv_close((uv_handle_t*)&server, close_cb); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(pipe_bind_error_inval) { - uv_pipe_t server; - int r; - - r = uv_pipe_init(uv_default_loop(), &server, 0); - ASSERT(r == 0); - r = uv_pipe_bind(&server, TEST_PIPENAME); - ASSERT(r == 0); - r = uv_pipe_bind(&server, TEST_PIPENAME_2); - ASSERT(r == UV_EINVAL); - - uv_close((uv_handle_t*)&server, close_cb); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(pipe_listen_without_bind) { - uv_pipe_t server; - int r; - - r = uv_pipe_init(uv_default_loop(), &server, 0); - ASSERT(r == 0); - - r = uv_listen((uv_stream_t*)&server, SOMAXCONN, NULL); - ASSERT(r == UV_EINVAL); - - uv_close((uv_handle_t*)&server, close_cb); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-pipe-close-stdout-read-stdin.c b/libuv/test/test-pipe-close-stdout-read-stdin.c deleted file mode 100644 index ee8bb2a..0000000 --- a/libuv/test/test-pipe-close-stdout-read-stdin.c +++ /dev/null @@ -1,104 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef _WIN32 - -#include -#include -#include -#include - -#include "uv.h" -#include "task.h" - -void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t* buf) -{ - static char buffer[1024]; - - buf->base = buffer; - buf->len = sizeof(buffer); -} - -void read_stdin(uv_stream_t *stream, ssize_t nread, const uv_buf_t* buf) -{ - if (nread < 0) { - uv_close((uv_handle_t*)stream, NULL); - return; - } -} - -/* - * This test is a reproduction of joyent/libuv#1419 . - */ -TEST_IMPL(pipe_close_stdout_read_stdin) { - int r = -1; - int pid; - int fd[2]; - int status; - uv_pipe_t stdin_pipe; - - r = pipe(fd); - ASSERT(r == 0); - - if ((pid = fork()) == 0) { - /* - * Make the read side of the pipe our stdin. - * The write side will be closed by the parent process. - */ - close(fd[1]); - close(0); - r = dup(fd[0]); - ASSERT(r != -1); - - /* Create a stream that reads from the pipe. */ - r = uv_pipe_init(uv_default_loop(), (uv_pipe_t *)&stdin_pipe, 0); - ASSERT(r == 0); - - r = uv_pipe_open((uv_pipe_t *)&stdin_pipe, 0); - ASSERT(r == 0); - - r = uv_read_start((uv_stream_t *)&stdin_pipe, alloc_buffer, read_stdin); - ASSERT(r == 0); - - /* - * Because the other end of the pipe was closed, there should - * be no event left to process after one run of the event loop. - * Otherwise, it means that events were not processed correctly. - */ - ASSERT(uv_run(uv_default_loop(), UV_RUN_NOWAIT) == 0); - } else { - /* - * Close both ends of the pipe so that the child - * get a POLLHUP event when it tries to read from - * the other end. - */ - close(fd[1]); - close(fd[0]); - - waitpid(pid, &status, 0); - ASSERT(WIFEXITED(status) && WEXITSTATUS(status) == 0); - } - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -#endif /* ifndef _WIN32 */ diff --git a/libuv/test/test-pipe-connect-error.c b/libuv/test/test-pipe-connect-error.c deleted file mode 100644 index ebb2a6c..0000000 --- a/libuv/test/test-pipe-connect-error.c +++ /dev/null @@ -1,95 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" -#include -#include - - -#ifdef _WIN32 -# define BAD_PIPENAME "bad-pipe" -#else -# define BAD_PIPENAME "/path/to/unix/socket/that/really/should/not/be/there" -#endif - - -static int close_cb_called = 0; -static int connect_cb_called = 0; - - -static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); - close_cb_called++; -} - - -static void connect_cb(uv_connect_t* connect_req, int status) { - ASSERT(status == UV_ENOENT); - uv_close((uv_handle_t*)connect_req->handle, close_cb); - connect_cb_called++; -} - - -static void connect_cb_file(uv_connect_t* connect_req, int status) { - ASSERT(status == UV_ENOTSOCK || status == UV_ECONNREFUSED); - uv_close((uv_handle_t*)connect_req->handle, close_cb); - connect_cb_called++; -} - - -TEST_IMPL(pipe_connect_bad_name) { - uv_pipe_t client; - uv_connect_t req; - int r; - - r = uv_pipe_init(uv_default_loop(), &client, 0); - ASSERT(r == 0); - uv_pipe_connect(&req, &client, BAD_PIPENAME, connect_cb); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(close_cb_called == 1); - ASSERT(connect_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(pipe_connect_to_file) { - const char* path = "test/fixtures/empty_file"; - uv_pipe_t client; - uv_connect_t req; - int r; - - r = uv_pipe_init(uv_default_loop(), &client, 0); - ASSERT(r == 0); - uv_pipe_connect(&req, &client, path, connect_cb_file); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(close_cb_called == 1); - ASSERT(connect_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-pipe-getsockname.c b/libuv/test/test-pipe-getsockname.c deleted file mode 100644 index 5e036f9..0000000 --- a/libuv/test/test-pipe-getsockname.c +++ /dev/null @@ -1,263 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" -#include -#include -#include - -#if defined(__linux__) - #include - #include -#endif - -#ifndef _WIN32 -# include /* close */ -#else -# include -#endif - -static uv_pipe_t pipe_client; -static uv_pipe_t pipe_server; -static uv_connect_t connect_req; - -static int pipe_close_cb_called = 0; -static int pipe_client_connect_cb_called = 0; - - -static void pipe_close_cb(uv_handle_t* handle) { - ASSERT(handle == (uv_handle_t*) &pipe_client || - handle == (uv_handle_t*) &pipe_server); - pipe_close_cb_called++; -} - - -static void pipe_client_connect_cb(uv_connect_t* req, int status) { - char buf[1024]; - size_t len; - int r; - - ASSERT(req == &connect_req); - ASSERT(status == 0); - - len = sizeof buf; - r = uv_pipe_getpeername(&pipe_client, buf, &len); - ASSERT(r == 0); - - ASSERT(buf[len - 1] != 0); - ASSERT(memcmp(buf, TEST_PIPENAME, len) == 0); - - len = sizeof buf; - r = uv_pipe_getsockname(&pipe_client, buf, &len); - ASSERT(r == 0 && len == 0); - - pipe_client_connect_cb_called++; - - - uv_close((uv_handle_t*) &pipe_client, pipe_close_cb); - uv_close((uv_handle_t*) &pipe_server, pipe_close_cb); -} - - -static void pipe_server_connection_cb(uv_stream_t* handle, int status) { - /* This function *may* be called, depending on whether accept or the - * connection callback is called first. - */ - ASSERT(status == 0); -} - - -TEST_IMPL(pipe_getsockname) { - uv_loop_t* loop; - char buf[1024]; - size_t len; - int r; - - loop = uv_default_loop(); - ASSERT(loop != NULL); - - r = uv_pipe_init(loop, &pipe_server, 0); - ASSERT(r == 0); - - len = sizeof buf; - r = uv_pipe_getsockname(&pipe_server, buf, &len); - ASSERT(r == UV_EBADF); - - len = sizeof buf; - r = uv_pipe_getpeername(&pipe_server, buf, &len); - ASSERT(r == UV_EBADF); - - r = uv_pipe_bind(&pipe_server, TEST_PIPENAME); - ASSERT(r == 0); - - len = sizeof buf; - r = uv_pipe_getsockname(&pipe_server, buf, &len); - ASSERT(r == 0); - - ASSERT(buf[len - 1] != 0); - ASSERT(memcmp(buf, TEST_PIPENAME, len) == 0); - - len = sizeof buf; - r = uv_pipe_getpeername(&pipe_server, buf, &len); - ASSERT(r == UV_ENOTCONN); - - r = uv_listen((uv_stream_t*) &pipe_server, 0, pipe_server_connection_cb); - ASSERT(r == 0); - - r = uv_pipe_init(loop, &pipe_client, 0); - ASSERT(r == 0); - - len = sizeof buf; - r = uv_pipe_getsockname(&pipe_client, buf, &len); - ASSERT(r == UV_EBADF); - - len = sizeof buf; - r = uv_pipe_getpeername(&pipe_client, buf, &len); - ASSERT(r == UV_EBADF); - - uv_pipe_connect(&connect_req, &pipe_client, TEST_PIPENAME, pipe_client_connect_cb); - - len = sizeof buf; - r = uv_pipe_getsockname(&pipe_client, buf, &len); - ASSERT(r == 0 && len == 0); - - len = sizeof buf; - r = uv_pipe_getpeername(&pipe_client, buf, &len); - ASSERT(r == 0); - - ASSERT(buf[len - 1] != 0); - ASSERT(memcmp(buf, TEST_PIPENAME, len) == 0); - - r = uv_run(loop, UV_RUN_DEFAULT); - ASSERT(r == 0); - ASSERT(pipe_client_connect_cb_called == 1); - ASSERT(pipe_close_cb_called == 2); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(pipe_getsockname_abstract) { -#if defined(__linux__) - char buf[1024]; - size_t len; - int r; - int sock; - struct sockaddr_un sun; - socklen_t sun_len; - char abstract_pipe[] = "\0test-pipe"; - - sock = socket(AF_LOCAL, SOCK_STREAM, 0); - ASSERT(sock != -1); - - sun_len = sizeof sun; - memset(&sun, 0, sun_len); - sun.sun_family = AF_UNIX; - memcpy(sun.sun_path, abstract_pipe, sizeof abstract_pipe); - - r = bind(sock, (struct sockaddr*)&sun, sun_len); - ASSERT(r == 0); - - r = uv_pipe_init(uv_default_loop(), &pipe_server, 0); - ASSERT(r == 0); - r = uv_pipe_open(&pipe_server, sock); - ASSERT(r == 0); - - len = sizeof buf; - r = uv_pipe_getsockname(&pipe_server, buf, &len); - ASSERT(r == 0); - - ASSERT(memcmp(buf, abstract_pipe, sizeof abstract_pipe) == 0); - - uv_close((uv_handle_t*)&pipe_server, pipe_close_cb); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - close(sock); - - ASSERT(pipe_close_cb_called == 1); - MAKE_VALGRIND_HAPPY(); - return 0; -#else - MAKE_VALGRIND_HAPPY(); - return 0; -#endif -} - -TEST_IMPL(pipe_getsockname_blocking) { -#ifdef _WIN32 - HANDLE readh, writeh; - int readfd; - char buf1[1024], buf2[1024]; - size_t len1, len2; - int r; - - r = CreatePipe(&readh, &writeh, NULL, 65536); - ASSERT(r != 0); - - r = uv_pipe_init(uv_default_loop(), &pipe_client, 0); - ASSERT(r == 0); - readfd = _open_osfhandle((intptr_t)readh, _O_RDONLY); - ASSERT(r != -1); - r = uv_pipe_open(&pipe_client, readfd); - ASSERT(r == 0); - r = uv_read_start((uv_stream_t*)&pipe_client, NULL, NULL); - ASSERT(r == 0); - Sleep(100); - r = uv_read_stop((uv_stream_t*)&pipe_client); - ASSERT(r == 0); - - len1 = sizeof buf1; - r = uv_pipe_getsockname(&pipe_client, buf1, &len1); - ASSERT(r == 0); - ASSERT(buf1[len1 - 1] != 0); - - r = uv_read_start((uv_stream_t*)&pipe_client, NULL, NULL); - ASSERT(r == 0); - Sleep(100); - - len2 = sizeof buf2; - r = uv_pipe_getsockname(&pipe_client, buf2, &len2); - ASSERT(r == 0); - ASSERT(buf2[len2 - 1] != 0); - - r = uv_read_stop((uv_stream_t*)&pipe_client); - ASSERT(r == 0); - - ASSERT(len1 == len2); - ASSERT(memcmp(buf1, buf2, len1) == 0); - - pipe_close_cb_called = 0; - uv_close((uv_handle_t*)&pipe_client, pipe_close_cb); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(pipe_close_cb_called == 1); - - _close(readfd); - CloseHandle(writeh); -#endif - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-pipe-sendmsg.c b/libuv/test/test-pipe-sendmsg.c deleted file mode 100644 index f6d893b..0000000 --- a/libuv/test/test-pipe-sendmsg.c +++ /dev/null @@ -1,169 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - - -#ifndef _WIN32 - -#include -#include -#include -#include -#include -#include -#include - - -/* NOTE: size should be divisible by 2 */ -static uv_pipe_t incoming[4]; -static unsigned int incoming_count; -static unsigned int close_called; - - -static void set_nonblocking(uv_os_sock_t sock) { - int r; -#ifdef _WIN32 - unsigned long on = 1; - r = ioctlsocket(sock, FIONBIO, &on); - ASSERT(r == 0); -#else - int flags = fcntl(sock, F_GETFL, 0); - ASSERT(flags >= 0); - r = fcntl(sock, F_SETFL, flags | O_NONBLOCK); - ASSERT(r >= 0); -#endif -} - - - - -static void close_cb(uv_handle_t* handle) { - close_called++; -} - - -static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) { - static char base[1]; - - buf->base = base; - buf->len = sizeof(base); -} - - -static void read_cb(uv_stream_t* handle, - ssize_t nread, - const uv_buf_t* buf) { - uv_pipe_t* p; - uv_pipe_t* inc; - uv_handle_type pending; - unsigned int i; - - p = (uv_pipe_t*) handle; - ASSERT(nread >= 0); - - while (uv_pipe_pending_count(p) != 0) { - pending = uv_pipe_pending_type(p); - ASSERT(pending == UV_NAMED_PIPE); - - ASSERT(incoming_count < ARRAY_SIZE(incoming)); - inc = &incoming[incoming_count++]; - ASSERT(0 == uv_pipe_init(p->loop, inc, 0)); - ASSERT(0 == uv_accept(handle, (uv_stream_t*) inc)); - } - - if (incoming_count != ARRAY_SIZE(incoming)) - return; - - ASSERT(0 == uv_read_stop((uv_stream_t*) p)); - uv_close((uv_handle_t*) p, close_cb); - for (i = 0; i < ARRAY_SIZE(incoming); i++) - uv_close((uv_handle_t*) &incoming[i], close_cb); -} - - -TEST_IMPL(pipe_sendmsg) { - uv_pipe_t p; - int r; - int fds[2]; - int send_fds[ARRAY_SIZE(incoming)]; - struct msghdr msg; - char scratch[64]; - struct cmsghdr *cmsg; - unsigned int i; - uv_buf_t buf; - - ASSERT(0 == socketpair(AF_UNIX, SOCK_STREAM, 0, fds)); - for (i = 0; i < ARRAY_SIZE(send_fds); i += 2) - ASSERT(0 == socketpair(AF_UNIX, SOCK_STREAM, 0, send_fds + i)); - ASSERT(i == ARRAY_SIZE(send_fds)); - ASSERT(0 == uv_pipe_init(uv_default_loop(), &p, 1)); - ASSERT(0 == uv_pipe_open(&p, fds[1])); - - buf = uv_buf_init("X", 1); - memset(&msg, 0, sizeof(msg)); - msg.msg_iov = (struct iovec*) &buf; - msg.msg_iovlen = 1; - msg.msg_flags = 0; - - msg.msg_control = (void*) scratch; - msg.msg_controllen = CMSG_LEN(sizeof(send_fds)); - ASSERT(sizeof(scratch) >= msg.msg_controllen); - - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = msg.msg_controllen; - - /* silence aliasing warning */ - { - void* pv = CMSG_DATA(cmsg); - int* pi = pv; - for (i = 0; i < ARRAY_SIZE(send_fds); i++) - pi[i] = send_fds[i]; - } - - set_nonblocking(fds[1]); - ASSERT(0 == uv_read_start((uv_stream_t*) &p, alloc_cb, read_cb)); - - do - r = sendmsg(fds[0], &msg, 0); - while (r == -1 && errno == EINTR); - ASSERT(r == 1); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(ARRAY_SIZE(incoming) == incoming_count); - ASSERT(ARRAY_SIZE(incoming) + 1 == close_called); - close(fds[0]); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -#else /* !_WIN32 */ - -TEST_IMPL(pipe_sendmsg) { - MAKE_VALGRIND_HAPPY(); - return 0; -} - -#endif /* _WIN32 */ diff --git a/libuv/test/test-pipe-server-close.c b/libuv/test/test-pipe-server-close.c deleted file mode 100644 index 1dcdfff..0000000 --- a/libuv/test/test-pipe-server-close.c +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include - - -static uv_pipe_t pipe_client; -static uv_pipe_t pipe_server; -static uv_connect_t connect_req; - -static int pipe_close_cb_called = 0; -static int pipe_client_connect_cb_called = 0; - - -static void pipe_close_cb(uv_handle_t* handle) { - ASSERT(handle == (uv_handle_t*) &pipe_client || - handle == (uv_handle_t*) &pipe_server); - pipe_close_cb_called++; -} - - -static void pipe_client_connect_cb(uv_connect_t* req, int status) { - ASSERT(req == &connect_req); - ASSERT(status == 0); - - pipe_client_connect_cb_called++; - - uv_close((uv_handle_t*) &pipe_client, pipe_close_cb); - uv_close((uv_handle_t*) &pipe_server, pipe_close_cb); -} - - -static void pipe_server_connection_cb(uv_stream_t* handle, int status) { - /* This function *may* be called, depending on whether accept or the - * connection callback is called first. - */ - ASSERT(status == 0); -} - - -TEST_IMPL(pipe_server_close) { - uv_loop_t* loop; - int r; - - loop = uv_default_loop(); - ASSERT(loop != NULL); - - r = uv_pipe_init(loop, &pipe_server, 0); - ASSERT(r == 0); - - r = uv_pipe_bind(&pipe_server, TEST_PIPENAME); - ASSERT(r == 0); - - r = uv_listen((uv_stream_t*) &pipe_server, 0, pipe_server_connection_cb); - ASSERT(r == 0); - - r = uv_pipe_init(loop, &pipe_client, 0); - ASSERT(r == 0); - - uv_pipe_connect(&connect_req, &pipe_client, TEST_PIPENAME, pipe_client_connect_cb); - - r = uv_run(loop, UV_RUN_DEFAULT); - ASSERT(r == 0); - ASSERT(pipe_client_connect_cb_called == 1); - ASSERT(pipe_close_cb_called == 2); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-platform-output.c b/libuv/test/test-platform-output.c deleted file mode 100644 index dc6fa32..0000000 --- a/libuv/test/test-platform-output.c +++ /dev/null @@ -1,124 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" -#include - - -TEST_IMPL(platform_output) { - char buffer[512]; - size_t rss; - size_t size; - double uptime; - uv_rusage_t rusage; - uv_cpu_info_t* cpus; - uv_interface_address_t* interfaces; - int count; - int i; - int err; - - err = uv_get_process_title(buffer, sizeof(buffer)); - ASSERT(err == 0); - printf("uv_get_process_title: %s\n", buffer); - - size = sizeof(buffer); - err = uv_cwd(buffer, &size); - ASSERT(err == 0); - printf("uv_cwd: %s\n", buffer); - - err = uv_resident_set_memory(&rss); - ASSERT(err == 0); - printf("uv_resident_set_memory: %llu\n", (unsigned long long) rss); - - err = uv_uptime(&uptime); - ASSERT(err == 0); - ASSERT(uptime > 0); - printf("uv_uptime: %f\n", uptime); - - err = uv_getrusage(&rusage); - ASSERT(err == 0); - ASSERT(rusage.ru_utime.tv_sec >= 0); - ASSERT(rusage.ru_utime.tv_usec >= 0); - ASSERT(rusage.ru_stime.tv_sec >= 0); - ASSERT(rusage.ru_stime.tv_usec >= 0); - printf("uv_getrusage:\n"); - printf(" user: %llu sec %llu microsec\n", - (unsigned long long) rusage.ru_utime.tv_sec, - (unsigned long long) rusage.ru_utime.tv_usec); - printf(" system: %llu sec %llu microsec\n", - (unsigned long long) rusage.ru_stime.tv_sec, - (unsigned long long) rusage.ru_stime.tv_usec); - - err = uv_cpu_info(&cpus, &count); - ASSERT(err == 0); - - printf("uv_cpu_info:\n"); - for (i = 0; i < count; i++) { - printf(" model: %s\n", cpus[i].model); - printf(" speed: %d\n", cpus[i].speed); - printf(" times.sys: %llu\n", (unsigned long long) cpus[i].cpu_times.sys); - printf(" times.user: %llu\n", - (unsigned long long) cpus[i].cpu_times.user); - printf(" times.idle: %llu\n", - (unsigned long long) cpus[i].cpu_times.idle); - printf(" times.irq: %llu\n", (unsigned long long) cpus[i].cpu_times.irq); - printf(" times.nice: %llu\n", - (unsigned long long) cpus[i].cpu_times.nice); - } - uv_free_cpu_info(cpus, count); - - err = uv_interface_addresses(&interfaces, &count); - ASSERT(err == 0); - - printf("uv_interface_addresses:\n"); - for (i = 0; i < count; i++) { - printf(" name: %s\n", interfaces[i].name); - printf(" internal: %d\n", interfaces[i].is_internal); - printf(" physical address: "); - printf("%02x:%02x:%02x:%02x:%02x:%02x\n", - (unsigned char)interfaces[i].phys_addr[0], - (unsigned char)interfaces[i].phys_addr[1], - (unsigned char)interfaces[i].phys_addr[2], - (unsigned char)interfaces[i].phys_addr[3], - (unsigned char)interfaces[i].phys_addr[4], - (unsigned char)interfaces[i].phys_addr[5]); - - if (interfaces[i].address.address4.sin_family == AF_INET) { - uv_ip4_name(&interfaces[i].address.address4, buffer, sizeof(buffer)); - } else if (interfaces[i].address.address4.sin_family == AF_INET6) { - uv_ip6_name(&interfaces[i].address.address6, buffer, sizeof(buffer)); - } - - printf(" address: %s\n", buffer); - - if (interfaces[i].netmask.netmask4.sin_family == AF_INET) { - uv_ip4_name(&interfaces[i].netmask.netmask4, buffer, sizeof(buffer)); - } else if (interfaces[i].netmask.netmask4.sin_family == AF_INET6) { - uv_ip6_name(&interfaces[i].netmask.netmask6, buffer, sizeof(buffer)); - } - - printf(" netmask: %s\n", buffer); - } - uv_free_interface_addresses(interfaces, count); - - return 0; -} diff --git a/libuv/test/test-poll-close-doesnt-corrupt-stack.c b/libuv/test/test-poll-close-doesnt-corrupt-stack.c deleted file mode 100644 index fc2cc00..0000000 --- a/libuv/test/test-poll-close-doesnt-corrupt-stack.c +++ /dev/null @@ -1,114 +0,0 @@ -/* Copyright Bert Belder, and other libuv contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifdef _WIN32 - -#include -#include - -#include "uv.h" -#include "task.h" - -#ifdef _MSC_VER /* msvc */ -# define NO_INLINE __declspec(noinline) -#else /* gcc */ -# define NO_INLINE __attribute__ ((noinline)) -#endif - - -uv_os_sock_t sock; -uv_poll_t handle; - -static int close_cb_called = 0; - - -static void close_cb(uv_handle_t* h) { - close_cb_called++; -} - - -static void poll_cb(uv_poll_t* h, int status, int events) { - ASSERT(0 && "should never get here"); -} - - -static void NO_INLINE close_socket_and_verify_stack() { - const uint32_t MARKER = 0xDEADBEEF; - const int VERIFY_AFTER = 10; /* ms */ - int r; - - volatile uint32_t data[65536]; - size_t i; - - for (i = 0; i < ARRAY_SIZE(data); i++) - data[i] = MARKER; - - r = closesocket(sock); - ASSERT(r == 0); - - uv_sleep(VERIFY_AFTER); - - for (i = 0; i < ARRAY_SIZE(data); i++) - ASSERT(data[i] == MARKER); -} - - -TEST_IMPL(poll_close_doesnt_corrupt_stack) { - struct WSAData wsa_data; - int r; - unsigned long on; - struct sockaddr_in addr; - - r = WSAStartup(MAKEWORD(2, 2), &wsa_data); - ASSERT(r == 0); - - sock = socket(AF_INET, SOCK_STREAM, 0); - ASSERT(sock != INVALID_SOCKET); - on = 1; - r = ioctlsocket(sock, FIONBIO, &on); - ASSERT(r == 0); - - r = uv_ip4_addr("127.0.0.1", TEST_PORT, &addr); - ASSERT(r == 0); - - r = connect(sock, (const struct sockaddr*) &addr, sizeof addr); - ASSERT(r != 0); - ASSERT(WSAGetLastError() == WSAEWOULDBLOCK); - - r = uv_poll_init_socket(uv_default_loop(), &handle, sock); - ASSERT(r == 0); - r = uv_poll_start(&handle, UV_READABLE | UV_WRITABLE, poll_cb); - ASSERT(r == 0); - - uv_close((uv_handle_t*) &handle, close_cb); - - close_socket_and_verify_stack(); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -#endif /* _WIN32 */ diff --git a/libuv/test/test-poll-close.c b/libuv/test/test-poll-close.c deleted file mode 100644 index 2eccddf..0000000 --- a/libuv/test/test-poll-close.c +++ /dev/null @@ -1,73 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include - -#ifndef _WIN32 -# include -# include -# include -#endif - -#include "uv.h" -#include "task.h" - -#define NUM_SOCKETS 64 - - -static int close_cb_called = 0; - - -static void close_cb(uv_handle_t* handle) { - close_cb_called++; -} - - -TEST_IMPL(poll_close) { - uv_os_sock_t sockets[NUM_SOCKETS]; - uv_poll_t poll_handles[NUM_SOCKETS]; - int i; - -#ifdef _WIN32 - { - struct WSAData wsa_data; - int r = WSAStartup(MAKEWORD(2, 2), &wsa_data); - ASSERT(r == 0); - } -#endif - - for (i = 0; i < NUM_SOCKETS; i++) { - sockets[i] = socket(AF_INET, SOCK_STREAM, 0); - uv_poll_init_socket(uv_default_loop(), &poll_handles[i], sockets[i]); - uv_poll_start(&poll_handles[i], UV_READABLE | UV_WRITABLE, NULL); - } - - for (i = 0; i < NUM_SOCKETS; i++) { - uv_close((uv_handle_t*) &poll_handles[i], close_cb); - } - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(close_cb_called == NUM_SOCKETS); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-poll-closesocket.c b/libuv/test/test-poll-closesocket.c deleted file mode 100644 index 4db74a0..0000000 --- a/libuv/test/test-poll-closesocket.c +++ /dev/null @@ -1,89 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifdef _WIN32 - -#include - -#include "uv.h" -#include "task.h" - -uv_os_sock_t sock; -uv_poll_t handle; - -static int close_cb_called = 0; - - -static void close_cb(uv_handle_t* h) { - close_cb_called++; -} - - -static void poll_cb(uv_poll_t* h, int status, int events) { - int r; - - ASSERT(status == 0); - ASSERT(h == &handle); - - r = uv_poll_start(&handle, UV_READABLE, poll_cb); - ASSERT(r == 0); - - closesocket(sock); - uv_close((uv_handle_t*) &handle, close_cb); - -} - - -TEST_IMPL(poll_closesocket) { - struct WSAData wsa_data; - int r; - unsigned long on; - struct sockaddr_in addr; - - r = WSAStartup(MAKEWORD(2, 2), &wsa_data); - ASSERT(r == 0); - - sock = socket(AF_INET, SOCK_STREAM, 0); - ASSERT(sock != INVALID_SOCKET); - on = 1; - r = ioctlsocket(sock, FIONBIO, &on); - ASSERT(r == 0); - - r = uv_ip4_addr("127.0.0.1", TEST_PORT, &addr); - ASSERT(r == 0); - - r = connect(sock, (const struct sockaddr*) &addr, sizeof addr); - ASSERT(r != 0); - ASSERT(WSAGetLastError() == WSAEWOULDBLOCK); - - r = uv_poll_init_socket(uv_default_loop(), &handle, sock); - ASSERT(r == 0); - r = uv_poll_start(&handle, UV_WRITABLE, poll_cb); - ASSERT(r == 0); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} -#endif diff --git a/libuv/test/test-poll.c b/libuv/test/test-poll.c deleted file mode 100644 index be8b00c..0000000 --- a/libuv/test/test-poll.c +++ /dev/null @@ -1,560 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include - -#ifndef _WIN32 -# include -# include -#endif - -#include "uv.h" -#include "task.h" - - -#define NUM_CLIENTS 5 -#define TRANSFER_BYTES (1 << 16) - -#undef MIN -#define MIN(a, b) (((a) < (b)) ? (a) : (b)); - - -typedef enum { - UNIDIRECTIONAL, - DUPLEX -} test_mode_t; - -typedef struct connection_context_s { - uv_poll_t poll_handle; - uv_timer_t timer_handle; - uv_os_sock_t sock; - size_t read, sent; - int is_server_connection; - int open_handles; - int got_fin, sent_fin; - unsigned int events, delayed_events; -} connection_context_t; - -typedef struct server_context_s { - uv_poll_t poll_handle; - uv_os_sock_t sock; - int connections; -} server_context_t; - - -static void delay_timer_cb(uv_timer_t* timer); - - -static test_mode_t test_mode = DUPLEX; - -static int closed_connections = 0; - -static int valid_writable_wakeups = 0; -static int spurious_writable_wakeups = 0; - - -static int got_eagain(void) { -#ifdef _WIN32 - return WSAGetLastError() == WSAEWOULDBLOCK; -#else - return errno == EAGAIN - || errno == EINPROGRESS -#ifdef EWOULDBLOCK - || errno == EWOULDBLOCK; -#endif - ; -#endif -} - - -static uv_os_sock_t create_bound_socket (struct sockaddr_in bind_addr) { - uv_os_sock_t sock; - int r; - - sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); -#ifdef _WIN32 - ASSERT(sock != INVALID_SOCKET); -#else - ASSERT(sock >= 0); -#endif - -#ifndef _WIN32 - { - /* Allow reuse of the port. */ - int yes = 1; - r = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes); - ASSERT(r == 0); - } -#endif - - r = bind(sock, (const struct sockaddr*) &bind_addr, sizeof bind_addr); - ASSERT(r == 0); - - return sock; -} - - -static void close_socket(uv_os_sock_t sock) { - int r; -#ifdef _WIN32 - r = closesocket(sock); -#else - r = close(sock); -#endif - ASSERT(r == 0); -} - - -static connection_context_t* create_connection_context( - uv_os_sock_t sock, int is_server_connection) { - int r; - connection_context_t* context; - - context = (connection_context_t*) malloc(sizeof *context); - ASSERT(context != NULL); - - context->sock = sock; - context->is_server_connection = is_server_connection; - context->read = 0; - context->sent = 0; - context->open_handles = 0; - context->events = 0; - context->delayed_events = 0; - context->got_fin = 0; - context->sent_fin = 0; - - r = uv_poll_init_socket(uv_default_loop(), &context->poll_handle, sock); - context->open_handles++; - context->poll_handle.data = context; - ASSERT(r == 0); - - r = uv_timer_init(uv_default_loop(), &context->timer_handle); - context->open_handles++; - context->timer_handle.data = context; - ASSERT(r == 0); - - return context; -} - - -static void connection_close_cb(uv_handle_t* handle) { - connection_context_t* context = (connection_context_t*) handle->data; - - if (--context->open_handles == 0) { - if (test_mode == DUPLEX || context->is_server_connection) { - ASSERT(context->read == TRANSFER_BYTES); - } else { - ASSERT(context->read == 0); - } - - if (test_mode == DUPLEX || !context->is_server_connection) { - ASSERT(context->sent == TRANSFER_BYTES); - } else { - ASSERT(context->sent == 0); - } - - closed_connections++; - - free(context); - } -} - - -static void destroy_connection_context(connection_context_t* context) { - uv_close((uv_handle_t*) &context->poll_handle, connection_close_cb); - uv_close((uv_handle_t*) &context->timer_handle, connection_close_cb); -} - - -static void connection_poll_cb(uv_poll_t* handle, int status, int events) { - connection_context_t* context = (connection_context_t*) handle->data; - unsigned int new_events; - int r; - - ASSERT(status == 0); - ASSERT(events & context->events); - ASSERT(!(events & ~context->events)); - - new_events = context->events; - - if (events & UV_READABLE) { - int action = rand() % 7; - - switch (action) { - case 0: - case 1: { - /* Read a couple of bytes. */ - static char buffer[74]; - r = recv(context->sock, buffer, sizeof buffer, 0); - ASSERT(r >= 0); - - if (r > 0) { - context->read += r; - } else { - /* Got FIN. */ - context->got_fin = 1; - new_events &= ~UV_READABLE; - } - - break; - } - - case 2: - case 3: { - /* Read until EAGAIN. */ - static char buffer[931]; - r = recv(context->sock, buffer, sizeof buffer, 0); - ASSERT(r >= 0); - - while (r > 0) { - context->read += r; - r = recv(context->sock, buffer, sizeof buffer, 0); - } - - if (r == 0) { - /* Got FIN. */ - context->got_fin = 1; - new_events &= ~UV_READABLE; - } else { - ASSERT(got_eagain()); - } - - break; - } - - case 4: - /* Ignore. */ - break; - - case 5: - /* Stop reading for a while. Restart in timer callback. */ - new_events &= ~UV_READABLE; - if (!uv_is_active((uv_handle_t*) &context->timer_handle)) { - context->delayed_events = UV_READABLE; - uv_timer_start(&context->timer_handle, delay_timer_cb, 10, 0); - } else { - context->delayed_events |= UV_READABLE; - } - break; - - case 6: - /* Fudge with the event mask. */ - uv_poll_start(&context->poll_handle, UV_WRITABLE, connection_poll_cb); - uv_poll_start(&context->poll_handle, UV_READABLE, connection_poll_cb); - context->events = UV_READABLE; - break; - - default: - ASSERT(0); - } - } - - if (events & UV_WRITABLE) { - if (context->sent < TRANSFER_BYTES && - !(test_mode == UNIDIRECTIONAL && context->is_server_connection)) { - /* We have to send more bytes. */ - int action = rand() % 7; - - switch (action) { - case 0: - case 1: { - /* Send a couple of bytes. */ - static char buffer[103]; - - int send_bytes = MIN(TRANSFER_BYTES - context->sent, sizeof buffer); - ASSERT(send_bytes > 0); - - r = send(context->sock, buffer, send_bytes, 0); - - if (r < 0) { - ASSERT(got_eagain()); - spurious_writable_wakeups++; - break; - } - - ASSERT(r > 0); - context->sent += r; - valid_writable_wakeups++; - break; - } - - case 2: - case 3: { - /* Send until EAGAIN. */ - static char buffer[1234]; - - int send_bytes = MIN(TRANSFER_BYTES - context->sent, sizeof buffer); - ASSERT(send_bytes > 0); - - r = send(context->sock, buffer, send_bytes, 0); - - if (r < 0) { - ASSERT(got_eagain()); - spurious_writable_wakeups++; - break; - } - - ASSERT(r > 0); - valid_writable_wakeups++; - context->sent += r; - - while (context->sent < TRANSFER_BYTES) { - send_bytes = MIN(TRANSFER_BYTES - context->sent, sizeof buffer); - ASSERT(send_bytes > 0); - - r = send(context->sock, buffer, send_bytes, 0); - - if (r <= 0) break; - context->sent += r; - } - ASSERT(r > 0 || got_eagain()); - break; - } - - case 4: - /* Ignore. */ - break; - - case 5: - /* Stop sending for a while. Restart in timer callback. */ - new_events &= ~UV_WRITABLE; - if (!uv_is_active((uv_handle_t*) &context->timer_handle)) { - context->delayed_events = UV_WRITABLE; - uv_timer_start(&context->timer_handle, delay_timer_cb, 100, 0); - } else { - context->delayed_events |= UV_WRITABLE; - } - break; - - case 6: - /* Fudge with the event mask. */ - uv_poll_start(&context->poll_handle, - UV_READABLE, - connection_poll_cb); - uv_poll_start(&context->poll_handle, - UV_WRITABLE, - connection_poll_cb); - context->events = UV_WRITABLE; - break; - - default: - ASSERT(0); - } - - } else { - /* Nothing more to write. Send FIN. */ - int r; -#ifdef _WIN32 - r = shutdown(context->sock, SD_SEND); -#else - r = shutdown(context->sock, SHUT_WR); -#endif - ASSERT(r == 0); - context->sent_fin = 1; - new_events &= ~UV_WRITABLE; - } - } - - if (context->got_fin && context->sent_fin) { - /* Sent and received FIN. Close and destroy context. */ - close_socket(context->sock); - destroy_connection_context(context); - context->events = 0; - - } else if (new_events != context->events) { - /* Poll mask changed. Call uv_poll_start again. */ - context->events = new_events; - uv_poll_start(handle, new_events, connection_poll_cb); - } - - /* Assert that uv_is_active works correctly for poll handles. */ - if (context->events != 0) { - ASSERT(1 == uv_is_active((uv_handle_t*) handle)); - } else { - ASSERT(0 == uv_is_active((uv_handle_t*) handle)); - } -} - - -static void delay_timer_cb(uv_timer_t* timer) { - connection_context_t* context = (connection_context_t*) timer->data; - int r; - - /* Timer should auto stop. */ - ASSERT(0 == uv_is_active((uv_handle_t*) timer)); - - /* Add the requested events to the poll mask. */ - ASSERT(context->delayed_events != 0); - context->events |= context->delayed_events; - context->delayed_events = 0; - - r = uv_poll_start(&context->poll_handle, - context->events, - connection_poll_cb); - ASSERT(r == 0); -} - - -static server_context_t* create_server_context( - uv_os_sock_t sock) { - int r; - server_context_t* context; - - context = (server_context_t*) malloc(sizeof *context); - ASSERT(context != NULL); - - context->sock = sock; - context->connections = 0; - - r = uv_poll_init_socket(uv_default_loop(), &context->poll_handle, sock); - context->poll_handle.data = context; - ASSERT(r == 0); - - return context; -} - - -static void server_close_cb(uv_handle_t* handle) { - server_context_t* context = (server_context_t*) handle->data; - free(context); -} - - -static void destroy_server_context(server_context_t* context) { - uv_close((uv_handle_t*) &context->poll_handle, server_close_cb); -} - - -static void server_poll_cb(uv_poll_t* handle, int status, int events) { - server_context_t* server_context = (server_context_t*) - handle->data; - connection_context_t* connection_context; - struct sockaddr_in addr; - socklen_t addr_len; - uv_os_sock_t sock; - int r; - - addr_len = sizeof addr; - sock = accept(server_context->sock, (struct sockaddr*) &addr, &addr_len); -#ifdef _WIN32 - ASSERT(sock != INVALID_SOCKET); -#else - ASSERT(sock >= 0); -#endif - - connection_context = create_connection_context(sock, 1); - connection_context->events = UV_READABLE | UV_WRITABLE; - r = uv_poll_start(&connection_context->poll_handle, - UV_READABLE | UV_WRITABLE, - connection_poll_cb); - ASSERT(r == 0); - - if (++server_context->connections == NUM_CLIENTS) { - close_socket(server_context->sock); - destroy_server_context(server_context); - } -} - - -static void start_server(void) { - server_context_t* context; - struct sockaddr_in addr; - uv_os_sock_t sock; - int r; - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - sock = create_bound_socket(addr); - context = create_server_context(sock); - - r = listen(sock, 100); - ASSERT(r == 0); - - r = uv_poll_start(&context->poll_handle, UV_READABLE, server_poll_cb); - ASSERT(r == 0); -} - - -static void start_client(void) { - uv_os_sock_t sock; - connection_context_t* context; - struct sockaddr_in server_addr; - struct sockaddr_in addr; - int r; - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &server_addr)); - ASSERT(0 == uv_ip4_addr("0.0.0.0", 0, &addr)); - - sock = create_bound_socket(addr); - context = create_connection_context(sock, 0); - - context->events = UV_READABLE | UV_WRITABLE; - r = uv_poll_start(&context->poll_handle, - UV_READABLE | UV_WRITABLE, - connection_poll_cb); - ASSERT(r == 0); - - r = connect(sock, (struct sockaddr*) &server_addr, sizeof server_addr); - ASSERT(r == 0 || got_eagain()); -} - - -static void start_poll_test(void) { - int i, r; - -#ifdef _WIN32 - { - struct WSAData wsa_data; - int r = WSAStartup(MAKEWORD(2, 2), &wsa_data); - ASSERT(r == 0); - } -#endif - - start_server(); - - for (i = 0; i < NUM_CLIENTS; i++) - start_client(); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - /* Assert that at most five percent of the writable wakeups was spurious. */ - ASSERT(spurious_writable_wakeups == 0 || - (valid_writable_wakeups + spurious_writable_wakeups) / - spurious_writable_wakeups > 20); - - ASSERT(closed_connections == NUM_CLIENTS * 2); - - MAKE_VALGRIND_HAPPY(); -} - - -TEST_IMPL(poll_duplex) { - test_mode = DUPLEX; - start_poll_test(); - return 0; -} - - -TEST_IMPL(poll_unidirectional) { - test_mode = UNIDIRECTIONAL; - start_poll_test(); - return 0; -} diff --git a/libuv/test/test-process-title.c b/libuv/test/test-process-title.c deleted file mode 100644 index 29be207..0000000 --- a/libuv/test/test-process-title.c +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" -#include - - -static void set_title(const char* title) { - char buffer[512]; - int err; - - err = uv_get_process_title(buffer, sizeof(buffer)); - ASSERT(err == 0); - - err = uv_set_process_title(title); - ASSERT(err == 0); - - err = uv_get_process_title(buffer, sizeof(buffer)); - ASSERT(err == 0); - - ASSERT(strcmp(buffer, title) == 0); -} - - -TEST_IMPL(process_title) { -#if defined(__sun) - RETURN_SKIP("uv_(get|set)_process_title is not implemented."); -#else - /* Check for format string vulnerabilities. */ - set_title("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"); - set_title("new title"); - return 0; -#endif -} diff --git a/libuv/test/test-ref.c b/libuv/test/test-ref.c deleted file mode 100644 index ddaa173..0000000 --- a/libuv/test/test-ref.c +++ /dev/null @@ -1,442 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include - - -static uv_write_t write_req; -static uv_shutdown_t shutdown_req; -static uv_connect_t connect_req; - -static char buffer[32767]; - -static int req_cb_called; -static int connect_cb_called; -static int write_cb_called; -static int shutdown_cb_called; -static int close_cb_called; - - -static void close_cb(uv_handle_t* handle) { - close_cb_called++; -} - - -static void do_close(void* handle) { - close_cb_called = 0; - uv_close((uv_handle_t*)handle, close_cb); - ASSERT(close_cb_called == 0); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(close_cb_called == 1); -} - - -static void fail_cb(void) { - FATAL("fail_cb should not have been called"); -} - - -static void fail_cb2(void) { - ASSERT(0 && "fail_cb2 should not have been called"); -} - - -static void req_cb(uv_handle_t* req, int status) { - req_cb_called++; -} - - -static void shutdown_cb(uv_shutdown_t* req, int status) { - ASSERT(req == &shutdown_req); - shutdown_cb_called++; -} - - -static void write_cb(uv_write_t* req, int status) { - ASSERT(req == &write_req); - uv_shutdown(&shutdown_req, req->handle, shutdown_cb); - write_cb_called++; -} - - -static void connect_and_write(uv_connect_t* req, int status) { - uv_buf_t buf = uv_buf_init(buffer, sizeof buffer); - ASSERT(req == &connect_req); - ASSERT(status == 0); - uv_write(&write_req, req->handle, &buf, 1, write_cb); - connect_cb_called++; -} - - - -static void connect_and_shutdown(uv_connect_t* req, int status) { - ASSERT(req == &connect_req); - ASSERT(status == 0); - uv_shutdown(&shutdown_req, req->handle, shutdown_cb); - connect_cb_called++; -} - - -TEST_IMPL(ref) { - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(idle_ref) { - uv_idle_t h; - uv_idle_init(uv_default_loop(), &h); - uv_idle_start(&h, (uv_idle_cb) fail_cb2); - uv_unref((uv_handle_t*)&h); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - do_close(&h); - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(async_ref) { - uv_async_t h; - uv_async_init(uv_default_loop(), &h, NULL); - uv_unref((uv_handle_t*)&h); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - do_close(&h); - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(prepare_ref) { - uv_prepare_t h; - uv_prepare_init(uv_default_loop(), &h); - uv_prepare_start(&h, (uv_prepare_cb) fail_cb2); - uv_unref((uv_handle_t*)&h); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - do_close(&h); - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(check_ref) { - uv_check_t h; - uv_check_init(uv_default_loop(), &h); - uv_check_start(&h, (uv_check_cb) fail_cb2); - uv_unref((uv_handle_t*)&h); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - do_close(&h); - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -static void prepare_cb(uv_prepare_t* h) { - ASSERT(h != NULL); - uv_unref((uv_handle_t*)h); -} - - -TEST_IMPL(unref_in_prepare_cb) { - uv_prepare_t h; - uv_prepare_init(uv_default_loop(), &h); - uv_prepare_start(&h, prepare_cb); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - do_close(&h); - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(timer_ref) { - uv_timer_t h; - uv_timer_init(uv_default_loop(), &h); - uv_unref((uv_handle_t*)&h); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - do_close(&h); - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(timer_ref2) { - uv_timer_t h; - uv_timer_init(uv_default_loop(), &h); - uv_timer_start(&h, (uv_timer_cb)fail_cb, 42, 42); - uv_unref((uv_handle_t*)&h); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - do_close(&h); - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(fs_event_ref) { - uv_fs_event_t h; - uv_fs_event_init(uv_default_loop(), &h); - uv_fs_event_start(&h, (uv_fs_event_cb)fail_cb, ".", 0); - uv_unref((uv_handle_t*)&h); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - do_close(&h); - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(fs_poll_ref) { - uv_fs_poll_t h; - uv_fs_poll_init(uv_default_loop(), &h); - uv_fs_poll_start(&h, NULL, ".", 999); - uv_unref((uv_handle_t*)&h); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - do_close(&h); - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(tcp_ref) { - uv_tcp_t h; - uv_tcp_init(uv_default_loop(), &h); - uv_unref((uv_handle_t*)&h); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - do_close(&h); - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(tcp_ref2) { - uv_tcp_t h; - uv_tcp_init(uv_default_loop(), &h); - uv_listen((uv_stream_t*)&h, 128, (uv_connection_cb)fail_cb); - uv_unref((uv_handle_t*)&h); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - do_close(&h); - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(tcp_ref2b) { - uv_tcp_t h; - uv_tcp_init(uv_default_loop(), &h); - uv_listen((uv_stream_t*)&h, 128, (uv_connection_cb)fail_cb); - uv_unref((uv_handle_t*)&h); - uv_close((uv_handle_t*)&h, close_cb); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(close_cb_called == 1); - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(tcp_ref3) { - struct sockaddr_in addr; - uv_tcp_t h; - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - uv_tcp_init(uv_default_loop(), &h); - uv_tcp_connect(&connect_req, - &h, - (const struct sockaddr*) &addr, - connect_and_shutdown); - uv_unref((uv_handle_t*)&h); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(connect_cb_called == 1); - ASSERT(shutdown_cb_called == 1); - do_close(&h); - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(tcp_ref4) { - struct sockaddr_in addr; - uv_tcp_t h; - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - uv_tcp_init(uv_default_loop(), &h); - uv_tcp_connect(&connect_req, - &h, - (const struct sockaddr*) &addr, - connect_and_write); - uv_unref((uv_handle_t*)&h); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(connect_cb_called == 1); - ASSERT(write_cb_called == 1); - ASSERT(shutdown_cb_called == 1); - do_close(&h); - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(udp_ref) { - uv_udp_t h; - uv_udp_init(uv_default_loop(), &h); - uv_unref((uv_handle_t*)&h); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - do_close(&h); - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(udp_ref2) { - struct sockaddr_in addr; - uv_udp_t h; - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - uv_udp_init(uv_default_loop(), &h); - uv_udp_bind(&h, (const struct sockaddr*) &addr, 0); - uv_udp_recv_start(&h, (uv_alloc_cb)fail_cb, (uv_udp_recv_cb)fail_cb); - uv_unref((uv_handle_t*)&h); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - do_close(&h); - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(udp_ref3) { - struct sockaddr_in addr; - uv_buf_t buf = uv_buf_init("PING", 4); - uv_udp_send_t req; - uv_udp_t h; - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - uv_udp_init(uv_default_loop(), &h); - uv_udp_send(&req, - &h, - &buf, - 1, - (const struct sockaddr*) &addr, - (uv_udp_send_cb) req_cb); - uv_unref((uv_handle_t*)&h); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(req_cb_called == 1); - do_close(&h); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(pipe_ref) { - uv_pipe_t h; - uv_pipe_init(uv_default_loop(), &h, 0); - uv_unref((uv_handle_t*)&h); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - do_close(&h); - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(pipe_ref2) { - uv_pipe_t h; - uv_pipe_init(uv_default_loop(), &h, 0); - uv_listen((uv_stream_t*)&h, 128, (uv_connection_cb)fail_cb); - uv_unref((uv_handle_t*)&h); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - do_close(&h); - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(pipe_ref3) { - uv_pipe_t h; - uv_pipe_init(uv_default_loop(), &h, 0); - uv_pipe_connect(&connect_req, &h, TEST_PIPENAME, connect_and_shutdown); - uv_unref((uv_handle_t*)&h); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(connect_cb_called == 1); - ASSERT(shutdown_cb_called == 1); - do_close(&h); - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(pipe_ref4) { - uv_pipe_t h; - uv_pipe_init(uv_default_loop(), &h, 0); - uv_pipe_connect(&connect_req, &h, TEST_PIPENAME, connect_and_write); - uv_unref((uv_handle_t*)&h); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(connect_cb_called == 1); - ASSERT(write_cb_called == 1); - ASSERT(shutdown_cb_called == 1); - do_close(&h); - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(process_ref) { - /* spawn_helper4 blocks indefinitely. */ - char *argv[] = { NULL, "spawn_helper4", NULL }; - uv_process_options_t options; - size_t exepath_size; - char exepath[256]; - uv_process_t h; - int r; - - memset(&options, 0, sizeof(options)); - exepath_size = sizeof(exepath); - - r = uv_exepath(exepath, &exepath_size); - ASSERT(r == 0); - - argv[0] = exepath; - options.file = exepath; - options.args = argv; - options.exit_cb = NULL; - - r = uv_spawn(uv_default_loop(), &h, &options); - ASSERT(r == 0); - - uv_unref((uv_handle_t*)&h); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - r = uv_process_kill(&h, /* SIGTERM */ 15); - ASSERT(r == 0); - - do_close(&h); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(has_ref) { - uv_idle_t h; - uv_idle_init(uv_default_loop(), &h); - uv_ref((uv_handle_t*)&h); - ASSERT(uv_has_ref((uv_handle_t*)&h) == 1); - uv_unref((uv_handle_t*)&h); - ASSERT(uv_has_ref((uv_handle_t*)&h) == 0); - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-run-nowait.c b/libuv/test/test-run-nowait.c deleted file mode 100644 index 43524f6..0000000 --- a/libuv/test/test-run-nowait.c +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -static uv_timer_t timer_handle; -static int timer_called = 0; - - -static void timer_cb(uv_timer_t* handle) { - ASSERT(handle == &timer_handle); - timer_called = 1; -} - - -TEST_IMPL(run_nowait) { - int r; - uv_timer_init(uv_default_loop(), &timer_handle); - uv_timer_start(&timer_handle, timer_cb, 100, 100); - - r = uv_run(uv_default_loop(), UV_RUN_NOWAIT); - ASSERT(r != 0); - ASSERT(timer_called == 0); - - return 0; -} diff --git a/libuv/test/test-run-once.c b/libuv/test/test-run-once.c deleted file mode 100644 index 10cbf95..0000000 --- a/libuv/test/test-run-once.c +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#define NUM_TICKS 64 - -static uv_idle_t idle_handle; -static int idle_counter; - - -static void idle_cb(uv_idle_t* handle) { - ASSERT(handle == &idle_handle); - - if (++idle_counter == NUM_TICKS) - uv_idle_stop(handle); -} - - -TEST_IMPL(run_once) { - uv_idle_init(uv_default_loop(), &idle_handle); - uv_idle_start(&idle_handle, idle_cb); - - while (uv_run(uv_default_loop(), UV_RUN_ONCE)); - ASSERT(idle_counter == NUM_TICKS); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-semaphore.c b/libuv/test/test-semaphore.c deleted file mode 100644 index ac03bb0..0000000 --- a/libuv/test/test-semaphore.c +++ /dev/null @@ -1,111 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include - -typedef struct { - uv_mutex_t mutex; - uv_sem_t sem; - int delay; - volatile int posted; -} worker_config; - - -static void worker(void* arg) { - worker_config* c = arg; - - if (c->delay) - uv_sleep(c->delay); - - uv_mutex_lock(&c->mutex); - ASSERT(c->posted == 0); - uv_sem_post(&c->sem); - c->posted = 1; - uv_mutex_unlock(&c->mutex); -} - - -TEST_IMPL(semaphore_1) { - uv_thread_t thread; - worker_config wc; - - memset(&wc, 0, sizeof(wc)); - - ASSERT(0 == uv_sem_init(&wc.sem, 0)); - ASSERT(0 == uv_mutex_init(&wc.mutex)); - ASSERT(0 == uv_thread_create(&thread, worker, &wc)); - - uv_sleep(100); - uv_mutex_lock(&wc.mutex); - ASSERT(wc.posted == 1); - uv_sem_wait(&wc.sem); /* should not block */ - uv_mutex_unlock(&wc.mutex); /* ergo, it should be ok to unlock after wait */ - - ASSERT(0 == uv_thread_join(&thread)); - uv_mutex_destroy(&wc.mutex); - uv_sem_destroy(&wc.sem); - - return 0; -} - - -TEST_IMPL(semaphore_2) { - uv_thread_t thread; - worker_config wc; - - memset(&wc, 0, sizeof(wc)); - wc.delay = 100; - - ASSERT(0 == uv_sem_init(&wc.sem, 0)); - ASSERT(0 == uv_mutex_init(&wc.mutex)); - ASSERT(0 == uv_thread_create(&thread, worker, &wc)); - - uv_sem_wait(&wc.sem); - - ASSERT(0 == uv_thread_join(&thread)); - uv_mutex_destroy(&wc.mutex); - uv_sem_destroy(&wc.sem); - - return 0; -} - - -TEST_IMPL(semaphore_3) { - uv_sem_t sem; - - ASSERT(0 == uv_sem_init(&sem, 3)); - uv_sem_wait(&sem); /* should not block */ - uv_sem_wait(&sem); /* should not block */ - ASSERT(0 == uv_sem_trywait(&sem)); - ASSERT(UV_EAGAIN == uv_sem_trywait(&sem)); - - uv_sem_post(&sem); - ASSERT(0 == uv_sem_trywait(&sem)); - ASSERT(UV_EAGAIN == uv_sem_trywait(&sem)); - - uv_sem_destroy(&sem); - - return 0; -} diff --git a/libuv/test/test-shutdown-close.c b/libuv/test/test-shutdown-close.c deleted file mode 100644 index 78c369b..0000000 --- a/libuv/test/test-shutdown-close.c +++ /dev/null @@ -1,108 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* - * These tests verify that the uv_shutdown callback is always made, even when - * it is immediately followed by an uv_close call. - */ - -#include "uv.h" -#include "task.h" - - -static uv_shutdown_t shutdown_req; -static uv_connect_t connect_req; - -static int connect_cb_called = 0; -static int shutdown_cb_called = 0; -static int close_cb_called = 0; - - -static void shutdown_cb(uv_shutdown_t* req, int status) { - ASSERT(req == &shutdown_req); - ASSERT(status == 0 || status == UV_ECANCELED); - shutdown_cb_called++; -} - - -static void close_cb(uv_handle_t* handle) { - close_cb_called++; -} - - -static void connect_cb(uv_connect_t* req, int status) { - int r; - - ASSERT(req == &connect_req); - ASSERT(status == 0); - - r = uv_shutdown(&shutdown_req, req->handle, shutdown_cb); - ASSERT(r == 0); - ASSERT(0 == uv_is_closing((uv_handle_t*) req->handle)); - uv_close((uv_handle_t*) req->handle, close_cb); - ASSERT(1 == uv_is_closing((uv_handle_t*) req->handle)); - - connect_cb_called++; -} - - -TEST_IMPL(shutdown_close_tcp) { - struct sockaddr_in addr; - uv_tcp_t h; - int r; - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - r = uv_tcp_init(uv_default_loop(), &h); - ASSERT(r == 0); - r = uv_tcp_connect(&connect_req, - &h, - (const struct sockaddr*) &addr, - connect_cb); - ASSERT(r == 0); - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(connect_cb_called == 1); - ASSERT(shutdown_cb_called == 1); - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(shutdown_close_pipe) { - uv_pipe_t h; - int r; - - r = uv_pipe_init(uv_default_loop(), &h, 0); - ASSERT(r == 0); - uv_pipe_connect(&connect_req, &h, TEST_PIPENAME, connect_cb); - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(connect_cb_called == 1); - ASSERT(shutdown_cb_called == 1); - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-shutdown-eof.c b/libuv/test/test-shutdown-eof.c deleted file mode 100644 index 9f95e75..0000000 --- a/libuv/test/test-shutdown-eof.c +++ /dev/null @@ -1,182 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" -#include -#include - -static uv_timer_t timer; -static uv_tcp_t tcp; -static uv_connect_t connect_req; -static uv_write_t write_req; -static uv_shutdown_t shutdown_req; -static uv_buf_t qbuf; -static int got_q; -static int got_eof; -static int called_connect_cb; -static int called_shutdown_cb; -static int called_tcp_close_cb; -static int called_timer_close_cb; -static int called_timer_cb; - - -static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) { - buf->base = malloc(size); - buf->len = size; -} - - -static void read_cb(uv_stream_t* t, ssize_t nread, const uv_buf_t* buf) { - ASSERT((uv_tcp_t*)t == &tcp); - - if (nread == 0) { - free(buf->base); - return; - } - - if (!got_q) { - ASSERT(nread == 1); - ASSERT(!got_eof); - ASSERT(buf->base[0] == 'Q'); - free(buf->base); - got_q = 1; - puts("got Q"); - } else { - ASSERT(nread == UV_EOF); - if (buf->base) { - free(buf->base); - } - got_eof = 1; - puts("got EOF"); - } -} - - -static void shutdown_cb(uv_shutdown_t *req, int status) { - ASSERT(req == &shutdown_req); - - ASSERT(called_connect_cb == 1); - ASSERT(!got_eof); - ASSERT(called_tcp_close_cb == 0); - ASSERT(called_timer_close_cb == 0); - ASSERT(called_timer_cb == 0); - - called_shutdown_cb++; -} - - -static void connect_cb(uv_connect_t *req, int status) { - ASSERT(status == 0); - ASSERT(req == &connect_req); - - /* Start reading from our connection so we can receive the EOF. */ - uv_read_start((uv_stream_t*)&tcp, alloc_cb, read_cb); - - /* - * Write the letter 'Q' to gracefully kill the echo-server. This will not - * effect our connection. - */ - uv_write(&write_req, (uv_stream_t*) &tcp, &qbuf, 1, NULL); - - /* Shutdown our end of the connection. */ - uv_shutdown(&shutdown_req, (uv_stream_t*) &tcp, shutdown_cb); - - called_connect_cb++; - ASSERT(called_shutdown_cb == 0); -} - - -static void tcp_close_cb(uv_handle_t* handle) { - ASSERT(handle == (uv_handle_t*) &tcp); - - ASSERT(called_connect_cb == 1); - ASSERT(got_q); - ASSERT(got_eof); - ASSERT(called_timer_cb == 1); - - called_tcp_close_cb++; -} - - -static void timer_close_cb(uv_handle_t* handle) { - ASSERT(handle == (uv_handle_t*) &timer); - called_timer_close_cb++; -} - - -static void timer_cb(uv_timer_t* handle) { - ASSERT(handle == &timer); - uv_close((uv_handle_t*) handle, timer_close_cb); - - /* - * The most important assert of the test: we have not received - * tcp_close_cb yet. - */ - ASSERT(called_tcp_close_cb == 0); - uv_close((uv_handle_t*) &tcp, tcp_close_cb); - - called_timer_cb++; -} - - -/* - * This test has a client which connects to the echo_server and immediately - * issues a shutdown. The echo-server, in response, will also shutdown their - * connection. We check, with a timer, that libuv is not automatically - * calling uv_close when the client receives the EOF from echo-server. - */ -TEST_IMPL(shutdown_eof) { - struct sockaddr_in server_addr; - int r; - - qbuf.base = "Q"; - qbuf.len = 1; - - r = uv_timer_init(uv_default_loop(), &timer); - ASSERT(r == 0); - - uv_timer_start(&timer, timer_cb, 100, 0); - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &server_addr)); - r = uv_tcp_init(uv_default_loop(), &tcp); - ASSERT(!r); - - r = uv_tcp_connect(&connect_req, - &tcp, - (const struct sockaddr*) &server_addr, - connect_cb); - ASSERT(!r); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(called_connect_cb == 1); - ASSERT(called_shutdown_cb == 1); - ASSERT(got_eof); - ASSERT(got_q); - ASSERT(called_tcp_close_cb == 1); - ASSERT(called_timer_close_cb == 1); - ASSERT(called_timer_cb == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - diff --git a/libuv/test/test-shutdown-twice.c b/libuv/test/test-shutdown-twice.c deleted file mode 100644 index 75c0543..0000000 --- a/libuv/test/test-shutdown-twice.c +++ /dev/null @@ -1,84 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* - * This is a regression test for issue #1113 (calling uv_shutdown twice will - * leave a ghost request in the system) - */ - -#include "uv.h" -#include "task.h" - -static uv_shutdown_t req1; -static uv_shutdown_t req2; - -static int shutdown_cb_called = 0; - -static void close_cb(uv_handle_t* handle) { - -} - -static void shutdown_cb(uv_shutdown_t* req, int status) { - ASSERT(req == &req1); - ASSERT(status == 0); - shutdown_cb_called++; - uv_close((uv_handle_t*) req->handle, close_cb); -} - -static void connect_cb(uv_connect_t* req, int status) { - int r; - - ASSERT(status == 0); - - r = uv_shutdown(&req1, req->handle, shutdown_cb); - ASSERT(r == 0); - r = uv_shutdown(&req2, req->handle, shutdown_cb); - ASSERT(r != 0); - -} - -TEST_IMPL(shutdown_twice) { - struct sockaddr_in addr; - uv_loop_t* loop; - int r; - uv_tcp_t h; - - uv_connect_t connect_req; - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - loop = uv_default_loop(); - - r = uv_tcp_init(loop, &h); - - r = uv_tcp_connect(&connect_req, - &h, - (const struct sockaddr*) &addr, - connect_cb); - ASSERT(r == 0); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(shutdown_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-signal-multiple-loops.c b/libuv/test/test-signal-multiple-loops.c deleted file mode 100644 index f8fef36..0000000 --- a/libuv/test/test-signal-multiple-loops.c +++ /dev/null @@ -1,289 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - - -/* This test does not pretend to be cross-platform. */ -#ifndef _WIN32 - -#include "uv.h" -#include "task.h" - -#include -#include -#include -#include -#include -#include -#include - -/* The value of NUM_SIGNAL_HANDLING_THREADS is not arbitrary; it needs to be a - * multiple of three for reasons that will become clear when you scroll down. - * We're basically creating three different thread groups. The total needs - * to be divisible by three in order for the numbers in the final check to - * match up. - */ -#define NUM_SIGNAL_HANDLING_THREADS 24 -#define NUM_LOOP_CREATING_THREADS 10 - -enum signal_action { - ONLY_SIGUSR1, - ONLY_SIGUSR2, - SIGUSR1_AND_SIGUSR2 -}; - -static uv_sem_t sem; -static uv_mutex_t counter_lock; -static volatile int stop = 0; - -static volatile int signal1_cb_counter = 0; -static volatile int signal2_cb_counter = 0; -static volatile int loop_creation_counter = 0; - - -static void increment_counter(volatile int* counter) { - uv_mutex_lock(&counter_lock); - ++(*counter); - uv_mutex_unlock(&counter_lock); -} - - -static void signal1_cb(uv_signal_t* handle, int signum) { - ASSERT(signum == SIGUSR1); - increment_counter(&signal1_cb_counter); - uv_signal_stop(handle); -} - - -static void signal2_cb(uv_signal_t* handle, int signum) { - ASSERT(signum == SIGUSR2); - increment_counter(&signal2_cb_counter); - uv_signal_stop(handle); -} - - -static void signal_handling_worker(void* context) { - enum signal_action action; - uv_signal_t signal1a; - uv_signal_t signal1b; - uv_signal_t signal2; - uv_loop_t loop; - int r; - - action = (enum signal_action) (uintptr_t) context; - - ASSERT(0 == uv_loop_init(&loop)); - - /* Setup the signal watchers and start them. */ - if (action == ONLY_SIGUSR1 || action == SIGUSR1_AND_SIGUSR2) { - r = uv_signal_init(&loop, &signal1a); - ASSERT(r == 0); - r = uv_signal_start(&signal1a, signal1_cb, SIGUSR1); - ASSERT(r == 0); - r = uv_signal_init(&loop, &signal1b); - ASSERT(r == 0); - r = uv_signal_start(&signal1b, signal1_cb, SIGUSR1); - ASSERT(r == 0); - } - - if (action == ONLY_SIGUSR2 || action == SIGUSR1_AND_SIGUSR2) { - r = uv_signal_init(&loop, &signal2); - ASSERT(r == 0); - r = uv_signal_start(&signal2, signal2_cb, SIGUSR2); - ASSERT(r == 0); - } - - /* Signal watchers are now set up. */ - uv_sem_post(&sem); - - /* Wait for all signals. The signal callbacks stop the watcher, so uv_run - * will return when all signal watchers caught a signal. - */ - r = uv_run(&loop, UV_RUN_DEFAULT); - ASSERT(r == 0); - - /* Restart the signal watchers. */ - if (action == ONLY_SIGUSR1 || action == SIGUSR1_AND_SIGUSR2) { - r = uv_signal_start(&signal1a, signal1_cb, SIGUSR1); - ASSERT(r == 0); - r = uv_signal_start(&signal1b, signal1_cb, SIGUSR1); - ASSERT(r == 0); - } - - if (action == ONLY_SIGUSR2 || action == SIGUSR1_AND_SIGUSR2) { - r = uv_signal_start(&signal2, signal2_cb, SIGUSR2); - ASSERT(r == 0); - } - - /* Wait for signals once more. */ - uv_sem_post(&sem); - - r = uv_run(&loop, UV_RUN_DEFAULT); - ASSERT(r == 0); - - /* Close the watchers. */ - if (action == ONLY_SIGUSR1 || action == SIGUSR1_AND_SIGUSR2) { - uv_close((uv_handle_t*) &signal1a, NULL); - uv_close((uv_handle_t*) &signal1b, NULL); - } - - if (action == ONLY_SIGUSR2 || action == SIGUSR1_AND_SIGUSR2) { - uv_close((uv_handle_t*) &signal2, NULL); - } - - /* Wait for the signal watchers to close. */ - r = uv_run(&loop, UV_RUN_DEFAULT); - ASSERT(r == 0); - - uv_loop_close(&loop); -} - - -static void signal_unexpected_cb(uv_signal_t* handle, int signum) { - ASSERT(0 && "signal_unexpected_cb should never be called"); -} - - -static void loop_creating_worker(void* context) { - (void) context; - - do { - uv_loop_t *loop; - uv_signal_t signal; - int r; - - loop = malloc(sizeof(*loop)); - ASSERT(loop != NULL); - ASSERT(0 == uv_loop_init(loop)); - - r = uv_signal_init(loop, &signal); - ASSERT(r == 0); - - r = uv_signal_start(&signal, signal_unexpected_cb, SIGTERM); - ASSERT(r == 0); - - uv_close((uv_handle_t*) &signal, NULL); - - r = uv_run(loop, UV_RUN_DEFAULT); - ASSERT(r == 0); - - uv_loop_close(loop); - - increment_counter(&loop_creation_counter); - } while (!stop); -} - - -TEST_IMPL(signal_multiple_loops) { - uv_thread_t loop_creating_threads[NUM_LOOP_CREATING_THREADS]; - uv_thread_t signal_handling_threads[NUM_SIGNAL_HANDLING_THREADS]; - enum signal_action action; - sigset_t sigset; - int i; - int r; - - r = uv_sem_init(&sem, 0); - ASSERT(r == 0); - - r = uv_mutex_init(&counter_lock); - ASSERT(r == 0); - - /* Create a couple of threads that create a destroy loops continuously. */ - for (i = 0; i < NUM_LOOP_CREATING_THREADS; i++) { - r = uv_thread_create(&loop_creating_threads[i], - loop_creating_worker, - NULL); - ASSERT(r == 0); - } - - /* Create a couple of threads that actually handle signals. */ - for (i = 0; i < NUM_SIGNAL_HANDLING_THREADS; i++) { - switch (i % 3) { - case 0: action = ONLY_SIGUSR1; break; - case 1: action = ONLY_SIGUSR2; break; - case 2: action = SIGUSR1_AND_SIGUSR2; break; - } - - r = uv_thread_create(&signal_handling_threads[i], - signal_handling_worker, - (void*) (uintptr_t) action); - ASSERT(r == 0); - } - - /* Wait until all threads have started and set up their signal watchers. */ - for (i = 0; i < NUM_SIGNAL_HANDLING_THREADS; i++) - uv_sem_wait(&sem); - - r = kill(getpid(), SIGUSR1); - ASSERT(r == 0); - r = kill(getpid(), SIGUSR2); - ASSERT(r == 0); - - /* Wait for all threads to handle these signals. */ - for (i = 0; i < NUM_SIGNAL_HANDLING_THREADS; i++) - uv_sem_wait(&sem); - - /* Block all signals to this thread, so we are sure that from here the signal - * handler runs in another thread. This is is more likely to catch thread and - * signal safety issues if there are any. - */ - sigfillset(&sigset); - pthread_sigmask(SIG_SETMASK, &sigset, NULL); - - r = kill(getpid(), SIGUSR1); - ASSERT(r == 0); - r = kill(getpid(), SIGUSR2); - ASSERT(r == 0); - - /* Wait for all signal handling threads to exit. */ - for (i = 0; i < NUM_SIGNAL_HANDLING_THREADS; i++) { - r = uv_thread_join(&signal_handling_threads[i]); - ASSERT(r == 0); - } - - /* Tell all loop creating threads to stop. */ - stop = 1; - - /* Wait for all loop creating threads to exit. */ - for (i = 0; i < NUM_LOOP_CREATING_THREADS; i++) { - r = uv_thread_join(&loop_creating_threads[i]); - ASSERT(r == 0); - } - - printf("signal1_cb calls: %d\n", signal1_cb_counter); - printf("signal2_cb calls: %d\n", signal2_cb_counter); - printf("loops created and destroyed: %d\n", loop_creation_counter); - - /* The division by three reflects the fact that we spawn three different - * thread groups of (NUM_SIGNAL_HANDLING_THREADS / 3) threads each. - */ - ASSERT(signal1_cb_counter == 8 * (NUM_SIGNAL_HANDLING_THREADS / 3)); - ASSERT(signal2_cb_counter == 4 * (NUM_SIGNAL_HANDLING_THREADS / 3)); - - /* We don't know exactly how much loops will be created and destroyed, but at - * least there should be 1 for every loop creating thread. - */ - ASSERT(loop_creation_counter >= NUM_LOOP_CREATING_THREADS); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -#endif /* !_WIN32 */ diff --git a/libuv/test/test-signal.c b/libuv/test/test-signal.c deleted file mode 100644 index fcdd8e4..0000000 --- a/libuv/test/test-signal.c +++ /dev/null @@ -1,152 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - - -/* This test does not pretend to be cross-platform. */ -#ifndef _WIN32 - -#include "uv.h" -#include "task.h" - -#include -#include -#include -#include -#include -#include -#include - -#define NSIGNALS 10 - -struct timer_ctx { - unsigned int ncalls; - uv_timer_t handle; - int signum; -}; - -struct signal_ctx { - enum { CLOSE, STOP } stop_or_close; - unsigned int ncalls; - uv_signal_t handle; - int signum; -}; - - -static void signal_cb(uv_signal_t* handle, int signum) { - struct signal_ctx* ctx = container_of(handle, struct signal_ctx, handle); - ASSERT(signum == ctx->signum); - - if (++ctx->ncalls == NSIGNALS) { - if (ctx->stop_or_close == STOP) - uv_signal_stop(handle); - else if (ctx->stop_or_close == CLOSE) - uv_close((uv_handle_t*)handle, NULL); - else - ASSERT(0); - } -} - - -static void timer_cb(uv_timer_t* handle) { - struct timer_ctx* ctx = container_of(handle, struct timer_ctx, handle); - - raise(ctx->signum); - - if (++ctx->ncalls == NSIGNALS) - uv_close((uv_handle_t*)handle, NULL); -} - - -static void start_watcher(uv_loop_t* loop, int signum, struct signal_ctx* ctx) { - ctx->ncalls = 0; - ctx->signum = signum; - ctx->stop_or_close = CLOSE; - ASSERT(0 == uv_signal_init(loop, &ctx->handle)); - ASSERT(0 == uv_signal_start(&ctx->handle, signal_cb, signum)); -} - - -static void start_timer(uv_loop_t* loop, int signum, struct timer_ctx* ctx) { - ctx->ncalls = 0; - ctx->signum = signum; - ASSERT(0 == uv_timer_init(loop, &ctx->handle)); - ASSERT(0 == uv_timer_start(&ctx->handle, timer_cb, 5, 5)); -} - - -TEST_IMPL(we_get_signal) { - struct signal_ctx sc; - struct timer_ctx tc; - uv_loop_t* loop; - - loop = uv_default_loop(); - start_timer(loop, SIGCHLD, &tc); - start_watcher(loop, SIGCHLD, &sc); - sc.stop_or_close = STOP; /* stop, don't close the signal handle */ - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - ASSERT(tc.ncalls == NSIGNALS); - ASSERT(sc.ncalls == NSIGNALS); - - start_timer(loop, SIGCHLD, &tc); - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - ASSERT(tc.ncalls == NSIGNALS); - ASSERT(sc.ncalls == NSIGNALS); - - sc.ncalls = 0; - sc.stop_or_close = CLOSE; /* now close it when it's done */ - uv_signal_start(&sc.handle, signal_cb, SIGCHLD); - - start_timer(loop, SIGCHLD, &tc); - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - ASSERT(tc.ncalls == NSIGNALS); - ASSERT(sc.ncalls == NSIGNALS); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(we_get_signals) { - struct signal_ctx sc[4]; - struct timer_ctx tc[2]; - uv_loop_t* loop; - unsigned int i; - - loop = uv_default_loop(); - start_watcher(loop, SIGUSR1, sc + 0); - start_watcher(loop, SIGUSR1, sc + 1); - start_watcher(loop, SIGUSR2, sc + 2); - start_watcher(loop, SIGUSR2, sc + 3); - start_timer(loop, SIGUSR1, tc + 0); - start_timer(loop, SIGUSR2, tc + 1); - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - - for (i = 0; i < ARRAY_SIZE(sc); i++) - ASSERT(sc[i].ncalls == NSIGNALS); - - for (i = 0; i < ARRAY_SIZE(tc); i++) - ASSERT(tc[i].ncalls == NSIGNALS); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -#endif /* _WIN32 */ diff --git a/libuv/test/test-socket-buffer-size.c b/libuv/test/test-socket-buffer-size.c deleted file mode 100644 index 72f8c25..0000000 --- a/libuv/test/test-socket-buffer-size.c +++ /dev/null @@ -1,77 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include -#include - -static uv_udp_t udp; -static uv_tcp_t tcp; -static int close_cb_called; - - -static void close_cb(uv_handle_t* handle) { - close_cb_called++; -} - - -static void check_buffer_size(uv_handle_t* handle) { - int value; - - value = 0; - ASSERT(0 == uv_recv_buffer_size(handle, &value)); - ASSERT(value > 0); - - value = 10000; - ASSERT(0 == uv_recv_buffer_size(handle, &value)); - - value = 0; - ASSERT(0 == uv_recv_buffer_size(handle, &value)); - /* linux sets double the value */ - ASSERT(value == 10000 || value == 20000); -} - - -TEST_IMPL(socket_buffer_size) { - struct sockaddr_in addr; - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - - ASSERT(0 == uv_tcp_init(uv_default_loop(), &tcp)); - ASSERT(0 == uv_tcp_bind(&tcp, (struct sockaddr*) &addr, 0)); - check_buffer_size((uv_handle_t*) &tcp); - uv_close((uv_handle_t*) &tcp, close_cb); - - ASSERT(0 == uv_udp_init(uv_default_loop(), &udp)); - ASSERT(0 == uv_udp_bind(&udp, (struct sockaddr*) &addr, 0)); - check_buffer_size((uv_handle_t*) &udp); - uv_close((uv_handle_t*) &udp, close_cb); - - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); - - ASSERT(close_cb_called == 2); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-spawn.c b/libuv/test/test-spawn.c deleted file mode 100644 index d3c0693..0000000 --- a/libuv/test/test-spawn.c +++ /dev/null @@ -1,1352 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" -#include -#include -#include -#include - -#ifdef _WIN32 -# if defined(__MINGW32__) -# include -# endif -# include -# include -#else -# include -#endif - - -static int close_cb_called; -static int exit_cb_called; -static uv_process_t process; -static uv_timer_t timer; -static uv_process_options_t options; -static char exepath[1024]; -static size_t exepath_size = 1024; -static char* args[3]; -static int no_term_signal; -static int timer_counter; - -#define OUTPUT_SIZE 1024 -static char output[OUTPUT_SIZE]; -static int output_used; - - -static void close_cb(uv_handle_t* handle) { - printf("close_cb\n"); - close_cb_called++; -} - -static void exit_cb(uv_process_t* process, - int64_t exit_status, - int term_signal) { - printf("exit_cb\n"); - exit_cb_called++; - ASSERT(exit_status == 1); - ASSERT(term_signal == 0); - uv_close((uv_handle_t*)process, close_cb); -} - - -static void fail_cb(uv_process_t* process, - int64_t exit_status, - int term_signal) { - ASSERT(0 && "fail_cb called"); -} - - -static void kill_cb(uv_process_t* process, - int64_t exit_status, - int term_signal) { - int err; - - printf("exit_cb\n"); - exit_cb_called++; -#ifdef _WIN32 - ASSERT(exit_status == 1); -#else - ASSERT(exit_status == 0); -#endif - ASSERT(no_term_signal || term_signal == 15); - uv_close((uv_handle_t*)process, close_cb); - - /* - * Sending signum == 0 should check if the - * child process is still alive, not kill it. - * This process should be dead. - */ - err = uv_kill(process->pid, 0); - ASSERT(err == UV_ESRCH); -} - -static void detach_failure_cb(uv_process_t* process, - int64_t exit_status, - int term_signal) { - printf("detach_cb\n"); - exit_cb_called++; -} - -static void on_alloc(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf) { - buf->base = output + output_used; - buf->len = OUTPUT_SIZE - output_used; -} - - -static void on_read(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { - if (nread > 0) { - output_used += nread; - } else if (nread < 0) { - ASSERT(nread == UV_EOF); - uv_close((uv_handle_t*)tcp, close_cb); - } -} - - -static void on_read_once(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { - uv_read_stop(tcp); - on_read(tcp, nread, buf); -} - - -static void write_cb(uv_write_t* req, int status) { - ASSERT(status == 0); - uv_close((uv_handle_t*)req->handle, close_cb); -} - - -static void init_process_options(char* test, uv_exit_cb exit_cb) { - /* Note spawn_helper1 defined in test/run-tests.c */ - int r = uv_exepath(exepath, &exepath_size); - ASSERT(r == 0); - exepath[exepath_size] = '\0'; - args[0] = exepath; - args[1] = test; - args[2] = NULL; - options.file = exepath; - options.args = args; - options.exit_cb = exit_cb; - options.flags = 0; -} - - -static void timer_cb(uv_timer_t* handle) { - uv_process_kill(&process, /* SIGTERM */ 15); - uv_close((uv_handle_t*)handle, close_cb); -} - - -static void timer_counter_cb(uv_timer_t* handle) { - ++timer_counter; -} - - -TEST_IMPL(spawn_fails) { - int r; - - init_process_options("", fail_cb); - options.file = options.args[0] = "program-that-had-better-not-exist"; - - r = uv_spawn(uv_default_loop(), &process, &options); - ASSERT(r == UV_ENOENT || r == UV_EACCES); - ASSERT(0 == uv_is_active((uv_handle_t*) &process)); - uv_close((uv_handle_t*) &process, NULL); - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(spawn_exit_code) { - int r; - - init_process_options("spawn_helper1", exit_cb); - - r = uv_spawn(uv_default_loop(), &process, &options); - ASSERT(r == 0); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(exit_cb_called == 1); - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(spawn_stdout) { - int r; - uv_pipe_t out; - uv_stdio_container_t stdio[2]; - - init_process_options("spawn_helper2", exit_cb); - - uv_pipe_init(uv_default_loop(), &out, 0); - options.stdio = stdio; - options.stdio[0].flags = UV_IGNORE; - options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; - options.stdio[1].data.stream = (uv_stream_t*)&out; - options.stdio_count = 2; - - r = uv_spawn(uv_default_loop(), &process, &options); - ASSERT(r == 0); - - r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read); - ASSERT(r == 0); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(exit_cb_called == 1); - ASSERT(close_cb_called == 2); /* Once for process once for the pipe. */ - printf("output is: %s", output); - ASSERT(strcmp("hello world\n", output) == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(spawn_stdout_to_file) { - int r; - uv_file file; - uv_fs_t fs_req; - uv_stdio_container_t stdio[2]; - uv_buf_t buf; - - /* Setup. */ - unlink("stdout_file"); - - init_process_options("spawn_helper2", exit_cb); - - r = uv_fs_open(uv_default_loop(), &fs_req, "stdout_file", O_CREAT | O_RDWR, - S_IRUSR | S_IWUSR, NULL); - ASSERT(r != -1); - uv_fs_req_cleanup(&fs_req); - - file = r; - - options.stdio = stdio; - options.stdio[0].flags = UV_IGNORE; - options.stdio[1].flags = UV_INHERIT_FD; - options.stdio[1].data.fd = file; - options.stdio_count = 2; - - r = uv_spawn(uv_default_loop(), &process, &options); - ASSERT(r == 0); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(exit_cb_called == 1); - ASSERT(close_cb_called == 1); - - buf = uv_buf_init(output, sizeof(output)); - r = uv_fs_read(uv_default_loop(), &fs_req, file, &buf, 1, 0, NULL); - ASSERT(r == 12); - uv_fs_req_cleanup(&fs_req); - - r = uv_fs_close(uv_default_loop(), &fs_req, file, NULL); - ASSERT(r == 0); - uv_fs_req_cleanup(&fs_req); - - printf("output is: %s", output); - ASSERT(strcmp("hello world\n", output) == 0); - - /* Cleanup. */ - unlink("stdout_file"); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(spawn_stdout_and_stderr_to_file) { - int r; - uv_file file; - uv_fs_t fs_req; - uv_stdio_container_t stdio[3]; - uv_buf_t buf; - - /* Setup. */ - unlink("stdout_file"); - - init_process_options("spawn_helper6", exit_cb); - - r = uv_fs_open(uv_default_loop(), &fs_req, "stdout_file", O_CREAT | O_RDWR, - S_IRUSR | S_IWUSR, NULL); - ASSERT(r != -1); - uv_fs_req_cleanup(&fs_req); - - file = r; - - options.stdio = stdio; - options.stdio[0].flags = UV_IGNORE; - options.stdio[1].flags = UV_INHERIT_FD; - options.stdio[1].data.fd = file; - options.stdio[2].flags = UV_INHERIT_FD; - options.stdio[2].data.fd = file; - options.stdio_count = 3; - - r = uv_spawn(uv_default_loop(), &process, &options); - ASSERT(r == 0); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(exit_cb_called == 1); - ASSERT(close_cb_called == 1); - - buf = uv_buf_init(output, sizeof(output)); - r = uv_fs_read(uv_default_loop(), &fs_req, file, &buf, 1, 0, NULL); - ASSERT(r == 27); - uv_fs_req_cleanup(&fs_req); - - r = uv_fs_close(uv_default_loop(), &fs_req, file, NULL); - ASSERT(r == 0); - uv_fs_req_cleanup(&fs_req); - - printf("output is: %s", output); - ASSERT(strcmp("hello world\nhello errworld\n", output) == 0); - - /* Cleanup. */ - unlink("stdout_file"); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(spawn_stdin) { - int r; - uv_pipe_t out; - uv_pipe_t in; - uv_write_t write_req; - uv_buf_t buf; - uv_stdio_container_t stdio[2]; - char buffer[] = "hello-from-spawn_stdin"; - - init_process_options("spawn_helper3", exit_cb); - - uv_pipe_init(uv_default_loop(), &out, 0); - uv_pipe_init(uv_default_loop(), &in, 0); - options.stdio = stdio; - options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; - options.stdio[0].data.stream = (uv_stream_t*)∈ - options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; - options.stdio[1].data.stream = (uv_stream_t*)&out; - options.stdio_count = 2; - - r = uv_spawn(uv_default_loop(), &process, &options); - ASSERT(r == 0); - - buf.base = buffer; - buf.len = sizeof(buffer); - r = uv_write(&write_req, (uv_stream_t*)&in, &buf, 1, write_cb); - ASSERT(r == 0); - - r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read); - ASSERT(r == 0); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(exit_cb_called == 1); - ASSERT(close_cb_called == 3); /* Once for process twice for the pipe. */ - ASSERT(strcmp(buffer, output) == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(spawn_stdio_greater_than_3) { - int r; - uv_pipe_t pipe; - uv_stdio_container_t stdio[4]; - - init_process_options("spawn_helper5", exit_cb); - - uv_pipe_init(uv_default_loop(), &pipe, 0); - options.stdio = stdio; - options.stdio[0].flags = UV_IGNORE; - options.stdio[1].flags = UV_IGNORE; - options.stdio[2].flags = UV_IGNORE; - options.stdio[3].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; - options.stdio[3].data.stream = (uv_stream_t*)&pipe; - options.stdio_count = 4; - - r = uv_spawn(uv_default_loop(), &process, &options); - ASSERT(r == 0); - - r = uv_read_start((uv_stream_t*) &pipe, on_alloc, on_read); - ASSERT(r == 0); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(exit_cb_called == 1); - ASSERT(close_cb_called == 2); /* Once for process once for the pipe. */ - printf("output from stdio[3] is: %s", output); - ASSERT(strcmp("fourth stdio!\n", output) == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(spawn_ignored_stdio) { - int r; - - init_process_options("spawn_helper6", exit_cb); - - options.stdio = NULL; - options.stdio_count = 0; - - r = uv_spawn(uv_default_loop(), &process, &options); - ASSERT(r == 0); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(exit_cb_called == 1); - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(spawn_and_kill) { - int r; - - init_process_options("spawn_helper4", kill_cb); - - r = uv_spawn(uv_default_loop(), &process, &options); - ASSERT(r == 0); - - r = uv_timer_init(uv_default_loop(), &timer); - ASSERT(r == 0); - - r = uv_timer_start(&timer, timer_cb, 500, 0); - ASSERT(r == 0); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(exit_cb_called == 1); - ASSERT(close_cb_called == 2); /* Once for process and once for timer. */ - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(spawn_preserve_env) { - int r; - uv_pipe_t out; - uv_stdio_container_t stdio[2]; - - init_process_options("spawn_helper7", exit_cb); - - uv_pipe_init(uv_default_loop(), &out, 0); - options.stdio = stdio; - options.stdio[0].flags = UV_IGNORE; - options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; - options.stdio[1].data.stream = (uv_stream_t*) &out; - options.stdio_count = 2; - - r = putenv("ENV_TEST=testval"); - ASSERT(r == 0); - - /* Explicitly set options.env to NULL to test for env clobbering. */ - options.env = NULL; - - r = uv_spawn(uv_default_loop(), &process, &options); - ASSERT(r == 0); - - r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read); - ASSERT(r == 0); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(exit_cb_called == 1); - ASSERT(close_cb_called == 2); - - printf("output is: %s", output); - ASSERT(strcmp("testval", output) == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(spawn_detached) { - int r; - - init_process_options("spawn_helper4", detach_failure_cb); - - options.flags |= UV_PROCESS_DETACHED; - - r = uv_spawn(uv_default_loop(), &process, &options); - ASSERT(r == 0); - - uv_unref((uv_handle_t*)&process); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(exit_cb_called == 0); - - r = uv_kill(process.pid, 0); - ASSERT(r == 0); - - r = uv_kill(process.pid, 15); - ASSERT(r == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -TEST_IMPL(spawn_and_kill_with_std) { - int r; - uv_pipe_t in, out, err; - uv_write_t write; - char message[] = "Nancy's joining me because the message this evening is " - "not my message but ours."; - uv_buf_t buf; - uv_stdio_container_t stdio[3]; - - init_process_options("spawn_helper4", kill_cb); - - r = uv_pipe_init(uv_default_loop(), &in, 0); - ASSERT(r == 0); - - r = uv_pipe_init(uv_default_loop(), &out, 0); - ASSERT(r == 0); - - r = uv_pipe_init(uv_default_loop(), &err, 0); - ASSERT(r == 0); - - options.stdio = stdio; - options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; - options.stdio[0].data.stream = (uv_stream_t*)∈ - options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; - options.stdio[1].data.stream = (uv_stream_t*)&out; - options.stdio[2].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; - options.stdio[2].data.stream = (uv_stream_t*)&err; - options.stdio_count = 3; - - r = uv_spawn(uv_default_loop(), &process, &options); - ASSERT(r == 0); - - buf = uv_buf_init(message, sizeof message); - r = uv_write(&write, (uv_stream_t*) &in, &buf, 1, write_cb); - ASSERT(r == 0); - - r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read); - ASSERT(r == 0); - - r = uv_read_start((uv_stream_t*) &err, on_alloc, on_read); - ASSERT(r == 0); - - r = uv_timer_init(uv_default_loop(), &timer); - ASSERT(r == 0); - - r = uv_timer_start(&timer, timer_cb, 500, 0); - ASSERT(r == 0); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(exit_cb_called == 1); - ASSERT(close_cb_called == 5); /* process x 1, timer x 1, stdio x 3. */ - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(spawn_and_ping) { - uv_write_t write_req; - uv_pipe_t in, out; - uv_buf_t buf; - uv_stdio_container_t stdio[2]; - int r; - - init_process_options("spawn_helper3", exit_cb); - buf = uv_buf_init("TEST", 4); - - uv_pipe_init(uv_default_loop(), &out, 0); - uv_pipe_init(uv_default_loop(), &in, 0); - options.stdio = stdio; - options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; - options.stdio[0].data.stream = (uv_stream_t*)∈ - options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; - options.stdio[1].data.stream = (uv_stream_t*)&out; - options.stdio_count = 2; - - r = uv_spawn(uv_default_loop(), &process, &options); - ASSERT(r == 0); - - /* Sending signum == 0 should check if the - * child process is still alive, not kill it. - */ - r = uv_process_kill(&process, 0); - ASSERT(r == 0); - - r = uv_write(&write_req, (uv_stream_t*)&in, &buf, 1, write_cb); - ASSERT(r == 0); - - r = uv_read_start((uv_stream_t*)&out, on_alloc, on_read); - ASSERT(r == 0); - - ASSERT(exit_cb_called == 0); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(exit_cb_called == 1); - ASSERT(strcmp(output, "TEST") == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(spawn_same_stdout_stderr) { - uv_write_t write_req; - uv_pipe_t in, out; - uv_buf_t buf; - uv_stdio_container_t stdio[3]; - int r; - - init_process_options("spawn_helper3", exit_cb); - buf = uv_buf_init("TEST", 4); - - uv_pipe_init(uv_default_loop(), &out, 0); - uv_pipe_init(uv_default_loop(), &in, 0); - options.stdio = stdio; - options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; - options.stdio[0].data.stream = (uv_stream_t*)∈ - options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; - options.stdio[1].data.stream = (uv_stream_t*)&out; - options.stdio_count = 2; - - r = uv_spawn(uv_default_loop(), &process, &options); - ASSERT(r == 0); - - /* Sending signum == 0 should check if the - * child process is still alive, not kill it. - */ - r = uv_process_kill(&process, 0); - ASSERT(r == 0); - - r = uv_write(&write_req, (uv_stream_t*)&in, &buf, 1, write_cb); - ASSERT(r == 0); - - r = uv_read_start((uv_stream_t*)&out, on_alloc, on_read); - ASSERT(r == 0); - - ASSERT(exit_cb_called == 0); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(exit_cb_called == 1); - ASSERT(strcmp(output, "TEST") == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(spawn_closed_process_io) { - uv_pipe_t in; - uv_write_t write_req; - uv_buf_t buf; - uv_stdio_container_t stdio[2]; - static char buffer[] = "hello-from-spawn_stdin\n"; - - init_process_options("spawn_helper3", exit_cb); - - uv_pipe_init(uv_default_loop(), &in, 0); - options.stdio = stdio; - options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; - options.stdio[0].data.stream = (uv_stream_t*) ∈ - options.stdio_count = 1; - - close(0); /* Close process stdin. */ - - ASSERT(0 == uv_spawn(uv_default_loop(), &process, &options)); - - buf = uv_buf_init(buffer, sizeof(buffer)); - ASSERT(0 == uv_write(&write_req, (uv_stream_t*) &in, &buf, 1, write_cb)); - - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); - - ASSERT(exit_cb_called == 1); - ASSERT(close_cb_called == 2); /* process, child stdin */ - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(kill) { - int r; - -#ifdef _WIN32 - no_term_signal = 1; -#endif - - init_process_options("spawn_helper4", kill_cb); - - r = uv_spawn(uv_default_loop(), &process, &options); - ASSERT(r == 0); - - /* Sending signum == 0 should check if the - * child process is still alive, not kill it. - */ - r = uv_kill(process.pid, 0); - ASSERT(r == 0); - - /* Kill the process. */ - r = uv_kill(process.pid, /* SIGTERM */ 15); - ASSERT(r == 0); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(exit_cb_called == 1); - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -#ifdef _WIN32 -TEST_IMPL(spawn_detect_pipe_name_collisions_on_windows) { - int r; - uv_pipe_t out; - char name[64]; - HANDLE pipe_handle; - uv_stdio_container_t stdio[2]; - - init_process_options("spawn_helper2", exit_cb); - - uv_pipe_init(uv_default_loop(), &out, 0); - options.stdio = stdio; - options.stdio[0].flags = UV_IGNORE; - options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; - options.stdio[1].data.stream = (uv_stream_t*)&out; - options.stdio_count = 2; - - /* Create a pipe that'll cause a collision. */ - _snprintf(name, - sizeof(name), - "\\\\.\\pipe\\uv\\%p-%d", - &out, - GetCurrentProcessId()); - pipe_handle = CreateNamedPipeA(name, - PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, - PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, - 10, - 65536, - 65536, - 0, - NULL); - ASSERT(pipe_handle != INVALID_HANDLE_VALUE); - - r = uv_spawn(uv_default_loop(), &process, &options); - ASSERT(r == 0); - - r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read); - ASSERT(r == 0); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(exit_cb_called == 1); - ASSERT(close_cb_called == 2); /* Once for process once for the pipe. */ - printf("output is: %s", output); - ASSERT(strcmp("hello world\n", output) == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -int make_program_args(char** args, int verbatim_arguments, WCHAR** dst_ptr); -WCHAR* quote_cmd_arg(const WCHAR *source, WCHAR *target); - -TEST_IMPL(argument_escaping) { - const WCHAR* test_str[] = { - L"", - L"HelloWorld", - L"Hello World", - L"Hello\"World", - L"Hello World\\", - L"Hello\\\"World", - L"Hello\\World", - L"Hello\\\\World", - L"Hello World\\", - L"c:\\path\\to\\node.exe --eval \"require('c:\\\\path\\\\to\\\\test.js')\"" - }; - const int count = sizeof(test_str) / sizeof(*test_str); - WCHAR** test_output; - WCHAR* command_line; - WCHAR** cracked; - size_t total_size = 0; - int i; - int num_args; - int result; - - char* verbatim[] = { - "cmd.exe", - "/c", - "c:\\path\\to\\node.exe --eval \"require('c:\\\\path\\\\to\\\\test.js')\"", - NULL - }; - WCHAR* verbatim_output; - WCHAR* non_verbatim_output; - - test_output = calloc(count, sizeof(WCHAR*)); - ASSERT(test_output != NULL); - for (i = 0; i < count; ++i) { - test_output[i] = calloc(2 * (wcslen(test_str[i]) + 2), sizeof(WCHAR)); - quote_cmd_arg(test_str[i], test_output[i]); - wprintf(L"input : %s\n", test_str[i]); - wprintf(L"output: %s\n", test_output[i]); - total_size += wcslen(test_output[i]) + 1; - } - command_line = calloc(total_size + 1, sizeof(WCHAR)); - ASSERT(command_line != NULL); - for (i = 0; i < count; ++i) { - wcscat(command_line, test_output[i]); - wcscat(command_line, L" "); - } - command_line[total_size - 1] = L'\0'; - - wprintf(L"command_line: %s\n", command_line); - - cracked = CommandLineToArgvW(command_line, &num_args); - for (i = 0; i < num_args; ++i) { - wprintf(L"%d: %s\t%s\n", i, test_str[i], cracked[i]); - ASSERT(wcscmp(test_str[i], cracked[i]) == 0); - } - - LocalFree(cracked); - for (i = 0; i < count; ++i) { - free(test_output[i]); - } - - result = make_program_args(verbatim, 1, &verbatim_output); - ASSERT(result == 0); - result = make_program_args(verbatim, 0, &non_verbatim_output); - ASSERT(result == 0); - - wprintf(L" verbatim_output: %s\n", verbatim_output); - wprintf(L"non_verbatim_output: %s\n", non_verbatim_output); - - ASSERT(wcscmp(verbatim_output, - L"cmd.exe /c c:\\path\\to\\node.exe --eval " - L"\"require('c:\\\\path\\\\to\\\\test.js')\"") == 0); - ASSERT(wcscmp(non_verbatim_output, - L"cmd.exe /c \"c:\\path\\to\\node.exe --eval " - L"\\\"require('c:\\\\path\\\\to\\\\test.js')\\\"\"") == 0); - - free(verbatim_output); - free(non_verbatim_output); - - return 0; -} - -int make_program_env(char** env_block, WCHAR** dst_ptr); - -TEST_IMPL(environment_creation) { - int i; - char* environment[] = { - "FOO=BAR", - "SYSTEM=ROOT", /* substring of a supplied var name */ - "SYSTEMROOTED=OMG", /* supplied var name is a substring */ - "TEMP=C:\\Temp", - "INVALID", - "BAZ=QUX", - "B_Z=QUX", - "B\xe2\x82\xacZ=QUX", - "B\xf0\x90\x80\x82Z=QUX", - "B\xef\xbd\xa1Z=QUX", - "B\xf0\xa3\x91\x96Z=QUX", - "BAZ", /* repeat, invalid variable */ - NULL - }; - WCHAR* wenvironment[] = { - L"BAZ=QUX", - L"B_Z=QUX", - L"B\x20acZ=QUX", - L"B\xd800\xdc02Z=QUX", - L"B\xd84d\xdc56Z=QUX", - L"B\xff61Z=QUX", - L"FOO=BAR", - L"SYSTEM=ROOT", /* substring of a supplied var name */ - L"SYSTEMROOTED=OMG", /* supplied var name is a substring */ - L"TEMP=C:\\Temp", - }; - WCHAR* from_env[] = { - /* list should be kept in sync with list - * in process.c, minus variables in wenvironment */ - L"HOMEDRIVE", - L"HOMEPATH", - L"LOGONSERVER", - L"PATH", - L"USERDOMAIN", - L"USERNAME", - L"USERPROFILE", - L"SYSTEMDRIVE", - L"SYSTEMROOT", - L"WINDIR", - /* test for behavior in the absence of a - * required-environment variable: */ - L"ZTHIS_ENV_VARIABLE_DOES_NOT_EXIST", - }; - int found_in_loc_env[ARRAY_SIZE(wenvironment)] = {0}; - int found_in_usr_env[ARRAY_SIZE(from_env)] = {0}; - WCHAR *expected[ARRAY_SIZE(from_env)]; - int result; - WCHAR* str; - WCHAR* prev; - WCHAR* env; - - for (i = 0; i < ARRAY_SIZE(from_env); i++) { - /* copy expected additions to environment locally */ - size_t len = GetEnvironmentVariableW(from_env[i], NULL, 0); - if (len == 0) { - found_in_usr_env[i] = 1; - str = malloc(1 * sizeof(WCHAR)); - *str = 0; - expected[i] = str; - } else { - size_t name_len = wcslen(from_env[i]); - str = malloc((name_len+1+len) * sizeof(WCHAR)); - wmemcpy(str, from_env[i], name_len); - expected[i] = str; - str += name_len; - *str++ = L'='; - GetEnvironmentVariableW(from_env[i], str, len); - } - } - - result = make_program_env(environment, &env); - ASSERT(result == 0); - - for (str = env, prev = NULL; *str; prev = str, str += wcslen(str) + 1) { - int found = 0; -#if 0 - _cputws(str); - putchar('\n'); -#endif - for (i = 0; i < ARRAY_SIZE(wenvironment) && !found; i++) { - if (!wcscmp(str, wenvironment[i])) { - ASSERT(!found_in_loc_env[i]); - found_in_loc_env[i] = 1; - found = 1; - } - } - for (i = 0; i < ARRAY_SIZE(expected) && !found; i++) { - if (!wcscmp(str, expected[i])) { - ASSERT(!found_in_usr_env[i]); - found_in_usr_env[i] = 1; - found = 1; - } - } - if (prev) { /* verify sort order -- requires Vista */ -#if _WIN32_WINNT >= 0x0600 && \ - (!defined(__MINGW32__) || defined(__MINGW64_VERSION_MAJOR)) - ASSERT(CompareStringOrdinal(prev, -1, str, -1, TRUE) == 1); -#endif - } - ASSERT(found); /* verify that we expected this variable */ - } - - /* verify that we found all expected variables */ - for (i = 0; i < ARRAY_SIZE(wenvironment); i++) { - ASSERT(found_in_loc_env[i]); - } - for (i = 0; i < ARRAY_SIZE(expected); i++) { - ASSERT(found_in_usr_env[i]); - } - - return 0; -} - -// Regression test for issue #909 -TEST_IMPL(spawn_with_an_odd_path) { - int r; - - char newpath[2048]; - char *path = getenv("PATH"); - ASSERT(path != NULL); - snprintf(newpath, 2048, ";.;%s", path); - SetEnvironmentVariable("PATH", path); - - init_process_options("", exit_cb); - options.file = options.args[0] = "program-that-had-better-not-exist"; - r = uv_spawn(uv_default_loop(), &process, &options); - ASSERT(r == UV_ENOENT || r == UV_EACCES); - ASSERT(0 == uv_is_active((uv_handle_t*) &process)); - uv_close((uv_handle_t*) &process, NULL); - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); - - MAKE_VALGRIND_HAPPY(); - return 0; -} -#endif - -#ifndef _WIN32 -TEST_IMPL(spawn_setuid_setgid) { - int r; - struct passwd* pw; - - /* if not root, then this will fail. */ - uv_uid_t uid = getuid(); - if (uid != 0) { - fprintf(stderr, "spawn_setuid_setgid skipped: not root\n"); - return 0; - } - - init_process_options("spawn_helper1", exit_cb); - - /* become the "nobody" user. */ - pw = getpwnam("nobody"); - ASSERT(pw != NULL); - options.uid = pw->pw_uid; - options.gid = pw->pw_gid; - options.flags = UV_PROCESS_SETUID | UV_PROCESS_SETGID; - - r = uv_spawn(uv_default_loop(), &process, &options); - if (r == UV_EACCES) - RETURN_SKIP("user 'nobody' cannot access the test runner"); - - ASSERT(r == 0); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(exit_cb_called == 1); - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} -#endif - - -#ifndef _WIN32 -TEST_IMPL(spawn_setuid_fails) { - int r; - - /* if root, become nobody. */ - uv_uid_t uid = getuid(); - if (uid == 0) { - struct passwd* pw; - pw = getpwnam("nobody"); - ASSERT(pw != NULL); - ASSERT(0 == setgid(pw->pw_gid)); - ASSERT(0 == setuid(pw->pw_uid)); - } - - init_process_options("spawn_helper1", fail_cb); - - options.flags |= UV_PROCESS_SETUID; - options.uid = 0; - - r = uv_spawn(uv_default_loop(), &process, &options); - ASSERT(r == UV_EPERM); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(close_cb_called == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(spawn_setgid_fails) { - int r; - - /* if root, become nobody. */ - uv_uid_t uid = getuid(); - if (uid == 0) { - struct passwd* pw; - pw = getpwnam("nobody"); - ASSERT(pw != NULL); - ASSERT(0 == setgid(pw->pw_gid)); - ASSERT(0 == setuid(pw->pw_uid)); - } - - init_process_options("spawn_helper1", fail_cb); - - options.flags |= UV_PROCESS_SETGID; - options.gid = 0; - - r = uv_spawn(uv_default_loop(), &process, &options); - ASSERT(r == UV_EPERM); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(close_cb_called == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} -#endif - - -#ifdef _WIN32 - -static void exit_cb_unexpected(uv_process_t* process, - int64_t exit_status, - int term_signal) { - ASSERT(0 && "should not have been called"); -} - - -TEST_IMPL(spawn_setuid_fails) { - int r; - - init_process_options("spawn_helper1", exit_cb_unexpected); - - options.flags |= UV_PROCESS_SETUID; - options.uid = (uv_uid_t) -42424242; - - r = uv_spawn(uv_default_loop(), &process, &options); - ASSERT(r == UV_ENOTSUP); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(close_cb_called == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(spawn_setgid_fails) { - int r; - - init_process_options("spawn_helper1", exit_cb_unexpected); - - options.flags |= UV_PROCESS_SETGID; - options.gid = (uv_gid_t) -42424242; - - r = uv_spawn(uv_default_loop(), &process, &options); - ASSERT(r == UV_ENOTSUP); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(close_cb_called == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} -#endif - - -TEST_IMPL(spawn_auto_unref) { - init_process_options("spawn_helper1", NULL); - ASSERT(0 == uv_spawn(uv_default_loop(), &process, &options)); - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); - ASSERT(0 == uv_is_closing((uv_handle_t*) &process)); - uv_close((uv_handle_t*) &process, NULL); - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); - ASSERT(1 == uv_is_closing((uv_handle_t*) &process)); - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -#ifndef _WIN32 -TEST_IMPL(spawn_fs_open) { - int fd; - uv_fs_t fs_req; - uv_pipe_t in; - uv_write_t write_req; - uv_buf_t buf; - uv_stdio_container_t stdio[1]; - - fd = uv_fs_open(uv_default_loop(), &fs_req, "/dev/null", O_RDWR, 0, NULL); - ASSERT(fd >= 0); - - init_process_options("spawn_helper8", exit_cb); - - ASSERT(0 == uv_pipe_init(uv_default_loop(), &in, 0)); - - options.stdio = stdio; - options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; - options.stdio[0].data.stream = (uv_stream_t*) ∈ - options.stdio_count = 1; - - ASSERT(0 == uv_spawn(uv_default_loop(), &process, &options)); - - buf = uv_buf_init((char*) &fd, sizeof(fd)); - ASSERT(0 == uv_write(&write_req, (uv_stream_t*) &in, &buf, 1, write_cb)); - - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); - ASSERT(0 == uv_fs_close(uv_default_loop(), &fs_req, fd, NULL)); - - ASSERT(exit_cb_called == 1); - ASSERT(close_cb_called == 2); /* One for `in`, one for process */ - - MAKE_VALGRIND_HAPPY(); - return 0; -} -#endif /* !_WIN32 */ - - -#ifndef _WIN32 -TEST_IMPL(closed_fd_events) { - uv_stdio_container_t stdio[3]; - uv_pipe_t pipe_handle; - int fd[2]; - - /* create a pipe and share it with a child process */ - ASSERT(0 == pipe(fd)); - - /* spawn_helper4 blocks indefinitely. */ - init_process_options("spawn_helper4", exit_cb); - options.stdio_count = 3; - options.stdio = stdio; - options.stdio[0].flags = UV_INHERIT_FD; - options.stdio[0].data.fd = fd[0]; - options.stdio[1].flags = UV_IGNORE; - options.stdio[2].flags = UV_IGNORE; - - ASSERT(0 == uv_spawn(uv_default_loop(), &process, &options)); - uv_unref((uv_handle_t*) &process); - - /* read from the pipe with uv */ - ASSERT(0 == uv_pipe_init(uv_default_loop(), &pipe_handle, 0)); - ASSERT(0 == uv_pipe_open(&pipe_handle, fd[0])); - fd[0] = -1; - - ASSERT(0 == uv_read_start((uv_stream_t*) &pipe_handle, on_alloc, on_read_once)); - - ASSERT(1 == write(fd[1], "", 1)); - - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE)); - - /* should have received just one byte */ - ASSERT(output_used == 1); - - /* close the pipe and see if we still get events */ - uv_close((uv_handle_t*) &pipe_handle, close_cb); - - ASSERT(1 == write(fd[1], "", 1)); - - ASSERT(0 == uv_timer_init(uv_default_loop(), &timer)); - ASSERT(0 == uv_timer_start(&timer, timer_counter_cb, 10, 0)); - - /* see if any spurious events interrupt the timer */ - if (1 == uv_run(uv_default_loop(), UV_RUN_ONCE)) - /* have to run again to really trigger the timer */ - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE)); - - ASSERT(timer_counter == 1); - - /* cleanup */ - ASSERT(0 == uv_process_kill(&process, /* SIGTERM */ 15)); - ASSERT(0 == close(fd[1])); - - MAKE_VALGRIND_HAPPY(); - return 0; -} -#endif /* !_WIN32 */ - -TEST_IMPL(spawn_reads_child_path) { - int r; - int len; - char file[64]; - char path[1024]; - char* env[3]; - - /* Need to carry over the dynamic linker path when the test runner is - * linked against libuv.so, see https://github.com/libuv/libuv/issues/85. - */ -#if defined(__APPLE__) - static const char dyld_path_var[] = "DYLD_LIBRARY_PATH"; -#else - static const char dyld_path_var[] = "LD_LIBRARY_PATH"; -#endif - - /* Set up the process, but make sure that the file to run is relative and */ - /* requires a lookup into PATH */ - init_process_options("spawn_helper1", exit_cb); - - /* Set up the PATH env variable */ - for (len = strlen(exepath); - exepath[len - 1] != '/' && exepath[len - 1] != '\\'; - len--); - strcpy(file, exepath + len); - exepath[len] = 0; - strcpy(path, "PATH="); - strcpy(path + 5, exepath); - - env[0] = path; - env[1] = getenv(dyld_path_var); - env[2] = NULL; - - if (env[1] != NULL) { - static char buf[1024 + sizeof(dyld_path_var)]; - snprintf(buf, sizeof(buf), "%s=%s", dyld_path_var, env[1]); - env[1] = buf; - } - - options.file = file; - options.args[0] = file; - options.env = env; - - r = uv_spawn(uv_default_loop(), &process, &options); - ASSERT(r == 0); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(exit_cb_called == 1); - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-stdio-over-pipes.c b/libuv/test/test-stdio-over-pipes.c deleted file mode 100644 index 1574476..0000000 --- a/libuv/test/test-stdio-over-pipes.c +++ /dev/null @@ -1,255 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include - - -static char exepath[1024]; -static size_t exepath_size = 1024; -static char* args[3]; -static uv_process_options_t options; -static int close_cb_called; -static int exit_cb_called; -static int on_read_cb_called; -static int after_write_cb_called; -static uv_pipe_t in; -static uv_pipe_t out; -static uv_loop_t* loop; -#define OUTPUT_SIZE 1024 -static char output[OUTPUT_SIZE]; -static int output_used; - - -static void close_cb(uv_handle_t* handle) { - close_cb_called++; -} - - -static void exit_cb(uv_process_t* process, - int64_t exit_status, - int term_signal) { - printf("exit_cb\n"); - exit_cb_called++; - ASSERT(exit_status == 0); - ASSERT(term_signal == 0); - uv_close((uv_handle_t*)process, close_cb); - uv_close((uv_handle_t*)&in, close_cb); - uv_close((uv_handle_t*)&out, close_cb); -} - - -static void init_process_options(char* test, uv_exit_cb exit_cb) { - int r = uv_exepath(exepath, &exepath_size); - ASSERT(r == 0); - exepath[exepath_size] = '\0'; - args[0] = exepath; - args[1] = test; - args[2] = NULL; - options.file = exepath; - options.args = args; - options.exit_cb = exit_cb; -} - - -static void on_alloc(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf) { - buf->base = output + output_used; - buf->len = OUTPUT_SIZE - output_used; -} - - -static void after_write(uv_write_t* req, int status) { - if (status) { - fprintf(stderr, "uv_write error: %s\n", uv_strerror(status)); - ASSERT(0); - } - - /* Free the read/write buffer and the request */ - free(req); - - after_write_cb_called++; -} - - -static void on_read(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* rdbuf) { - uv_write_t* req; - uv_buf_t wrbuf; - int r; - - ASSERT(nread > 0 || nread == UV_EOF); - - if (nread > 0) { - output_used += nread; - if (output_used == 12) { - ASSERT(memcmp("hello world\n", output, 12) == 0); - wrbuf = uv_buf_init(output, output_used); - req = malloc(sizeof(*req)); - r = uv_write(req, (uv_stream_t*)&in, &wrbuf, 1, after_write); - ASSERT(r == 0); - } - } - - on_read_cb_called++; -} - - -TEST_IMPL(stdio_over_pipes) { - int r; - uv_process_t process; - uv_stdio_container_t stdio[2]; - - loop = uv_default_loop(); - - init_process_options("stdio_over_pipes_helper", exit_cb); - - uv_pipe_init(loop, &out, 0); - uv_pipe_init(loop, &in, 0); - - options.stdio = stdio; - options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; - options.stdio[0].data.stream = (uv_stream_t*)∈ - options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE; - options.stdio[1].data.stream = (uv_stream_t*)&out; - options.stdio_count = 2; - - r = uv_spawn(loop, &process, &options); - ASSERT(r == 0); - - r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read); - ASSERT(r == 0); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(on_read_cb_called > 1); - ASSERT(after_write_cb_called == 1); - ASSERT(exit_cb_called == 1); - ASSERT(close_cb_called == 3); - ASSERT(memcmp("hello world\n", output, 12) == 0); - ASSERT(output_used == 12); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -/* Everything here runs in a child process. */ - -static int on_pipe_read_called; -static int after_write_called; -static uv_pipe_t stdin_pipe; -static uv_pipe_t stdout_pipe; - -static void on_pipe_read(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { - ASSERT(nread > 0); - ASSERT(memcmp("hello world\n", buf->base, nread) == 0); - on_pipe_read_called++; - - free(buf->base); - - uv_close((uv_handle_t*)&stdin_pipe, close_cb); - uv_close((uv_handle_t*)&stdout_pipe, close_cb); -} - - -static void after_pipe_write(uv_write_t* req, int status) { - ASSERT(status == 0); - after_write_called++; -} - - -static void on_read_alloc(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf) { - buf->base = malloc(suggested_size); - buf->len = suggested_size; -} - - -int stdio_over_pipes_helper(void) { - /* Write several buffers to test that the write order is preserved. */ - char* buffers[] = { - "he", - "ll", - "o ", - "wo", - "rl", - "d", - "\n" - }; - - uv_write_t write_req[ARRAY_SIZE(buffers)]; - uv_buf_t buf[ARRAY_SIZE(buffers)]; - unsigned int i; - int r; - uv_loop_t* loop = uv_default_loop(); - - ASSERT(UV_NAMED_PIPE == uv_guess_handle(0)); - ASSERT(UV_NAMED_PIPE == uv_guess_handle(1)); - - r = uv_pipe_init(loop, &stdin_pipe, 0); - ASSERT(r == 0); - r = uv_pipe_init(loop, &stdout_pipe, 0); - ASSERT(r == 0); - - uv_pipe_open(&stdin_pipe, 0); - uv_pipe_open(&stdout_pipe, 1); - - /* Unref both stdio handles to make sure that all writes complete. */ - uv_unref((uv_handle_t*)&stdin_pipe); - uv_unref((uv_handle_t*)&stdout_pipe); - - for (i = 0; i < ARRAY_SIZE(buffers); i++) { - buf[i] = uv_buf_init((char*)buffers[i], strlen(buffers[i])); - } - - for (i = 0; i < ARRAY_SIZE(buffers); i++) { - r = uv_write(&write_req[i], (uv_stream_t*)&stdout_pipe, &buf[i], 1, - after_pipe_write); - ASSERT(r == 0); - } - - uv_run(loop, UV_RUN_DEFAULT); - - ASSERT(after_write_called == 7); - ASSERT(on_pipe_read_called == 0); - ASSERT(close_cb_called == 0); - - uv_ref((uv_handle_t*)&stdout_pipe); - uv_ref((uv_handle_t*)&stdin_pipe); - - r = uv_read_start((uv_stream_t*)&stdin_pipe, on_read_alloc, on_pipe_read); - ASSERT(r == 0); - - uv_run(loop, UV_RUN_DEFAULT); - - ASSERT(after_write_called == 7); - ASSERT(on_pipe_read_called == 1); - ASSERT(close_cb_called == 2); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-tcp-bind-error.c b/libuv/test/test-tcp-bind-error.c deleted file mode 100644 index 10ed68e..0000000 --- a/libuv/test/test-tcp-bind-error.c +++ /dev/null @@ -1,216 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" -#include -#include - - -static int close_cb_called = 0; - - -static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); - close_cb_called++; -} - - -TEST_IMPL(tcp_bind_error_addrinuse) { - struct sockaddr_in addr; - uv_tcp_t server1, server2; - int r; - - ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); - r = uv_tcp_init(uv_default_loop(), &server1); - ASSERT(r == 0); - r = uv_tcp_bind(&server1, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - - r = uv_tcp_init(uv_default_loop(), &server2); - ASSERT(r == 0); - r = uv_tcp_bind(&server2, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - - r = uv_listen((uv_stream_t*)&server1, 128, NULL); - ASSERT(r == 0); - r = uv_listen((uv_stream_t*)&server2, 128, NULL); - ASSERT(r == UV_EADDRINUSE); - - uv_close((uv_handle_t*)&server1, close_cb); - uv_close((uv_handle_t*)&server2, close_cb); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(close_cb_called == 2); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(tcp_bind_error_addrnotavail_1) { - struct sockaddr_in addr; - uv_tcp_t server; - int r; - - ASSERT(0 == uv_ip4_addr("127.255.255.255", TEST_PORT, &addr)); - - r = uv_tcp_init(uv_default_loop(), &server); - ASSERT(r == 0); - - /* It seems that Linux is broken here - bind succeeds. */ - r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0 || r == UV_EADDRNOTAVAIL); - - uv_close((uv_handle_t*)&server, close_cb); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(tcp_bind_error_addrnotavail_2) { - struct sockaddr_in addr; - uv_tcp_t server; - int r; - - ASSERT(0 == uv_ip4_addr("4.4.4.4", TEST_PORT, &addr)); - - r = uv_tcp_init(uv_default_loop(), &server); - ASSERT(r == 0); - r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); - ASSERT(r == UV_EADDRNOTAVAIL); - - uv_close((uv_handle_t*)&server, close_cb); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(tcp_bind_error_fault) { - char garbage[] = - "blah blah blah blah blah blah blah blah blah blah blah blah"; - struct sockaddr_in* garbage_addr; - uv_tcp_t server; - int r; - - garbage_addr = (struct sockaddr_in*) &garbage; - - r = uv_tcp_init(uv_default_loop(), &server); - ASSERT(r == 0); - r = uv_tcp_bind(&server, (const struct sockaddr*) garbage_addr, 0); - ASSERT(r == UV_EINVAL); - - uv_close((uv_handle_t*)&server, close_cb); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -/* Notes: On Linux uv_bind(server, NULL) will segfault the program. */ - -TEST_IMPL(tcp_bind_error_inval) { - struct sockaddr_in addr1; - struct sockaddr_in addr2; - uv_tcp_t server; - int r; - - ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr1)); - ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT_2, &addr2)); - - r = uv_tcp_init(uv_default_loop(), &server); - ASSERT(r == 0); - r = uv_tcp_bind(&server, (const struct sockaddr*) &addr1, 0); - ASSERT(r == 0); - r = uv_tcp_bind(&server, (const struct sockaddr*) &addr2, 0); - ASSERT(r == UV_EINVAL); - - uv_close((uv_handle_t*)&server, close_cb); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(tcp_bind_localhost_ok) { - struct sockaddr_in addr; - uv_tcp_t server; - int r; - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - - r = uv_tcp_init(uv_default_loop(), &server); - ASSERT(r == 0); - r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(tcp_bind_invalid_flags) { - struct sockaddr_in addr; - uv_tcp_t server; - int r; - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - - r = uv_tcp_init(uv_default_loop(), &server); - ASSERT(r == 0); - r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, UV_TCP_IPV6ONLY); - ASSERT(r == UV_EINVAL); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(tcp_listen_without_bind) { - int r; - uv_tcp_t server; - - r = uv_tcp_init(uv_default_loop(), &server); - ASSERT(r == 0); - r = uv_listen((uv_stream_t*)&server, 128, NULL); - ASSERT(r == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-tcp-bind6-error.c b/libuv/test/test-tcp-bind6-error.c deleted file mode 100644 index b762bcb..0000000 --- a/libuv/test/test-tcp-bind6-error.c +++ /dev/null @@ -1,176 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" -#include -#include - - -static int close_cb_called = 0; - - -static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); - close_cb_called++; -} - - -TEST_IMPL(tcp_bind6_error_addrinuse) { - struct sockaddr_in6 addr; - uv_tcp_t server1, server2; - int r; - - if (!can_ipv6()) - RETURN_SKIP("IPv6 not supported"); - - ASSERT(0 == uv_ip6_addr("::", TEST_PORT, &addr)); - - r = uv_tcp_init(uv_default_loop(), &server1); - ASSERT(r == 0); - r = uv_tcp_bind(&server1, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - - r = uv_tcp_init(uv_default_loop(), &server2); - ASSERT(r == 0); - r = uv_tcp_bind(&server2, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - - r = uv_listen((uv_stream_t*)&server1, 128, NULL); - ASSERT(r == 0); - r = uv_listen((uv_stream_t*)&server2, 128, NULL); - ASSERT(r == UV_EADDRINUSE); - - uv_close((uv_handle_t*)&server1, close_cb); - uv_close((uv_handle_t*)&server2, close_cb); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(close_cb_called == 2); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(tcp_bind6_error_addrnotavail) { - struct sockaddr_in6 addr; - uv_tcp_t server; - int r; - - if (!can_ipv6()) - RETURN_SKIP("IPv6 not supported"); - - ASSERT(0 == uv_ip6_addr("4:4:4:4:4:4:4:4", TEST_PORT, &addr)); - - r = uv_tcp_init(uv_default_loop(), &server); - ASSERT(r == 0); - r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); - ASSERT(r == UV_EADDRNOTAVAIL); - - uv_close((uv_handle_t*)&server, close_cb); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(tcp_bind6_error_fault) { - char garbage[] = - "blah blah blah blah blah blah blah blah blah blah blah blah"; - struct sockaddr_in6* garbage_addr; - uv_tcp_t server; - int r; - - if (!can_ipv6()) - RETURN_SKIP("IPv6 not supported"); - - garbage_addr = (struct sockaddr_in6*) &garbage; - - r = uv_tcp_init(uv_default_loop(), &server); - ASSERT(r == 0); - r = uv_tcp_bind(&server, (const struct sockaddr*) garbage_addr, 0); - ASSERT(r == UV_EINVAL); - - uv_close((uv_handle_t*)&server, close_cb); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -/* Notes: On Linux uv_bind6(server, NULL) will segfault the program. */ - -TEST_IMPL(tcp_bind6_error_inval) { - struct sockaddr_in6 addr1; - struct sockaddr_in6 addr2; - uv_tcp_t server; - int r; - - if (!can_ipv6()) - RETURN_SKIP("IPv6 not supported"); - - ASSERT(0 == uv_ip6_addr("::", TEST_PORT, &addr1)); - ASSERT(0 == uv_ip6_addr("::", TEST_PORT_2, &addr2)); - - r = uv_tcp_init(uv_default_loop(), &server); - ASSERT(r == 0); - r = uv_tcp_bind(&server, (const struct sockaddr*) &addr1, 0); - ASSERT(r == 0); - r = uv_tcp_bind(&server, (const struct sockaddr*) &addr2, 0); - ASSERT(r == UV_EINVAL); - - uv_close((uv_handle_t*)&server, close_cb); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(tcp_bind6_localhost_ok) { - struct sockaddr_in6 addr; - uv_tcp_t server; - int r; - - if (!can_ipv6()) - RETURN_SKIP("IPv6 not supported"); - - ASSERT(0 == uv_ip6_addr("::1", TEST_PORT, &addr)); - - r = uv_tcp_init(uv_default_loop(), &server); - ASSERT(r == 0); - r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-tcp-close-accept.c b/libuv/test/test-tcp-close-accept.c deleted file mode 100644 index 5517aaf..0000000 --- a/libuv/test/test-tcp-close-accept.c +++ /dev/null @@ -1,188 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* this test is Unix only */ -#ifndef _WIN32 - -#include "uv.h" -#include "task.h" - -#include -#include - -static struct sockaddr_in addr; -static uv_tcp_t tcp_server; -static uv_tcp_t tcp_outgoing[2]; -static uv_tcp_t tcp_incoming[ARRAY_SIZE(tcp_outgoing)]; -static uv_connect_t connect_reqs[ARRAY_SIZE(tcp_outgoing)]; -static uv_tcp_t tcp_check; -static uv_connect_t tcp_check_req; -static uv_write_t write_reqs[ARRAY_SIZE(tcp_outgoing)]; -static unsigned int got_connections; -static unsigned int close_cb_called; -static unsigned int write_cb_called; -static unsigned int read_cb_called; - -static void close_cb(uv_handle_t* handle) { - close_cb_called++; -} - -static void write_cb(uv_write_t* req, int status) { - ASSERT(status == 0); - write_cb_called++; -} - -static void connect_cb(uv_connect_t* req, int status) { - unsigned int i; - uv_buf_t buf; - uv_stream_t* outgoing; - - if (req == &tcp_check_req) { - ASSERT(status != 0); - - /* Close check and incoming[0], time to finish test */ - uv_close((uv_handle_t*) &tcp_incoming[0], close_cb); - uv_close((uv_handle_t*) &tcp_check, close_cb); - return; - } - - ASSERT(status == 0); - ASSERT(connect_reqs <= req); - ASSERT(req <= connect_reqs + ARRAY_SIZE(connect_reqs)); - i = req - connect_reqs; - - buf = uv_buf_init("x", 1); - outgoing = (uv_stream_t*) &tcp_outgoing[i]; - ASSERT(0 == uv_write(&write_reqs[i], outgoing, &buf, 1, write_cb)); -} - -static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) { - static char slab[1]; - buf->base = slab; - buf->len = sizeof(slab); -} - -static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { - uv_loop_t* loop; - unsigned int i; - - /* Only first stream should receive read events */ - ASSERT(stream == (uv_stream_t*) &tcp_incoming[0]); - ASSERT(0 == uv_read_stop(stream)); - ASSERT(1 == nread); - - loop = stream->loop; - read_cb_called++; - - /* Close all active incomings, except current one */ - for (i = 1; i < got_connections; i++) - uv_close((uv_handle_t*) &tcp_incoming[i], close_cb); - - /* Create new fd that should be one of the closed incomings */ - ASSERT(0 == uv_tcp_init(loop, &tcp_check)); - ASSERT(0 == uv_tcp_connect(&tcp_check_req, - &tcp_check, - (const struct sockaddr*) &addr, - connect_cb)); - ASSERT(0 == uv_read_start((uv_stream_t*) &tcp_check, alloc_cb, read_cb)); - - /* Close server, so no one will connect to it */ - uv_close((uv_handle_t*) &tcp_server, close_cb); -} - -static void connection_cb(uv_stream_t* server, int status) { - unsigned int i; - uv_tcp_t* incoming; - - ASSERT(server == (uv_stream_t*) &tcp_server); - - /* Ignore tcp_check connection */ - if (got_connections == ARRAY_SIZE(tcp_incoming)) - return; - - /* Accept everyone */ - incoming = &tcp_incoming[got_connections++]; - ASSERT(0 == uv_tcp_init(server->loop, incoming)); - ASSERT(0 == uv_accept(server, (uv_stream_t*) incoming)); - - if (got_connections != ARRAY_SIZE(tcp_incoming)) - return; - - /* Once all clients are accepted - start reading */ - for (i = 0; i < ARRAY_SIZE(tcp_incoming); i++) { - incoming = &tcp_incoming[i]; - ASSERT(0 == uv_read_start((uv_stream_t*) incoming, alloc_cb, read_cb)); - } -} - -TEST_IMPL(tcp_close_accept) { - unsigned int i; - uv_loop_t* loop; - uv_tcp_t* client; - - /* - * A little explanation of what goes on below: - * - * We'll create server and connect to it using two clients, each writing one - * byte once connected. - * - * When all clients will be accepted by server - we'll start reading from them - * and, on first client's first byte, will close second client and server. - * After that, we'll immediately initiate new connection to server using - * tcp_check handle (thus, reusing fd from second client). - * - * In this situation uv__io_poll()'s event list should still contain read - * event for second client, and, if not cleaned up properly, `tcp_check` will - * receive stale event of second incoming and invoke `connect_cb` with zero - * status. - */ - - loop = uv_default_loop(); - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - - ASSERT(0 == uv_tcp_init(loop, &tcp_server)); - ASSERT(0 == uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0)); - ASSERT(0 == uv_listen((uv_stream_t*) &tcp_server, - ARRAY_SIZE(tcp_outgoing), - connection_cb)); - - for (i = 0; i < ARRAY_SIZE(tcp_outgoing); i++) { - client = tcp_outgoing + i; - - ASSERT(0 == uv_tcp_init(loop, client)); - ASSERT(0 == uv_tcp_connect(&connect_reqs[i], - client, - (const struct sockaddr*) &addr, - connect_cb)); - } - - uv_run(loop, UV_RUN_DEFAULT); - - ASSERT(ARRAY_SIZE(tcp_outgoing) == got_connections); - ASSERT((ARRAY_SIZE(tcp_outgoing) + 2) == close_cb_called); - ASSERT(ARRAY_SIZE(tcp_outgoing) == write_cb_called); - ASSERT(1 == read_cb_called); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -#endif /* !_WIN32 */ diff --git a/libuv/test/test-tcp-close-while-connecting.c b/libuv/test/test-tcp-close-while-connecting.c deleted file mode 100644 index 0a69a0d..0000000 --- a/libuv/test/test-tcp-close-while-connecting.c +++ /dev/null @@ -1,82 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -static uv_timer_t timer1_handle; -static uv_timer_t timer2_handle; -static uv_tcp_t tcp_handle; - -static int connect_cb_called; -static int timer1_cb_called; -static int close_cb_called; - - -static void close_cb(uv_handle_t* handle) { - close_cb_called++; -} - - -static void connect_cb(uv_connect_t* req, int status) { - ASSERT(status == UV_ECANCELED); - uv_timer_stop(&timer2_handle); - connect_cb_called++; -} - - -static void timer1_cb(uv_timer_t* handle) { - uv_close((uv_handle_t*)handle, close_cb); - uv_close((uv_handle_t*)&tcp_handle, close_cb); - timer1_cb_called++; -} - - -static void timer2_cb(uv_timer_t* handle) { - ASSERT(0 && "should not be called"); -} - - -TEST_IMPL(tcp_close_while_connecting) { - uv_connect_t connect_req; - struct sockaddr_in addr; - uv_loop_t* loop; - - loop = uv_default_loop(); - ASSERT(0 == uv_ip4_addr("1.2.3.4", TEST_PORT, &addr)); - ASSERT(0 == uv_tcp_init(loop, &tcp_handle)); - ASSERT(0 == uv_tcp_connect(&connect_req, - &tcp_handle, - (const struct sockaddr*) &addr, - connect_cb)); - ASSERT(0 == uv_timer_init(loop, &timer1_handle)); - ASSERT(0 == uv_timer_start(&timer1_handle, timer1_cb, 50, 0)); - ASSERT(0 == uv_timer_init(loop, &timer2_handle)); - ASSERT(0 == uv_timer_start(&timer2_handle, timer2_cb, 86400 * 1000, 0)); - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - - ASSERT(connect_cb_called == 1); - ASSERT(timer1_cb_called == 1); - ASSERT(close_cb_called == 2); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-tcp-close.c b/libuv/test/test-tcp-close.c deleted file mode 100644 index e65885a..0000000 --- a/libuv/test/test-tcp-close.c +++ /dev/null @@ -1,136 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include /* memset */ - -#define NUM_WRITE_REQS 32 - -static uv_tcp_t tcp_handle; -static uv_connect_t connect_req; - -static int write_cb_called; -static int close_cb_called; - -static void connect_cb(uv_connect_t* req, int status); -static void write_cb(uv_write_t* req, int status); -static void close_cb(uv_handle_t* handle); - - -static void connect_cb(uv_connect_t* conn_req, int status) { - uv_write_t* req; - uv_buf_t buf; - int i, r; - - buf = uv_buf_init("PING", 4); - for (i = 0; i < NUM_WRITE_REQS; i++) { - req = malloc(sizeof *req); - ASSERT(req != NULL); - - r = uv_write(req, (uv_stream_t*)&tcp_handle, &buf, 1, write_cb); - ASSERT(r == 0); - } - - uv_close((uv_handle_t*)&tcp_handle, close_cb); -} - - -static void write_cb(uv_write_t* req, int status) { - /* write callbacks should run before the close callback */ - ASSERT(close_cb_called == 0); - ASSERT(req->handle == (uv_stream_t*)&tcp_handle); - write_cb_called++; - free(req); -} - - -static void close_cb(uv_handle_t* handle) { - ASSERT(handle == (uv_handle_t*)&tcp_handle); - close_cb_called++; -} - - -static void connection_cb(uv_stream_t* server, int status) { - ASSERT(status == 0); -} - - -static void start_server(uv_loop_t* loop, uv_tcp_t* handle) { - struct sockaddr_in addr; - int r; - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - - r = uv_tcp_init(loop, handle); - ASSERT(r == 0); - - r = uv_tcp_bind(handle, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - - r = uv_listen((uv_stream_t*)handle, 128, connection_cb); - ASSERT(r == 0); - - uv_unref((uv_handle_t*)handle); -} - - -/* Check that pending write requests have their callbacks - * invoked when the handle is closed. - */ -TEST_IMPL(tcp_close) { - struct sockaddr_in addr; - uv_tcp_t tcp_server; - uv_loop_t* loop; - int r; - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - - loop = uv_default_loop(); - - /* We can't use the echo server, it doesn't handle ECONNRESET. */ - start_server(loop, &tcp_server); - - r = uv_tcp_init(loop, &tcp_handle); - ASSERT(r == 0); - - r = uv_tcp_connect(&connect_req, - &tcp_handle, - (const struct sockaddr*) &addr, - connect_cb); - ASSERT(r == 0); - - ASSERT(write_cb_called == 0); - ASSERT(close_cb_called == 0); - - r = uv_run(loop, UV_RUN_DEFAULT); - ASSERT(r == 0); - - printf("%d of %d write reqs seen\n", write_cb_called, NUM_WRITE_REQS); - - ASSERT(write_cb_called == NUM_WRITE_REQS); - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-tcp-connect-error-after-write.c b/libuv/test/test-tcp-connect-error-after-write.c deleted file mode 100644 index 3f2e357..0000000 --- a/libuv/test/test-tcp-connect-error-after-write.c +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include -#include - -static int connect_cb_called; -static int write_cb_called; -static int close_cb_called; - - -static void close_cb(uv_handle_t* handle) { - close_cb_called++; -} - - -static void connect_cb(uv_connect_t* req, int status) { - ASSERT(status < 0); - connect_cb_called++; - uv_close((uv_handle_t*)req->handle, close_cb); -} - - -static void write_cb(uv_write_t* req, int status) { - ASSERT(status < 0); - write_cb_called++; -} - - -/* - * Try to connect to an address on which nothing listens, get ECONNREFUSED - * (uv errno 12) and get connect_cb() called once with status != 0. - * Related issue: https://github.com/joyent/libuv/issues/443 - */ -TEST_IMPL(tcp_connect_error_after_write) { - uv_connect_t connect_req; - struct sockaddr_in addr; - uv_write_t write_req; - uv_tcp_t conn; - uv_buf_t buf; - int r; - -#ifdef _WIN32 - fprintf(stderr, "This test is disabled on Windows for now.\n"); - fprintf(stderr, "See https://github.com/joyent/libuv/issues/444\n"); - return 0; /* windows slackers... */ -#endif - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - buf = uv_buf_init("TEST", 4); - - r = uv_tcp_init(uv_default_loop(), &conn); - ASSERT(r == 0); - - r = uv_write(&write_req, (uv_stream_t*)&conn, &buf, 1, write_cb); - ASSERT(r == UV_EBADF); - - r = uv_tcp_connect(&connect_req, - &conn, - (const struct sockaddr*) &addr, - connect_cb); - ASSERT(r == 0); - - r = uv_write(&write_req, (uv_stream_t*)&conn, &buf, 1, write_cb); - ASSERT(r == 0); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(connect_cb_called == 1); - ASSERT(write_cb_called == 1); - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-tcp-connect-error.c b/libuv/test/test-tcp-connect-error.c deleted file mode 100644 index eab1eeb..0000000 --- a/libuv/test/test-tcp-connect-error.c +++ /dev/null @@ -1,73 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" -#include -#include - - -static int connect_cb_called = 0; -static int close_cb_called = 0; - - - -static void connect_cb(uv_connect_t* handle, int status) { - ASSERT(handle != NULL); - connect_cb_called++; -} - - - -static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); - close_cb_called++; -} - - -TEST_IMPL(tcp_connect_error_fault) { - const char garbage[] = - "blah blah blah blah blah blah blah blah blah blah blah blah"; - const struct sockaddr_in* garbage_addr; - uv_tcp_t server; - int r; - uv_connect_t req; - - garbage_addr = (const struct sockaddr_in*) &garbage; - - r = uv_tcp_init(uv_default_loop(), &server); - ASSERT(r == 0); - r = uv_tcp_connect(&req, - &server, - (const struct sockaddr*) garbage_addr, - connect_cb); - ASSERT(r == UV_EINVAL); - - uv_close((uv_handle_t*)&server, close_cb); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(connect_cb_called == 0); - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-tcp-connect-timeout.c b/libuv/test/test-tcp-connect-timeout.c deleted file mode 100644 index a22c773..0000000 --- a/libuv/test/test-tcp-connect-timeout.c +++ /dev/null @@ -1,89 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" -#include -#include - - -static int connect_cb_called; -static int close_cb_called; - -static uv_connect_t connect_req; -static uv_timer_t timer; -static uv_tcp_t conn; - -static void connect_cb(uv_connect_t* req, int status); -static void timer_cb(uv_timer_t* handle); -static void close_cb(uv_handle_t* handle); - - -static void connect_cb(uv_connect_t* req, int status) { - ASSERT(req == &connect_req); - ASSERT(status == UV_ECANCELED); - connect_cb_called++; -} - - -static void timer_cb(uv_timer_t* handle) { - ASSERT(handle == &timer); - uv_close((uv_handle_t*)&conn, close_cb); - uv_close((uv_handle_t*)&timer, close_cb); -} - - -static void close_cb(uv_handle_t* handle) { - ASSERT(handle == (uv_handle_t*)&conn || handle == (uv_handle_t*)&timer); - close_cb_called++; -} - - -/* Verify that connecting to an unreachable address or port doesn't hang - * the event loop. - */ -TEST_IMPL(tcp_connect_timeout) { - struct sockaddr_in addr; - int r; - - ASSERT(0 == uv_ip4_addr("8.8.8.8", 9999, &addr)); - - r = uv_timer_init(uv_default_loop(), &timer); - ASSERT(r == 0); - - r = uv_timer_start(&timer, timer_cb, 50, 0); - ASSERT(r == 0); - - r = uv_tcp_init(uv_default_loop(), &conn); - ASSERT(r == 0); - - r = uv_tcp_connect(&connect_req, - &conn, - (const struct sockaddr*) &addr, - connect_cb); - ASSERT(r == 0); - - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-tcp-connect6-error.c b/libuv/test/test-tcp-connect6-error.c deleted file mode 100644 index 91ac0a3..0000000 --- a/libuv/test/test-tcp-connect6-error.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" -#include -#include - - -static int connect_cb_called = 0; -static int close_cb_called = 0; - - -static void connect_cb(uv_connect_t* handle, int status) { - ASSERT(handle != NULL); - connect_cb_called++; -} - - -static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); - close_cb_called++; -} - - -TEST_IMPL(tcp_connect6_error_fault) { - const char garbage[] = - "blah blah blah blah blah blah blah blah blah blah blah blah"; - const struct sockaddr_in6* garbage_addr; - uv_tcp_t server; - int r; - uv_connect_t req; - - garbage_addr = (const struct sockaddr_in6*) &garbage; - - r = uv_tcp_init(uv_default_loop(), &server); - ASSERT(r == 0); - r = uv_tcp_connect(&req, - &server, - (const struct sockaddr*) garbage_addr, - connect_cb); - ASSERT(r == UV_EINVAL); - - uv_close((uv_handle_t*)&server, close_cb); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(connect_cb_called == 0); - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-tcp-flags.c b/libuv/test/test-tcp-flags.c deleted file mode 100644 index 68afb39..0000000 --- a/libuv/test/test-tcp-flags.c +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include - - -TEST_IMPL(tcp_flags) { - uv_loop_t* loop; - uv_tcp_t handle; - int r; - - loop = uv_default_loop(); - - r = uv_tcp_init(loop, &handle); - ASSERT(r == 0); - - r = uv_tcp_nodelay(&handle, 1); - ASSERT(r == 0); - - r = uv_tcp_keepalive(&handle, 1, 60); - ASSERT(r == 0); - - uv_close((uv_handle_t*)&handle, NULL); - - r = uv_run(loop, UV_RUN_DEFAULT); - ASSERT(r == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-tcp-open.c b/libuv/test/test-tcp-open.c deleted file mode 100644 index edeacc7..0000000 --- a/libuv/test/test-tcp-open.c +++ /dev/null @@ -1,182 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" -#include -#include -#include - -#ifndef _WIN32 -# include -#endif - -static int shutdown_cb_called = 0; -static int connect_cb_called = 0; -static int write_cb_called = 0; -static int close_cb_called = 0; - -static uv_connect_t connect_req; -static uv_shutdown_t shutdown_req; -static uv_write_t write_req; - - -static void startup(void) { -#ifdef _WIN32 - struct WSAData wsa_data; - int r = WSAStartup(MAKEWORD(2, 2), &wsa_data); - ASSERT(r == 0); -#endif -} - - -static uv_os_sock_t create_tcp_socket(void) { - uv_os_sock_t sock; - - sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); -#ifdef _WIN32 - ASSERT(sock != INVALID_SOCKET); -#else - ASSERT(sock >= 0); -#endif - -#ifndef _WIN32 - { - /* Allow reuse of the port. */ - int yes = 1; - int r = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes); - ASSERT(r == 0); - } -#endif - - return sock; -} - - -static void alloc_cb(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf) { - static char slab[65536]; - ASSERT(suggested_size <= sizeof(slab)); - buf->base = slab; - buf->len = sizeof(slab); -} - - -static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); - close_cb_called++; -} - - -static void shutdown_cb(uv_shutdown_t* req, int status) { - ASSERT(req == &shutdown_req); - ASSERT(status == 0); - - /* Now we wait for the EOF */ - shutdown_cb_called++; -} - - -static void read_cb(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { - ASSERT(tcp != NULL); - - if (nread >= 0) { - ASSERT(nread == 4); - ASSERT(memcmp("PING", buf->base, nread) == 0); - } - else { - ASSERT(nread == UV_EOF); - printf("GOT EOF\n"); - uv_close((uv_handle_t*)tcp, close_cb); - } -} - - -static void write_cb(uv_write_t* req, int status) { - ASSERT(req != NULL); - - if (status) { - fprintf(stderr, "uv_write error: %s\n", uv_strerror(status)); - ASSERT(0); - } - - write_cb_called++; -} - - -static void connect_cb(uv_connect_t* req, int status) { - uv_buf_t buf = uv_buf_init("PING", 4); - uv_stream_t* stream; - int r; - - ASSERT(req == &connect_req); - ASSERT(status == 0); - - stream = req->handle; - connect_cb_called++; - - r = uv_write(&write_req, stream, &buf, 1, write_cb); - ASSERT(r == 0); - - /* Shutdown on drain. */ - r = uv_shutdown(&shutdown_req, stream, shutdown_cb); - ASSERT(r == 0); - - /* Start reading */ - r = uv_read_start(stream, alloc_cb, read_cb); - ASSERT(r == 0); -} - - -TEST_IMPL(tcp_open) { - struct sockaddr_in addr; - uv_tcp_t client; - uv_os_sock_t sock; - int r; - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - - startup(); - sock = create_tcp_socket(); - - r = uv_tcp_init(uv_default_loop(), &client); - ASSERT(r == 0); - - r = uv_tcp_open(&client, sock); - ASSERT(r == 0); - - r = uv_tcp_connect(&connect_req, - &client, - (const struct sockaddr*) &addr, - connect_cb); - ASSERT(r == 0); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(shutdown_cb_called == 1); - ASSERT(connect_cb_called == 1); - ASSERT(write_cb_called == 1); - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-tcp-read-stop.c b/libuv/test/test-tcp-read-stop.c deleted file mode 100644 index 488e8fb..0000000 --- a/libuv/test/test-tcp-read-stop.c +++ /dev/null @@ -1,76 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -static uv_timer_t timer_handle; -static uv_tcp_t tcp_handle; -static uv_write_t write_req; - - -static void fail_cb(void) { - ASSERT(0 && "fail_cb called"); -} - - -static void write_cb(uv_write_t* req, int status) { - uv_close((uv_handle_t*) &timer_handle, NULL); - uv_close((uv_handle_t*) &tcp_handle, NULL); -} - - -static void timer_cb(uv_timer_t* handle) { - uv_buf_t buf = uv_buf_init("PING", 4); - ASSERT(0 == uv_write(&write_req, - (uv_stream_t*) &tcp_handle, - &buf, - 1, - write_cb)); - ASSERT(0 == uv_read_stop((uv_stream_t*) &tcp_handle)); -} - - -static void connect_cb(uv_connect_t* req, int status) { - ASSERT(0 == status); - ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 50, 0)); - ASSERT(0 == uv_read_start((uv_stream_t*) &tcp_handle, - (uv_alloc_cb) fail_cb, - (uv_read_cb) fail_cb)); -} - - -TEST_IMPL(tcp_read_stop) { - uv_connect_t connect_req; - struct sockaddr_in addr; - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - ASSERT(0 == uv_timer_init(uv_default_loop(), &timer_handle)); - ASSERT(0 == uv_tcp_init(uv_default_loop(), &tcp_handle)); - ASSERT(0 == uv_tcp_connect(&connect_req, - &tcp_handle, - (const struct sockaddr*) &addr, - connect_cb)); - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); - MAKE_VALGRIND_HAPPY(); - - return 0; -} diff --git a/libuv/test/test-tcp-shutdown-after-write.c b/libuv/test/test-tcp-shutdown-after-write.c deleted file mode 100644 index 463b4b0..0000000 --- a/libuv/test/test-tcp-shutdown-after-write.c +++ /dev/null @@ -1,138 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -static void write_cb(uv_write_t* req, int status); -static void shutdown_cb(uv_shutdown_t* req, int status); - -static uv_tcp_t conn; -static uv_timer_t timer; -static uv_connect_t connect_req; -static uv_write_t write_req; -static uv_shutdown_t shutdown_req; - -static int connect_cb_called; -static int write_cb_called; -static int shutdown_cb_called; - -static int conn_close_cb_called; -static int timer_close_cb_called; - - -static void close_cb(uv_handle_t* handle) { - if (handle == (uv_handle_t*)&conn) - conn_close_cb_called++; - else if (handle == (uv_handle_t*)&timer) - timer_close_cb_called++; - else - ASSERT(0 && "bad handle in close_cb"); -} - - -static void alloc_cb(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf) { - static char slab[64]; - buf->base = slab; - buf->len = sizeof(slab); -} - - -static void timer_cb(uv_timer_t* handle) { - uv_buf_t buf; - int r; - - uv_close((uv_handle_t*)handle, close_cb); - - buf = uv_buf_init("TEST", 4); - r = uv_write(&write_req, (uv_stream_t*)&conn, &buf, 1, write_cb); - ASSERT(r == 0); - - r = uv_shutdown(&shutdown_req, (uv_stream_t*)&conn, shutdown_cb); - ASSERT(r == 0); -} - - -static void read_cb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { -} - - -static void connect_cb(uv_connect_t* req, int status) { - int r; - - ASSERT(status == 0); - connect_cb_called++; - - r = uv_read_start((uv_stream_t*)&conn, alloc_cb, read_cb); - ASSERT(r == 0); -} - - -static void write_cb(uv_write_t* req, int status) { - ASSERT(status == 0); - write_cb_called++; -} - - -static void shutdown_cb(uv_shutdown_t* req, int status) { - ASSERT(status == 0); - shutdown_cb_called++; - uv_close((uv_handle_t*)&conn, close_cb); -} - - -TEST_IMPL(tcp_shutdown_after_write) { - struct sockaddr_in addr; - uv_loop_t* loop; - int r; - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - loop = uv_default_loop(); - - r = uv_timer_init(loop, &timer); - ASSERT(r == 0); - - r = uv_timer_start(&timer, timer_cb, 125, 0); - ASSERT(r == 0); - - r = uv_tcp_init(loop, &conn); - ASSERT(r == 0); - - r = uv_tcp_connect(&connect_req, - &conn, - (const struct sockaddr*) &addr, - connect_cb); - ASSERT(r == 0); - - r = uv_run(loop, UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(connect_cb_called == 1); - ASSERT(write_cb_called == 1); - ASSERT(shutdown_cb_called == 1); - ASSERT(conn_close_cb_called == 1); - ASSERT(timer_close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-tcp-try-write.c b/libuv/test/test-tcp-try-write.c deleted file mode 100644 index 8a60136..0000000 --- a/libuv/test/test-tcp-try-write.c +++ /dev/null @@ -1,130 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include -#include - -#define MAX_BYTES 1024 * 1024 - -static uv_tcp_t server; -static uv_tcp_t client; -static uv_tcp_t incoming; -static int connect_cb_called; -static int close_cb_called; -static int connection_cb_called; -static int bytes_read; -static int bytes_written; - - -static void close_cb(uv_handle_t* handle) { - close_cb_called++; -} - - -static void connect_cb(uv_connect_t* req, int status) { - int r; - uv_buf_t buf; - ASSERT(status == 0); - connect_cb_called++; - - do { - buf = uv_buf_init("PING", 4); - r = uv_try_write((uv_stream_t*) &client, &buf, 1); - ASSERT(r > 0 || r == UV_EAGAIN); - if (r > 0) { - bytes_written += r; - break; - } - } while (1); - uv_close((uv_handle_t*) &client, close_cb); -} - - -static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) { - static char base[1024]; - - buf->base = base; - buf->len = sizeof(base); -} - - -static void read_cb(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { - if (nread < 0) { - uv_close((uv_handle_t*) tcp, close_cb); - uv_close((uv_handle_t*) &server, close_cb); - return; - } - - bytes_read += nread; -} - - -static void connection_cb(uv_stream_t* tcp, int status) { - ASSERT(status == 0); - - ASSERT(0 == uv_tcp_init(tcp->loop, &incoming)); - ASSERT(0 == uv_accept(tcp, (uv_stream_t*) &incoming)); - - connection_cb_called++; - ASSERT(0 == uv_read_start((uv_stream_t*) &incoming, alloc_cb, read_cb)); -} - - -static void start_server(void) { - struct sockaddr_in addr; - - ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); - - ASSERT(0 == uv_tcp_init(uv_default_loop(), &server)); - ASSERT(0 == uv_tcp_bind(&server, (struct sockaddr*) &addr, 0)); - ASSERT(0 == uv_listen((uv_stream_t*) &server, 128, connection_cb)); -} - - -TEST_IMPL(tcp_try_write) { - uv_connect_t connect_req; - struct sockaddr_in addr; - - start_server(); - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - - ASSERT(0 == uv_tcp_init(uv_default_loop(), &client)); - ASSERT(0 == uv_tcp_connect(&connect_req, - &client, - (struct sockaddr*) &addr, - connect_cb)); - - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); - - ASSERT(connect_cb_called == 1); - ASSERT(close_cb_called == 3); - ASSERT(connection_cb_called == 1); - ASSERT(bytes_read == bytes_written); - ASSERT(bytes_written > 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-tcp-unexpected-read.c b/libuv/test/test-tcp-unexpected-read.c deleted file mode 100644 index c7b9814..0000000 --- a/libuv/test/test-tcp-unexpected-read.c +++ /dev/null @@ -1,117 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -static uv_check_t check_handle; -static uv_timer_t timer_handle; -static uv_tcp_t server_handle; -static uv_tcp_t client_handle; -static uv_tcp_t peer_handle; -static uv_write_t write_req; -static uv_connect_t connect_req; - -static unsigned long ticks; /* event loop ticks */ - - -static void check_cb(uv_check_t* handle) { - ticks++; -} - - -static void timer_cb(uv_timer_t* handle) { - uv_close((uv_handle_t*) &check_handle, NULL); - uv_close((uv_handle_t*) &timer_handle, NULL); - uv_close((uv_handle_t*) &server_handle, NULL); - uv_close((uv_handle_t*) &client_handle, NULL); - uv_close((uv_handle_t*) &peer_handle, NULL); -} - - -static void alloc_cb(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf) { - ASSERT(0 && "alloc_cb should not have been called"); -} - - -static void read_cb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { - ASSERT(0 && "read_cb should not have been called"); -} - - -static void connect_cb(uv_connect_t* req, int status) { - ASSERT(req->handle == (uv_stream_t*) &client_handle); - ASSERT(0 == status); -} - - -static void write_cb(uv_write_t* req, int status) { - ASSERT(req->handle == (uv_stream_t*) &peer_handle); - ASSERT(0 == status); -} - - -static void connection_cb(uv_stream_t* handle, int status) { - uv_buf_t buf; - - buf = uv_buf_init("PING", 4); - - ASSERT(0 == status); - ASSERT(0 == uv_accept(handle, (uv_stream_t*) &peer_handle)); - ASSERT(0 == uv_read_start((uv_stream_t*) &peer_handle, alloc_cb, read_cb)); - ASSERT(0 == uv_write(&write_req, (uv_stream_t*) &peer_handle, - &buf, 1, write_cb)); -} - - -TEST_IMPL(tcp_unexpected_read) { - struct sockaddr_in addr; - uv_loop_t* loop; - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - loop = uv_default_loop(); - - ASSERT(0 == uv_timer_init(loop, &timer_handle)); - ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 1000, 0)); - ASSERT(0 == uv_check_init(loop, &check_handle)); - ASSERT(0 == uv_check_start(&check_handle, check_cb)); - ASSERT(0 == uv_tcp_init(loop, &server_handle)); - ASSERT(0 == uv_tcp_init(loop, &client_handle)); - ASSERT(0 == uv_tcp_init(loop, &peer_handle)); - ASSERT(0 == uv_tcp_bind(&server_handle, (const struct sockaddr*) &addr, 0)); - ASSERT(0 == uv_listen((uv_stream_t*) &server_handle, 1, connection_cb)); - ASSERT(0 == uv_tcp_connect(&connect_req, - &client_handle, - (const struct sockaddr*) &addr, - connect_cb)); - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - - /* This is somewhat inexact but the idea is that the event loop should not - * start busy looping when the server sends a message and the client isn't - * reading. - */ - ASSERT(ticks <= 20); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-tcp-write-after-connect.c b/libuv/test/test-tcp-write-after-connect.c deleted file mode 100644 index aa03228..0000000 --- a/libuv/test/test-tcp-write-after-connect.c +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef _WIN32 - -#include "uv.h" -#include "task.h" - -uv_loop_t loop; -uv_tcp_t tcp_client; -uv_connect_t connection_request; -uv_write_t write_request; -uv_buf_t buf = { "HELLO", 4 }; - - -static void write_cb(uv_write_t *req, int status) { - ASSERT(status == UV_ECANCELED); - uv_close((uv_handle_t*) req->handle, NULL); -} - - -static void connect_cb(uv_connect_t *req, int status) { - ASSERT(status == UV_ECONNREFUSED); -} - - -TEST_IMPL(tcp_write_after_connect) { - struct sockaddr_in sa; - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &sa)); - ASSERT(0 == uv_loop_init(&loop)); - ASSERT(0 == uv_tcp_init(&loop, &tcp_client)); - - ASSERT(0 == uv_tcp_connect(&connection_request, - &tcp_client, - (const struct sockaddr *) - &sa, - connect_cb)); - - ASSERT(0 == uv_write(&write_request, - (uv_stream_t *)&tcp_client, - &buf, 1, - write_cb)); - - uv_run(&loop, UV_RUN_DEFAULT); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -#endif diff --git a/libuv/test/test-tcp-write-queue-order.c b/libuv/test/test-tcp-write-queue-order.c deleted file mode 100644 index aa4d2ac..0000000 --- a/libuv/test/test-tcp-write-queue-order.c +++ /dev/null @@ -1,137 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include - -#include "uv.h" -#include "task.h" - -#define REQ_COUNT 10000 - -static uv_timer_t timer; -static uv_tcp_t server; -static uv_tcp_t client; -static uv_tcp_t incoming; -static int connect_cb_called; -static int close_cb_called; -static int connection_cb_called; -static int write_callbacks; -static int write_cancelled_callbacks; -static int write_error_callbacks; - -static uv_write_t write_requests[REQ_COUNT]; - - -static void close_cb(uv_handle_t* handle) { - close_cb_called++; -} - -void timer_cb(uv_timer_t* handle) { - uv_close((uv_handle_t*) &client, close_cb); - uv_close((uv_handle_t*) &server, close_cb); - uv_close((uv_handle_t*) &incoming, close_cb); -} - -void write_cb(uv_write_t* req, int status) { - if (status == 0) - write_callbacks++; - else if (status == UV_ECANCELED) - write_cancelled_callbacks++; - else - write_error_callbacks++; -} - -static void connect_cb(uv_connect_t* req, int status) { - static char base[1024]; - int r; - int i; - uv_buf_t buf; - - ASSERT(status == 0); - connect_cb_called++; - - buf = uv_buf_init(base, sizeof(base)); - - for (i = 0; i < REQ_COUNT; i++) { - r = uv_write(&write_requests[i], - req->handle, - &buf, - 1, - write_cb); - ASSERT(r == 0); - } -} - - -static void connection_cb(uv_stream_t* tcp, int status) { - ASSERT(status == 0); - - ASSERT(0 == uv_tcp_init(tcp->loop, &incoming)); - ASSERT(0 == uv_accept(tcp, (uv_stream_t*) &incoming)); - - connection_cb_called++; -} - - -static void start_server(void) { - struct sockaddr_in addr; - - ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); - - ASSERT(0 == uv_tcp_init(uv_default_loop(), &server)); - ASSERT(0 == uv_tcp_bind(&server, (struct sockaddr*) &addr, 0)); - ASSERT(0 == uv_listen((uv_stream_t*) &server, 128, connection_cb)); -} - - -TEST_IMPL(tcp_write_queue_order) { - uv_connect_t connect_req; - struct sockaddr_in addr; - - start_server(); - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - - ASSERT(0 == uv_tcp_init(uv_default_loop(), &client)); - ASSERT(0 == uv_tcp_connect(&connect_req, - &client, - (struct sockaddr*) &addr, - connect_cb)); - - ASSERT(0 == uv_timer_init(uv_default_loop(), &timer)); - ASSERT(0 == uv_timer_start(&timer, timer_cb, 100, 0)); - - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); - - ASSERT(connect_cb_called == 1); - ASSERT(connection_cb_called == 1); - ASSERT(write_callbacks > 0); - ASSERT(write_cancelled_callbacks > 0); - ASSERT(write_callbacks + - write_error_callbacks + - write_cancelled_callbacks == REQ_COUNT); - ASSERT(close_cb_called == 3); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-tcp-write-to-half-open-connection.c b/libuv/test/test-tcp-write-to-half-open-connection.c deleted file mode 100644 index 2fa2ae7..0000000 --- a/libuv/test/test-tcp-write-to-half-open-connection.c +++ /dev/null @@ -1,141 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include -#include - -static void connection_cb(uv_stream_t* server, int status); -static void connect_cb(uv_connect_t* req, int status); -static void write_cb(uv_write_t* req, int status); -static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf); -static void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf); - -static uv_tcp_t tcp_server; -static uv_tcp_t tcp_client; -static uv_tcp_t tcp_peer; /* client socket as accept()-ed by server */ -static uv_connect_t connect_req; -static uv_write_t write_req; - -static int write_cb_called; -static int read_cb_called; - -static void connection_cb(uv_stream_t* server, int status) { - int r; - uv_buf_t buf; - - ASSERT(server == (uv_stream_t*)&tcp_server); - ASSERT(status == 0); - - r = uv_tcp_init(server->loop, &tcp_peer); - ASSERT(r == 0); - - r = uv_accept(server, (uv_stream_t*)&tcp_peer); - ASSERT(r == 0); - - r = uv_read_start((uv_stream_t*)&tcp_peer, alloc_cb, read_cb); - ASSERT(r == 0); - - buf.base = "hello\n"; - buf.len = 6; - - r = uv_write(&write_req, (uv_stream_t*)&tcp_peer, &buf, 1, write_cb); - ASSERT(r == 0); -} - - -static void alloc_cb(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf) { - static char slab[1024]; - buf->base = slab; - buf->len = sizeof(slab); -} - - -static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { - if (nread < 0) { - fprintf(stderr, "read_cb error: %s\n", uv_err_name(nread)); - ASSERT(nread == UV_ECONNRESET || nread == UV_EOF); - - uv_close((uv_handle_t*)&tcp_server, NULL); - uv_close((uv_handle_t*)&tcp_peer, NULL); - } - - read_cb_called++; -} - - -static void connect_cb(uv_connect_t* req, int status) { - ASSERT(req == &connect_req); - ASSERT(status == 0); - - /* Close the client. */ - uv_close((uv_handle_t*)&tcp_client, NULL); -} - - -static void write_cb(uv_write_t* req, int status) { - ASSERT(status == 0); - write_cb_called++; -} - - -TEST_IMPL(tcp_write_to_half_open_connection) { - struct sockaddr_in addr; - uv_loop_t* loop; - int r; - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - - loop = uv_default_loop(); - ASSERT(loop != NULL); - - r = uv_tcp_init(loop, &tcp_server); - ASSERT(r == 0); - - r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - - r = uv_listen((uv_stream_t*)&tcp_server, 1, connection_cb); - ASSERT(r == 0); - - r = uv_tcp_init(loop, &tcp_client); - ASSERT(r == 0); - - r = uv_tcp_connect(&connect_req, - &tcp_client, - (const struct sockaddr*) &addr, - connect_cb); - ASSERT(r == 0); - - r = uv_run(loop, UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(write_cb_called > 0); - ASSERT(read_cb_called > 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-tcp-writealot.c b/libuv/test/test-tcp-writealot.c deleted file mode 100644 index 6cfe2eb..0000000 --- a/libuv/test/test-tcp-writealot.c +++ /dev/null @@ -1,176 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" -#include -#include - - -#define WRITES 3 -#define CHUNKS_PER_WRITE 4096 -#define CHUNK_SIZE 10024 /* 10 kb */ - -#define TOTAL_BYTES (WRITES * CHUNKS_PER_WRITE * CHUNK_SIZE) - -static char* send_buffer; - -static int shutdown_cb_called = 0; -static int connect_cb_called = 0; -static int write_cb_called = 0; -static int close_cb_called = 0; -static size_t bytes_sent = 0; -static size_t bytes_sent_done = 0; -static size_t bytes_received_done = 0; - -static uv_connect_t connect_req; -static uv_shutdown_t shutdown_req; -static uv_write_t write_reqs[WRITES]; - - -static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) { - buf->base = malloc(size); - buf->len = size; -} - - -static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); - close_cb_called++; -} - - -static void shutdown_cb(uv_shutdown_t* req, int status) { - uv_tcp_t* tcp; - - ASSERT(req == &shutdown_req); - ASSERT(status == 0); - - tcp = (uv_tcp_t*)(req->handle); - - /* The write buffer should be empty by now. */ - ASSERT(tcp->write_queue_size == 0); - - /* Now we wait for the EOF */ - shutdown_cb_called++; - - /* We should have had all the writes called already. */ - ASSERT(write_cb_called == WRITES); -} - - -static void read_cb(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { - ASSERT(tcp != NULL); - - if (nread >= 0) { - bytes_received_done += nread; - } - else { - ASSERT(nread == UV_EOF); - printf("GOT EOF\n"); - uv_close((uv_handle_t*)tcp, close_cb); - } - - free(buf->base); -} - - -static void write_cb(uv_write_t* req, int status) { - ASSERT(req != NULL); - - if (status) { - fprintf(stderr, "uv_write error: %s\n", uv_strerror(status)); - ASSERT(0); - } - - bytes_sent_done += CHUNKS_PER_WRITE * CHUNK_SIZE; - write_cb_called++; -} - - -static void connect_cb(uv_connect_t* req, int status) { - uv_buf_t send_bufs[CHUNKS_PER_WRITE]; - uv_stream_t* stream; - int i, j, r; - - ASSERT(req == &connect_req); - ASSERT(status == 0); - - stream = req->handle; - connect_cb_called++; - - /* Write a lot of data */ - for (i = 0; i < WRITES; i++) { - uv_write_t* write_req = write_reqs + i; - - for (j = 0; j < CHUNKS_PER_WRITE; j++) { - send_bufs[j] = uv_buf_init(send_buffer + bytes_sent, CHUNK_SIZE); - bytes_sent += CHUNK_SIZE; - } - - r = uv_write(write_req, stream, send_bufs, CHUNKS_PER_WRITE, write_cb); - ASSERT(r == 0); - } - - /* Shutdown on drain. */ - r = uv_shutdown(&shutdown_req, stream, shutdown_cb); - ASSERT(r == 0); - - /* Start reading */ - r = uv_read_start(stream, alloc_cb, read_cb); - ASSERT(r == 0); -} - - -TEST_IMPL(tcp_writealot) { - struct sockaddr_in addr; - uv_tcp_t client; - int r; - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - - send_buffer = calloc(1, TOTAL_BYTES); - ASSERT(send_buffer != NULL); - - r = uv_tcp_init(uv_default_loop(), &client); - ASSERT(r == 0); - - r = uv_tcp_connect(&connect_req, - &client, - (const struct sockaddr*) &addr, - connect_cb); - ASSERT(r == 0); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(shutdown_cb_called == 1); - ASSERT(connect_cb_called == 1); - ASSERT(write_cb_called == WRITES); - ASSERT(close_cb_called == 1); - ASSERT(bytes_sent == TOTAL_BYTES); - ASSERT(bytes_sent_done == TOTAL_BYTES); - ASSERT(bytes_received_done == TOTAL_BYTES); - - free(send_buffer); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-thread-equal.c b/libuv/test/test-thread-equal.c deleted file mode 100644 index 27c07ee..0000000 --- a/libuv/test/test-thread-equal.c +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -uv_thread_t main_thread_id; -uv_thread_t subthreads[2]; - -static void check_thread(void* arg) { - uv_thread_t *thread_id = arg; - uv_thread_t self_id = uv_thread_self(); - ASSERT(uv_thread_equal(&main_thread_id, &self_id) == 0); - *thread_id = uv_thread_self(); -} - -TEST_IMPL(thread_equal) { - uv_thread_t threads[2]; - main_thread_id = uv_thread_self(); - ASSERT(0 != uv_thread_equal(&main_thread_id, &main_thread_id)); - ASSERT(0 == uv_thread_create(threads + 0, check_thread, subthreads + 0)); - ASSERT(0 == uv_thread_create(threads + 1, check_thread, subthreads + 1)); - ASSERT(0 == uv_thread_join(threads + 0)); - ASSERT(0 == uv_thread_join(threads + 1)); - ASSERT(0 == uv_thread_equal(subthreads + 0, subthreads + 1)); - return 0; -} diff --git a/libuv/test/test-thread.c b/libuv/test/test-thread.c deleted file mode 100644 index 7f3321a..0000000 --- a/libuv/test/test-thread.c +++ /dev/null @@ -1,211 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include -#include /* memset */ - -struct getaddrinfo_req { - uv_thread_t thread_id; - unsigned int counter; - uv_loop_t* loop; - uv_getaddrinfo_t handle; -}; - - -struct fs_req { - uv_thread_t thread_id; - unsigned int counter; - uv_loop_t* loop; - uv_fs_t handle; -}; - - -struct test_thread { - uv_thread_t thread_id; - volatile int thread_called; -}; - -static void getaddrinfo_do(struct getaddrinfo_req* req); -static void getaddrinfo_cb(uv_getaddrinfo_t* handle, - int status, - struct addrinfo* res); -static void fs_do(struct fs_req* req); -static void fs_cb(uv_fs_t* handle); - -static volatile int thread_called; -static uv_key_t tls_key; - - -static void getaddrinfo_do(struct getaddrinfo_req* req) { - int r; - - r = uv_getaddrinfo(req->loop, - &req->handle, - getaddrinfo_cb, - "localhost", - NULL, - NULL); - ASSERT(r == 0); -} - - -static void getaddrinfo_cb(uv_getaddrinfo_t* handle, - int status, - struct addrinfo* res) { - struct getaddrinfo_req* req; - - ASSERT(status == 0); - - req = container_of(handle, struct getaddrinfo_req, handle); - uv_freeaddrinfo(res); - - if (--req->counter) - getaddrinfo_do(req); -} - - -static void fs_do(struct fs_req* req) { - int r; - - r = uv_fs_stat(req->loop, &req->handle, ".", fs_cb); - ASSERT(r == 0); -} - - -static void fs_cb(uv_fs_t* handle) { - struct fs_req* req = container_of(handle, struct fs_req, handle); - - uv_fs_req_cleanup(handle); - - if (--req->counter) - fs_do(req); -} - - -static void do_work(void* arg) { - struct getaddrinfo_req getaddrinfo_reqs[16]; - struct fs_req fs_reqs[16]; - uv_loop_t* loop; - size_t i; - int r; - struct test_thread* thread = arg; - - loop = malloc(sizeof *loop); - ASSERT(loop != NULL); - ASSERT(0 == uv_loop_init(loop)); - - for (i = 0; i < ARRAY_SIZE(getaddrinfo_reqs); i++) { - struct getaddrinfo_req* req = getaddrinfo_reqs + i; - req->counter = 16; - req->loop = loop; - getaddrinfo_do(req); - } - - for (i = 0; i < ARRAY_SIZE(fs_reqs); i++) { - struct fs_req* req = fs_reqs + i; - req->counter = 16; - req->loop = loop; - fs_do(req); - } - - r = uv_run(loop, UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(0 == uv_loop_close(loop)); - free(loop); - thread->thread_called = 1; -} - - -static void thread_entry(void* arg) { - ASSERT(arg == (void *) 42); - thread_called++; -} - - -TEST_IMPL(thread_create) { - uv_thread_t tid; - int r; - - r = uv_thread_create(&tid, thread_entry, (void *) 42); - ASSERT(r == 0); - - r = uv_thread_join(&tid); - ASSERT(r == 0); - - ASSERT(thread_called == 1); - - return 0; -} - - -/* Hilariously bad test name. Run a lot of tasks in the thread pool and verify - * that each "finished" callback is run in its originating thread. - */ -TEST_IMPL(threadpool_multiple_event_loops) { - struct test_thread threads[8]; - size_t i; - int r; - - memset(threads, 0, sizeof(threads)); - - for (i = 0; i < ARRAY_SIZE(threads); i++) { - r = uv_thread_create(&threads[i].thread_id, do_work, &threads[i]); - ASSERT(r == 0); - } - - for (i = 0; i < ARRAY_SIZE(threads); i++) { - r = uv_thread_join(&threads[i].thread_id); - ASSERT(r == 0); - ASSERT(threads[i].thread_called); - } - - return 0; -} - - -static void tls_thread(void* arg) { - ASSERT(NULL == uv_key_get(&tls_key)); - uv_key_set(&tls_key, arg); - ASSERT(arg == uv_key_get(&tls_key)); - uv_key_set(&tls_key, NULL); - ASSERT(NULL == uv_key_get(&tls_key)); -} - - -TEST_IMPL(thread_local_storage) { - char name[] = "main"; - uv_thread_t threads[2]; - ASSERT(0 == uv_key_create(&tls_key)); - ASSERT(NULL == uv_key_get(&tls_key)); - uv_key_set(&tls_key, name); - ASSERT(name == uv_key_get(&tls_key)); - ASSERT(0 == uv_thread_create(threads + 0, tls_thread, threads + 0)); - ASSERT(0 == uv_thread_create(threads + 1, tls_thread, threads + 1)); - ASSERT(0 == uv_thread_join(threads + 0)); - ASSERT(0 == uv_thread_join(threads + 1)); - uv_key_delete(&tls_key); - return 0; -} diff --git a/libuv/test/test-threadpool-cancel.c b/libuv/test/test-threadpool-cancel.c deleted file mode 100644 index f999cba..0000000 --- a/libuv/test/test-threadpool-cancel.c +++ /dev/null @@ -1,359 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#define INIT_CANCEL_INFO(ci, what) \ - do { \ - (ci)->reqs = (what); \ - (ci)->nreqs = ARRAY_SIZE(what); \ - (ci)->stride = sizeof((what)[0]); \ - } \ - while (0) - -struct cancel_info { - void* reqs; - unsigned nreqs; - unsigned stride; - uv_timer_t timer_handle; -}; - -static uv_cond_t signal_cond; -static uv_mutex_t signal_mutex; -static uv_mutex_t wait_mutex; -static unsigned num_threads; -static unsigned fs_cb_called; -static unsigned work_cb_called; -static unsigned done_cb_called; -static unsigned done2_cb_called; -static unsigned timer_cb_called; - - -static void work_cb(uv_work_t* req) { - uv_mutex_lock(&signal_mutex); - uv_cond_signal(&signal_cond); - uv_mutex_unlock(&signal_mutex); - - uv_mutex_lock(&wait_mutex); - uv_mutex_unlock(&wait_mutex); - - work_cb_called++; -} - - -static void done_cb(uv_work_t* req, int status) { - done_cb_called++; - free(req); -} - - -static void saturate_threadpool(void) { - uv_work_t* req; - - ASSERT(0 == uv_cond_init(&signal_cond)); - ASSERT(0 == uv_mutex_init(&signal_mutex)); - ASSERT(0 == uv_mutex_init(&wait_mutex)); - - uv_mutex_lock(&signal_mutex); - uv_mutex_lock(&wait_mutex); - - for (num_threads = 0; /* empty */; num_threads++) { - req = malloc(sizeof(*req)); - ASSERT(req != NULL); - ASSERT(0 == uv_queue_work(uv_default_loop(), req, work_cb, done_cb)); - - /* Expect to get signalled within 350 ms, otherwise assume that - * the thread pool is saturated. As with any timing dependent test, - * this is obviously not ideal. - */ - if (uv_cond_timedwait(&signal_cond, - &signal_mutex, - (uint64_t) (350 * 1e6))) { - ASSERT(0 == uv_cancel((uv_req_t*) req)); - break; - } - } -} - - -static void unblock_threadpool(void) { - uv_mutex_unlock(&signal_mutex); - uv_mutex_unlock(&wait_mutex); -} - - -static void cleanup_threadpool(void) { - ASSERT(done_cb_called == num_threads + 1); /* +1 == cancelled work req. */ - ASSERT(work_cb_called == num_threads); - - uv_cond_destroy(&signal_cond); - uv_mutex_destroy(&signal_mutex); - uv_mutex_destroy(&wait_mutex); -} - - -static void fs_cb(uv_fs_t* req) { - ASSERT(req->result == UV_ECANCELED); - uv_fs_req_cleanup(req); - fs_cb_called++; -} - - -static void getaddrinfo_cb(uv_getaddrinfo_t* req, - int status, - struct addrinfo* res) { - ASSERT(status == UV_EAI_CANCELED); - ASSERT(res == NULL); - uv_freeaddrinfo(res); /* Should not crash. */ -} - - -static void getnameinfo_cb(uv_getnameinfo_t* handle, - int status, - const char* hostname, - const char* service) { - ASSERT(status == UV_EAI_CANCELED); - ASSERT(hostname == NULL); - ASSERT(service == NULL); -} - - -static void work2_cb(uv_work_t* req) { - ASSERT(0 && "work2_cb called"); -} - - -static void done2_cb(uv_work_t* req, int status) { - ASSERT(status == UV_ECANCELED); - done2_cb_called++; -} - - -static void timer_cb(uv_timer_t* handle) { - struct cancel_info* ci; - uv_req_t* req; - unsigned i; - - ci = container_of(handle, struct cancel_info, timer_handle); - - for (i = 0; i < ci->nreqs; i++) { - req = (uv_req_t*) ((char*) ci->reqs + i * ci->stride); - ASSERT(0 == uv_cancel(req)); - } - - uv_close((uv_handle_t*) &ci->timer_handle, NULL); - unblock_threadpool(); - timer_cb_called++; -} - - -static void nop_work_cb(uv_work_t* req) { -} - - -static void nop_done_cb(uv_work_t* req, int status) { - req->data = "OK"; -} - - -TEST_IMPL(threadpool_cancel_getaddrinfo) { - uv_getaddrinfo_t reqs[4]; - struct cancel_info ci; - struct addrinfo hints; - uv_loop_t* loop; - int r; - - INIT_CANCEL_INFO(&ci, reqs); - loop = uv_default_loop(); - saturate_threadpool(); - - r = uv_getaddrinfo(loop, reqs + 0, getaddrinfo_cb, "fail", NULL, NULL); - ASSERT(r == 0); - - r = uv_getaddrinfo(loop, reqs + 1, getaddrinfo_cb, NULL, "fail", NULL); - ASSERT(r == 0); - - r = uv_getaddrinfo(loop, reqs + 2, getaddrinfo_cb, "fail", "fail", NULL); - ASSERT(r == 0); - - r = uv_getaddrinfo(loop, reqs + 3, getaddrinfo_cb, "fail", NULL, &hints); - ASSERT(r == 0); - - ASSERT(0 == uv_timer_init(loop, &ci.timer_handle)); - ASSERT(0 == uv_timer_start(&ci.timer_handle, timer_cb, 10, 0)); - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - ASSERT(1 == timer_cb_called); - - cleanup_threadpool(); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(threadpool_cancel_getnameinfo) { - uv_getnameinfo_t reqs[4]; - struct sockaddr_in addr4; - struct cancel_info ci; - uv_loop_t* loop; - int r; - - r = uv_ip4_addr("127.0.0.1", 80, &addr4); - ASSERT(r == 0); - - INIT_CANCEL_INFO(&ci, reqs); - loop = uv_default_loop(); - saturate_threadpool(); - - r = uv_getnameinfo(loop, reqs + 0, getnameinfo_cb, (const struct sockaddr*)&addr4, 0); - ASSERT(r == 0); - - r = uv_getnameinfo(loop, reqs + 1, getnameinfo_cb, (const struct sockaddr*)&addr4, 0); - ASSERT(r == 0); - - r = uv_getnameinfo(loop, reqs + 2, getnameinfo_cb, (const struct sockaddr*)&addr4, 0); - ASSERT(r == 0); - - r = uv_getnameinfo(loop, reqs + 3, getnameinfo_cb, (const struct sockaddr*)&addr4, 0); - ASSERT(r == 0); - - ASSERT(0 == uv_timer_init(loop, &ci.timer_handle)); - ASSERT(0 == uv_timer_start(&ci.timer_handle, timer_cb, 10, 0)); - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - ASSERT(1 == timer_cb_called); - - cleanup_threadpool(); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(threadpool_cancel_work) { - struct cancel_info ci; - uv_work_t reqs[16]; - uv_loop_t* loop; - unsigned i; - - INIT_CANCEL_INFO(&ci, reqs); - loop = uv_default_loop(); - saturate_threadpool(); - - for (i = 0; i < ARRAY_SIZE(reqs); i++) - ASSERT(0 == uv_queue_work(loop, reqs + i, work2_cb, done2_cb)); - - ASSERT(0 == uv_timer_init(loop, &ci.timer_handle)); - ASSERT(0 == uv_timer_start(&ci.timer_handle, timer_cb, 10, 0)); - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - ASSERT(1 == timer_cb_called); - ASSERT(ARRAY_SIZE(reqs) == done2_cb_called); - - cleanup_threadpool(); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(threadpool_cancel_fs) { - struct cancel_info ci; - uv_fs_t reqs[25]; - uv_loop_t* loop; - unsigned n; - - INIT_CANCEL_INFO(&ci, reqs); - loop = uv_default_loop(); - saturate_threadpool(); - - /* Needs to match ARRAY_SIZE(fs_reqs). */ - n = 0; - ASSERT(0 == uv_fs_chmod(loop, reqs + n++, "/", 0, fs_cb)); - ASSERT(0 == uv_fs_chown(loop, reqs + n++, "/", 0, 0, fs_cb)); - ASSERT(0 == uv_fs_close(loop, reqs + n++, 0, fs_cb)); - ASSERT(0 == uv_fs_fchmod(loop, reqs + n++, 0, 0, fs_cb)); - ASSERT(0 == uv_fs_fchown(loop, reqs + n++, 0, 0, 0, fs_cb)); - ASSERT(0 == uv_fs_fdatasync(loop, reqs + n++, 0, fs_cb)); - ASSERT(0 == uv_fs_fstat(loop, reqs + n++, 0, fs_cb)); - ASSERT(0 == uv_fs_fsync(loop, reqs + n++, 0, fs_cb)); - ASSERT(0 == uv_fs_ftruncate(loop, reqs + n++, 0, 0, fs_cb)); - ASSERT(0 == uv_fs_futime(loop, reqs + n++, 0, 0, 0, fs_cb)); - ASSERT(0 == uv_fs_link(loop, reqs + n++, "/", "/", fs_cb)); - ASSERT(0 == uv_fs_lstat(loop, reqs + n++, "/", fs_cb)); - ASSERT(0 == uv_fs_mkdir(loop, reqs + n++, "/", 0, fs_cb)); - ASSERT(0 == uv_fs_open(loop, reqs + n++, "/", 0, 0, fs_cb)); - ASSERT(0 == uv_fs_read(loop, reqs + n++, 0, NULL, 0, 0, fs_cb)); - ASSERT(0 == uv_fs_scandir(loop, reqs + n++, "/", 0, fs_cb)); - ASSERT(0 == uv_fs_readlink(loop, reqs + n++, "/", fs_cb)); - ASSERT(0 == uv_fs_rename(loop, reqs + n++, "/", "/", fs_cb)); - ASSERT(0 == uv_fs_mkdir(loop, reqs + n++, "/", 0, fs_cb)); - ASSERT(0 == uv_fs_sendfile(loop, reqs + n++, 0, 0, 0, 0, fs_cb)); - ASSERT(0 == uv_fs_stat(loop, reqs + n++, "/", fs_cb)); - ASSERT(0 == uv_fs_symlink(loop, reqs + n++, "/", "/", 0, fs_cb)); - ASSERT(0 == uv_fs_unlink(loop, reqs + n++, "/", fs_cb)); - ASSERT(0 == uv_fs_utime(loop, reqs + n++, "/", 0, 0, fs_cb)); - ASSERT(0 == uv_fs_write(loop, reqs + n++, 0, NULL, 0, 0, fs_cb)); - ASSERT(n == ARRAY_SIZE(reqs)); - - ASSERT(0 == uv_timer_init(loop, &ci.timer_handle)); - ASSERT(0 == uv_timer_start(&ci.timer_handle, timer_cb, 10, 0)); - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - ASSERT(n == fs_cb_called); - ASSERT(1 == timer_cb_called); - - cleanup_threadpool(); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(threadpool_cancel_single) { - uv_loop_t* loop; - uv_work_t req; - int cancelled; - int i; - - loop = uv_default_loop(); - for (i = 0; i < 5000; i++) { - req.data = NULL; - ASSERT(0 == uv_queue_work(loop, &req, nop_work_cb, nop_done_cb)); - - cancelled = uv_cancel((uv_req_t*) &req); - if (cancelled == 0) - break; - - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - } - - if (cancelled != 0) { - fputs("Failed to cancel a work req in 5,000 iterations, giving up.\n", - stderr); - return 1; - } - - ASSERT(req.data == NULL); - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - ASSERT(req.data != NULL); /* Should have been updated by nop_done_cb(). */ - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-threadpool.c b/libuv/test/test-threadpool.c deleted file mode 100644 index e3d17d7..0000000 --- a/libuv/test/test-threadpool.c +++ /dev/null @@ -1,76 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -static int work_cb_count; -static int after_work_cb_count; -static uv_work_t work_req; -static char data; - - -static void work_cb(uv_work_t* req) { - ASSERT(req == &work_req); - ASSERT(req->data == &data); - work_cb_count++; -} - - -static void after_work_cb(uv_work_t* req, int status) { - ASSERT(status == 0); - ASSERT(req == &work_req); - ASSERT(req->data == &data); - after_work_cb_count++; -} - - -TEST_IMPL(threadpool_queue_work_simple) { - int r; - - work_req.data = &data; - r = uv_queue_work(uv_default_loop(), &work_req, work_cb, after_work_cb); - ASSERT(r == 0); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(work_cb_count == 1); - ASSERT(after_work_cb_count == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(threadpool_queue_work_einval) { - int r; - - work_req.data = &data; - r = uv_queue_work(uv_default_loop(), &work_req, NULL, after_work_cb); - ASSERT(r == UV_EINVAL); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(work_cb_count == 0); - ASSERT(after_work_cb_count == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-timer-again.c b/libuv/test/test-timer-again.c deleted file mode 100644 index 095cd9e..0000000 --- a/libuv/test/test-timer-again.c +++ /dev/null @@ -1,137 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - - -static int close_cb_called = 0; -static int repeat_1_cb_called = 0; -static int repeat_2_cb_called = 0; - -static int repeat_2_cb_allowed = 0; - -static uv_timer_t dummy, repeat_1, repeat_2; - -static uint64_t start_time; - - -static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); - - close_cb_called++; -} - - -static void repeat_1_cb(uv_timer_t* handle) { - int r; - - ASSERT(handle == &repeat_1); - ASSERT(uv_timer_get_repeat((uv_timer_t*)handle) == 50); - - LOGF("repeat_1_cb called after %ld ms\n", - (long int)(uv_now(uv_default_loop()) - start_time)); - - repeat_1_cb_called++; - - r = uv_timer_again(&repeat_2); - ASSERT(r == 0); - - if (repeat_1_cb_called == 10) { - uv_close((uv_handle_t*)handle, close_cb); - /* We're not calling uv_timer_again on repeat_2 any more, so after this */ - /* timer_2_cb is expected. */ - repeat_2_cb_allowed = 1; - return; - } -} - - -static void repeat_2_cb(uv_timer_t* handle) { - ASSERT(handle == &repeat_2); - ASSERT(repeat_2_cb_allowed); - - LOGF("repeat_2_cb called after %ld ms\n", - (long int)(uv_now(uv_default_loop()) - start_time)); - - repeat_2_cb_called++; - - if (uv_timer_get_repeat(&repeat_2) == 0) { - ASSERT(0 == uv_is_active((uv_handle_t*) handle)); - uv_close((uv_handle_t*)handle, close_cb); - return; - } - - LOGF("uv_timer_get_repeat %ld ms\n", - (long int)uv_timer_get_repeat(&repeat_2)); - ASSERT(uv_timer_get_repeat(&repeat_2) == 100); - - /* This shouldn't take effect immediately. */ - uv_timer_set_repeat(&repeat_2, 0); -} - - -TEST_IMPL(timer_again) { - int r; - - start_time = uv_now(uv_default_loop()); - ASSERT(0 < start_time); - - /* Verify that it is not possible to uv_timer_again a never-started timer. */ - r = uv_timer_init(uv_default_loop(), &dummy); - ASSERT(r == 0); - r = uv_timer_again(&dummy); - ASSERT(r == UV_EINVAL); - uv_unref((uv_handle_t*)&dummy); - - /* Start timer repeat_1. */ - r = uv_timer_init(uv_default_loop(), &repeat_1); - ASSERT(r == 0); - r = uv_timer_start(&repeat_1, repeat_1_cb, 50, 0); - ASSERT(r == 0); - ASSERT(uv_timer_get_repeat(&repeat_1) == 0); - - /* Actually make repeat_1 repeating. */ - uv_timer_set_repeat(&repeat_1, 50); - ASSERT(uv_timer_get_repeat(&repeat_1) == 50); - - /* - * Start another repeating timer. It'll be again()ed by the repeat_1 so - * it should not time out until repeat_1 stops. - */ - r = uv_timer_init(uv_default_loop(), &repeat_2); - ASSERT(r == 0); - r = uv_timer_start(&repeat_2, repeat_2_cb, 100, 100); - ASSERT(r == 0); - ASSERT(uv_timer_get_repeat(&repeat_2) == 100); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(repeat_1_cb_called == 10); - ASSERT(repeat_2_cb_called == 2); - ASSERT(close_cb_called == 2); - - LOGF("Test took %ld ms (expected ~700 ms)\n", - (long int)(uv_now(uv_default_loop()) - start_time)); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-timer-from-check.c b/libuv/test/test-timer-from-check.c deleted file mode 100644 index a18c7e1..0000000 --- a/libuv/test/test-timer-from-check.c +++ /dev/null @@ -1,80 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -static uv_prepare_t prepare_handle; -static uv_check_t check_handle; -static uv_timer_t timer_handle; - -static int prepare_cb_called; -static int check_cb_called; -static int timer_cb_called; - - -static void prepare_cb(uv_prepare_t* handle) { - ASSERT(0 == uv_prepare_stop(&prepare_handle)); - ASSERT(0 == prepare_cb_called); - ASSERT(1 == check_cb_called); - ASSERT(0 == timer_cb_called); - prepare_cb_called++; -} - - -static void timer_cb(uv_timer_t* handle) { - ASSERT(0 == uv_timer_stop(&timer_handle)); - ASSERT(1 == prepare_cb_called); - ASSERT(1 == check_cb_called); - ASSERT(0 == timer_cb_called); - timer_cb_called++; -} - - -static void check_cb(uv_check_t* handle) { - ASSERT(0 == uv_check_stop(&check_handle)); - ASSERT(0 == uv_timer_stop(&timer_handle)); /* Runs before timer_cb. */ - ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 50, 0)); - ASSERT(0 == uv_prepare_start(&prepare_handle, prepare_cb)); - ASSERT(0 == prepare_cb_called); - ASSERT(0 == check_cb_called); - ASSERT(0 == timer_cb_called); - check_cb_called++; -} - - -TEST_IMPL(timer_from_check) { - ASSERT(0 == uv_prepare_init(uv_default_loop(), &prepare_handle)); - ASSERT(0 == uv_check_init(uv_default_loop(), &check_handle)); - ASSERT(0 == uv_check_start(&check_handle, check_cb)); - ASSERT(0 == uv_timer_init(uv_default_loop(), &timer_handle)); - ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 50, 0)); - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); - ASSERT(1 == prepare_cb_called); - ASSERT(1 == check_cb_called); - ASSERT(1 == timer_cb_called); - uv_close((uv_handle_t*) &prepare_handle, NULL); - uv_close((uv_handle_t*) &check_handle, NULL); - uv_close((uv_handle_t*) &timer_handle, NULL); - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE)); - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-timer.c b/libuv/test/test-timer.c deleted file mode 100644 index aba050f..0000000 --- a/libuv/test/test-timer.c +++ /dev/null @@ -1,303 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - - -static int once_cb_called = 0; -static int once_close_cb_called = 0; -static int repeat_cb_called = 0; -static int repeat_close_cb_called = 0; -static int order_cb_called = 0; -static uint64_t start_time; -static uv_timer_t tiny_timer; -static uv_timer_t huge_timer1; -static uv_timer_t huge_timer2; - - -static void once_close_cb(uv_handle_t* handle) { - printf("ONCE_CLOSE_CB\n"); - - ASSERT(handle != NULL); - ASSERT(0 == uv_is_active(handle)); - - once_close_cb_called++; -} - - -static void once_cb(uv_timer_t* handle) { - printf("ONCE_CB %d\n", once_cb_called); - - ASSERT(handle != NULL); - ASSERT(0 == uv_is_active((uv_handle_t*) handle)); - - once_cb_called++; - - uv_close((uv_handle_t*)handle, once_close_cb); - - /* Just call this randomly for the code coverage. */ - uv_update_time(uv_default_loop()); -} - - -static void repeat_close_cb(uv_handle_t* handle) { - printf("REPEAT_CLOSE_CB\n"); - - ASSERT(handle != NULL); - - repeat_close_cb_called++; -} - - -static void repeat_cb(uv_timer_t* handle) { - printf("REPEAT_CB\n"); - - ASSERT(handle != NULL); - ASSERT(1 == uv_is_active((uv_handle_t*) handle)); - - repeat_cb_called++; - - if (repeat_cb_called == 5) { - uv_close((uv_handle_t*)handle, repeat_close_cb); - } -} - - -static void never_cb(uv_timer_t* handle) { - FATAL("never_cb should never be called"); -} - - -TEST_IMPL(timer) { - uv_timer_t once_timers[10]; - uv_timer_t *once; - uv_timer_t repeat, never; - unsigned int i; - int r; - - start_time = uv_now(uv_default_loop()); - ASSERT(0 < start_time); - - /* Let 10 timers time out in 500 ms total. */ - for (i = 0; i < ARRAY_SIZE(once_timers); i++) { - once = once_timers + i; - r = uv_timer_init(uv_default_loop(), once); - ASSERT(r == 0); - r = uv_timer_start(once, once_cb, i * 50, 0); - ASSERT(r == 0); - } - - /* The 11th timer is a repeating timer that runs 4 times */ - r = uv_timer_init(uv_default_loop(), &repeat); - ASSERT(r == 0); - r = uv_timer_start(&repeat, repeat_cb, 100, 100); - ASSERT(r == 0); - - /* The 12th timer should not do anything. */ - r = uv_timer_init(uv_default_loop(), &never); - ASSERT(r == 0); - r = uv_timer_start(&never, never_cb, 100, 100); - ASSERT(r == 0); - r = uv_timer_stop(&never); - ASSERT(r == 0); - uv_unref((uv_handle_t*)&never); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(once_cb_called == 10); - ASSERT(once_close_cb_called == 10); - printf("repeat_cb_called %d\n", repeat_cb_called); - ASSERT(repeat_cb_called == 5); - ASSERT(repeat_close_cb_called == 1); - - ASSERT(500 <= uv_now(uv_default_loop()) - start_time); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(timer_start_twice) { - uv_timer_t once; - int r; - - r = uv_timer_init(uv_default_loop(), &once); - ASSERT(r == 0); - r = uv_timer_start(&once, never_cb, 86400 * 1000, 0); - ASSERT(r == 0); - r = uv_timer_start(&once, once_cb, 10, 0); - ASSERT(r == 0); - r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(r == 0); - - ASSERT(once_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(timer_init) { - uv_timer_t handle; - - ASSERT(0 == uv_timer_init(uv_default_loop(), &handle)); - ASSERT(0 == uv_timer_get_repeat(&handle)); - ASSERT(0 == uv_is_active((uv_handle_t*) &handle)); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -static void order_cb_a(uv_timer_t *handle) { - ASSERT(order_cb_called++ == *(int*)handle->data); -} - - -static void order_cb_b(uv_timer_t *handle) { - ASSERT(order_cb_called++ == *(int*)handle->data); -} - - -TEST_IMPL(timer_order) { - int first; - int second; - uv_timer_t handle_a; - uv_timer_t handle_b; - - first = 0; - second = 1; - ASSERT(0 == uv_timer_init(uv_default_loop(), &handle_a)); - ASSERT(0 == uv_timer_init(uv_default_loop(), &handle_b)); - - /* Test for starting handle_a then handle_b */ - handle_a.data = &first; - ASSERT(0 == uv_timer_start(&handle_a, order_cb_a, 0, 0)); - handle_b.data = &second; - ASSERT(0 == uv_timer_start(&handle_b, order_cb_b, 0, 0)); - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); - - ASSERT(order_cb_called == 2); - - ASSERT(0 == uv_timer_stop(&handle_a)); - ASSERT(0 == uv_timer_stop(&handle_b)); - - /* Test for starting handle_b then handle_a */ - order_cb_called = 0; - handle_b.data = &first; - ASSERT(0 == uv_timer_start(&handle_b, order_cb_b, 0, 0)); - - handle_a.data = &second; - ASSERT(0 == uv_timer_start(&handle_a, order_cb_a, 0, 0)); - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); - - ASSERT(order_cb_called == 2); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -static void tiny_timer_cb(uv_timer_t* handle) { - ASSERT(handle == &tiny_timer); - uv_close((uv_handle_t*) &tiny_timer, NULL); - uv_close((uv_handle_t*) &huge_timer1, NULL); - uv_close((uv_handle_t*) &huge_timer2, NULL); -} - - -TEST_IMPL(timer_huge_timeout) { - ASSERT(0 == uv_timer_init(uv_default_loop(), &tiny_timer)); - ASSERT(0 == uv_timer_init(uv_default_loop(), &huge_timer1)); - ASSERT(0 == uv_timer_init(uv_default_loop(), &huge_timer2)); - ASSERT(0 == uv_timer_start(&tiny_timer, tiny_timer_cb, 1, 0)); - ASSERT(0 == uv_timer_start(&huge_timer1, tiny_timer_cb, 0xffffffffffffLL, 0)); - ASSERT(0 == uv_timer_start(&huge_timer2, tiny_timer_cb, (uint64_t) -1, 0)); - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -static void huge_repeat_cb(uv_timer_t* handle) { - static int ncalls; - - if (ncalls == 0) - ASSERT(handle == &huge_timer1); - else - ASSERT(handle == &tiny_timer); - - if (++ncalls == 10) { - uv_close((uv_handle_t*) &tiny_timer, NULL); - uv_close((uv_handle_t*) &huge_timer1, NULL); - } -} - - -TEST_IMPL(timer_huge_repeat) { - ASSERT(0 == uv_timer_init(uv_default_loop(), &tiny_timer)); - ASSERT(0 == uv_timer_init(uv_default_loop(), &huge_timer1)); - ASSERT(0 == uv_timer_start(&tiny_timer, huge_repeat_cb, 2, 2)); - ASSERT(0 == uv_timer_start(&huge_timer1, huge_repeat_cb, 1, (uint64_t) -1)); - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -static unsigned int timer_run_once_timer_cb_called; - - -static void timer_run_once_timer_cb(uv_timer_t* handle) { - timer_run_once_timer_cb_called++; -} - - -TEST_IMPL(timer_run_once) { - uv_timer_t timer_handle; - - ASSERT(0 == uv_timer_init(uv_default_loop(), &timer_handle)); - ASSERT(0 == uv_timer_start(&timer_handle, timer_run_once_timer_cb, 0, 0)); - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE)); - ASSERT(1 == timer_run_once_timer_cb_called); - - ASSERT(0 == uv_timer_start(&timer_handle, timer_run_once_timer_cb, 1, 0)); - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE)); - ASSERT(2 == timer_run_once_timer_cb_called); - - uv_close((uv_handle_t*) &timer_handle, NULL); - ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE)); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(timer_null_callback) { - uv_timer_t handle; - - ASSERT(0 == uv_timer_init(uv_default_loop(), &handle)); - ASSERT(UV_EINVAL == uv_timer_start(&handle, NULL, 100, 100)); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-tty.c b/libuv/test/test-tty.c deleted file mode 100644 index 7e1ce26..0000000 --- a/libuv/test/test-tty.c +++ /dev/null @@ -1,130 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#ifdef _WIN32 -# include -# include -#else /* Unix */ -# include -# include -#endif - -#include -#include - - -TEST_IMPL(tty) { - int r, width, height; - int ttyin_fd, ttyout_fd; - uv_tty_t tty_in, tty_out; - uv_loop_t* loop = uv_default_loop(); - - /* Make sure we have an FD that refers to a tty */ -#ifdef _WIN32 - HANDLE handle; - handle = CreateFileA("conin$", - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - ASSERT(handle != INVALID_HANDLE_VALUE); - ttyin_fd = _open_osfhandle((intptr_t) handle, 0); - - handle = CreateFileA("conout$", - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - ASSERT(handle != INVALID_HANDLE_VALUE); - ttyout_fd = _open_osfhandle((intptr_t) handle, 0); - -#else /* unix */ - ttyin_fd = open("/dev/tty", O_RDONLY, 0); - if (ttyin_fd < 0) { - LOGF("Cannot open /dev/tty as read-only: %s\n", strerror(errno)); - return TEST_SKIP; - } - - ttyout_fd = open("/dev/tty", O_WRONLY, 0); - if (ttyout_fd < 0) { - LOGF("Cannot open /dev/tty as write-only: %s\n", strerror(errno)); - return TEST_SKIP; - } -#endif - - ASSERT(ttyin_fd >= 0); - ASSERT(ttyout_fd >= 0); - - ASSERT(UV_UNKNOWN_HANDLE == uv_guess_handle(-1)); - - ASSERT(UV_TTY == uv_guess_handle(ttyin_fd)); - ASSERT(UV_TTY == uv_guess_handle(ttyout_fd)); - - r = uv_tty_init(uv_default_loop(), &tty_in, ttyin_fd, 1); /* Readable. */ - ASSERT(r == 0); - - r = uv_tty_init(uv_default_loop(), &tty_out, ttyout_fd, 0); /* Writable. */ - ASSERT(r == 0); - - r = uv_tty_get_winsize(&tty_out, &width, &height); - ASSERT(r == 0); - - printf("width=%d height=%d\n", width, height); - - if (width == 0 && height == 0) { - /* Some environments such as containers or Jenkins behave like this - * sometimes */ - MAKE_VALGRIND_HAPPY(); - return TEST_SKIP; - } - - /* - * Is it a safe assumption that most people have terminals larger than - * 10x10? - */ - ASSERT(width > 10); - ASSERT(height > 10); - - /* Turn on raw mode. */ - r = uv_tty_set_mode(&tty_in, 1); - ASSERT(r == 0); - - /* Turn off raw mode. */ - r = uv_tty_set_mode(&tty_in, 0); - ASSERT(r == 0); - - /* TODO check the actual mode! */ - - uv_close((uv_handle_t*) &tty_in, NULL); - uv_close((uv_handle_t*) &tty_out, NULL); - - uv_run(loop, UV_RUN_DEFAULT); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-udp-bind.c b/libuv/test/test-udp-bind.c deleted file mode 100644 index a1e080e..0000000 --- a/libuv/test/test-udp-bind.c +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include -#include - - -TEST_IMPL(udp_bind) { - struct sockaddr_in addr; - uv_loop_t* loop; - uv_udp_t h1, h2; - int r; - - ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); - - loop = uv_default_loop(); - - r = uv_udp_init(loop, &h1); - ASSERT(r == 0); - - r = uv_udp_init(loop, &h2); - ASSERT(r == 0); - - r = uv_udp_bind(&h1, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - - r = uv_udp_bind(&h2, (const struct sockaddr*) &addr, 0); - ASSERT(r == UV_EADDRINUSE); - - uv_close((uv_handle_t*) &h1, NULL); - uv_close((uv_handle_t*) &h2, NULL); - - r = uv_run(loop, UV_RUN_DEFAULT); - ASSERT(r == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(udp_bind_reuseaddr) { - struct sockaddr_in addr; - uv_loop_t* loop; - uv_udp_t h1, h2; - int r; - - ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); - - loop = uv_default_loop(); - - r = uv_udp_init(loop, &h1); - ASSERT(r == 0); - - r = uv_udp_init(loop, &h2); - ASSERT(r == 0); - - r = uv_udp_bind(&h1, (const struct sockaddr*) &addr, UV_UDP_REUSEADDR); - ASSERT(r == 0); - - r = uv_udp_bind(&h2, (const struct sockaddr*) &addr, UV_UDP_REUSEADDR); - ASSERT(r == 0); - - uv_close((uv_handle_t*) &h1, NULL); - uv_close((uv_handle_t*) &h2, NULL); - - r = uv_run(loop, UV_RUN_DEFAULT); - ASSERT(r == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-udp-dgram-too-big.c b/libuv/test/test-udp-dgram-too-big.c deleted file mode 100644 index bd44c42..0000000 --- a/libuv/test/test-udp-dgram-too-big.c +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include -#include - -#define CHECK_HANDLE(handle) \ - ASSERT((uv_udp_t*)(handle) == &handle_) - -#define CHECK_REQ(req) \ - ASSERT((req) == &req_); - -static uv_udp_t handle_; -static uv_udp_send_t req_; - -static int send_cb_called; -static int close_cb_called; - - -static void close_cb(uv_handle_t* handle) { - CHECK_HANDLE(handle); - close_cb_called++; -} - - -static void send_cb(uv_udp_send_t* req, int status) { - CHECK_REQ(req); - CHECK_HANDLE(req->handle); - - ASSERT(status == UV_EMSGSIZE); - - uv_close((uv_handle_t*)req->handle, close_cb); - send_cb_called++; -} - - -TEST_IMPL(udp_dgram_too_big) { - char dgram[65536]; /* 64K MTU is unlikely, even on localhost */ - struct sockaddr_in addr; - uv_buf_t buf; - int r; - - memset(dgram, 42, sizeof dgram); /* silence valgrind */ - - r = uv_udp_init(uv_default_loop(), &handle_); - ASSERT(r == 0); - - buf = uv_buf_init(dgram, sizeof dgram); - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - - r = uv_udp_send(&req_, - &handle_, - &buf, - 1, - (const struct sockaddr*) &addr, - send_cb); - ASSERT(r == 0); - - ASSERT(close_cb_called == 0); - ASSERT(send_cb_called == 0); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(send_cb_called == 1); - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-udp-ipv6.c b/libuv/test/test-udp-ipv6.c deleted file mode 100644 index 1d5720c..0000000 --- a/libuv/test/test-udp-ipv6.c +++ /dev/null @@ -1,172 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include -#include - -#define CHECK_HANDLE(handle) \ - ASSERT((uv_udp_t*)(handle) == &server \ - || (uv_udp_t*)(handle) == &client \ - || (uv_timer_t*)(handle) == &timeout) - -#define CHECK_REQ(req) \ - ASSERT((req) == &req_); - -static uv_udp_t client; -static uv_udp_t server; -static uv_udp_send_t req_; -static uv_timer_t timeout; - -static int send_cb_called; -static int recv_cb_called; -static int close_cb_called; - - -static void alloc_cb(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf) { - static char slab[65536]; - CHECK_HANDLE(handle); - buf->base = slab; - buf->len = sizeof(slab); -} - - -static void close_cb(uv_handle_t* handle) { - CHECK_HANDLE(handle); - close_cb_called++; -} - - -static void send_cb(uv_udp_send_t* req, int status) { - CHECK_REQ(req); - CHECK_HANDLE(req->handle); - ASSERT(status == 0); - send_cb_called++; -} - - -static void ipv6_recv_fail(uv_udp_t* handle, - ssize_t nread, - const uv_buf_t* buf, - const struct sockaddr* addr, - unsigned flags) { - ASSERT(0 && "this function should not have been called"); -} - - -static void ipv6_recv_ok(uv_udp_t* handle, - ssize_t nread, - const uv_buf_t* buf, - const struct sockaddr* addr, - unsigned flags) { - CHECK_HANDLE(handle); - ASSERT(nread >= 0); - - if (nread) - recv_cb_called++; -} - - -static void timeout_cb(uv_timer_t* timer) { - uv_close((uv_handle_t*)&server, close_cb); - uv_close((uv_handle_t*)&client, close_cb); - uv_close((uv_handle_t*)&timeout, close_cb); -} - - -static void do_test(uv_udp_recv_cb recv_cb, int bind_flags) { - struct sockaddr_in6 addr6; - struct sockaddr_in addr; - uv_buf_t buf; - int r; - - ASSERT(0 == uv_ip6_addr("::0", TEST_PORT, &addr6)); - - r = uv_udp_init(uv_default_loop(), &server); - ASSERT(r == 0); - - r = uv_udp_bind(&server, (const struct sockaddr*) &addr6, bind_flags); - ASSERT(r == 0); - - r = uv_udp_recv_start(&server, alloc_cb, recv_cb); - ASSERT(r == 0); - - r = uv_udp_init(uv_default_loop(), &client); - ASSERT(r == 0); - - buf = uv_buf_init("PING", 4); - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - - r = uv_udp_send(&req_, - &client, - &buf, - 1, - (const struct sockaddr*) &addr, - send_cb); - ASSERT(r == 0); - - r = uv_timer_init(uv_default_loop(), &timeout); - ASSERT(r == 0); - - r = uv_timer_start(&timeout, timeout_cb, 500, 0); - ASSERT(r == 0); - - ASSERT(close_cb_called == 0); - ASSERT(send_cb_called == 0); - ASSERT(recv_cb_called == 0); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(close_cb_called == 3); - - MAKE_VALGRIND_HAPPY(); -} - - -TEST_IMPL(udp_dual_stack) { - if (!can_ipv6()) - RETURN_SKIP("IPv6 not supported"); - - do_test(ipv6_recv_ok, 0); - - ASSERT(recv_cb_called == 1); - ASSERT(send_cb_called == 1); - - return 0; -} - - -TEST_IMPL(udp_ipv6_only) { - if (!can_ipv6()) - RETURN_SKIP("IPv6 not supported"); - - do_test(ipv6_recv_fail, UV_UDP_IPV6ONLY); - - ASSERT(recv_cb_called == 0); - ASSERT(send_cb_called == 1); - - return 0; -} diff --git a/libuv/test/test-udp-multicast-interface.c b/libuv/test/test-udp-multicast-interface.c deleted file mode 100644 index f0679c5..0000000 --- a/libuv/test/test-udp-multicast-interface.c +++ /dev/null @@ -1,99 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include -#include - -#define CHECK_HANDLE(handle) \ - ASSERT((uv_udp_t*)(handle) == &server || (uv_udp_t*)(handle) == &client) - -static uv_udp_t server; -static uv_udp_t client; - -static int sv_send_cb_called; -static int close_cb_called; - - -static void close_cb(uv_handle_t* handle) { - CHECK_HANDLE(handle); - close_cb_called++; -} - - -static void sv_send_cb(uv_udp_send_t* req, int status) { - ASSERT(req != NULL); - ASSERT(status == 0); - CHECK_HANDLE(req->handle); - - sv_send_cb_called++; - - uv_close((uv_handle_t*) req->handle, close_cb); -} - - -TEST_IMPL(udp_multicast_interface) { - int r; - uv_udp_send_t req; - uv_buf_t buf; - struct sockaddr_in addr; - struct sockaddr_in baddr; - - ASSERT(0 == uv_ip4_addr("239.255.0.1", TEST_PORT, &addr)); - - r = uv_udp_init(uv_default_loop(), &server); - ASSERT(r == 0); - - ASSERT(0 == uv_ip4_addr("0.0.0.0", 0, &baddr)); - r = uv_udp_bind(&server, (const struct sockaddr*)&baddr, 0); - ASSERT(r == 0); - - r = uv_udp_set_multicast_interface(&server, "0.0.0.0"); - ASSERT(r == 0); - - /* server sends "PING" */ - buf = uv_buf_init("PING", 4); - r = uv_udp_send(&req, - &server, - &buf, - 1, - (const struct sockaddr*)&addr, - sv_send_cb); - ASSERT(r == 0); - - ASSERT(close_cb_called == 0); - ASSERT(sv_send_cb_called == 0); - - /* run the loop till all events are processed */ - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(sv_send_cb_called == 1); - ASSERT(close_cb_called == 1); - - ASSERT(client.send_queue_size == 0); - ASSERT(server.send_queue_size == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-udp-multicast-interface6.c b/libuv/test/test-udp-multicast-interface6.c deleted file mode 100644 index d3881e8..0000000 --- a/libuv/test/test-udp-multicast-interface6.c +++ /dev/null @@ -1,103 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include -#include - -#define CHECK_HANDLE(handle) \ - ASSERT((uv_udp_t*)(handle) == &server || (uv_udp_t*)(handle) == &client) - -static uv_udp_t server; -static uv_udp_t client; - -static int sv_send_cb_called; -static int close_cb_called; - - -static void close_cb(uv_handle_t* handle) { - CHECK_HANDLE(handle); - close_cb_called++; -} - - -static void sv_send_cb(uv_udp_send_t* req, int status) { - ASSERT(req != NULL); - ASSERT(status == 0); - CHECK_HANDLE(req->handle); - - sv_send_cb_called++; - - uv_close((uv_handle_t*) req->handle, close_cb); -} - - -TEST_IMPL(udp_multicast_interface6) { - int r; - uv_udp_send_t req; - uv_buf_t buf; - struct sockaddr_in6 addr; - struct sockaddr_in6 baddr; - - if (!can_ipv6()) - RETURN_SKIP("IPv6 not supported"); - - ASSERT(0 == uv_ip6_addr("::1", TEST_PORT, &addr)); - - r = uv_udp_init(uv_default_loop(), &server); - ASSERT(r == 0); - - ASSERT(0 == uv_ip6_addr("::", 0, &baddr)); - r = uv_udp_bind(&server, (const struct sockaddr*)&baddr, 0); - ASSERT(r == 0); - -#if defined(__APPLE__) || defined(__FreeBSD__) - r = uv_udp_set_multicast_interface(&server, "::1%lo0"); -#else - r = uv_udp_set_multicast_interface(&server, NULL); -#endif - ASSERT(r == 0); - - /* server sends "PING" */ - buf = uv_buf_init("PING", 4); - r = uv_udp_send(&req, - &server, - &buf, - 1, - (const struct sockaddr*)&addr, - sv_send_cb); - ASSERT(r == 0); - - ASSERT(close_cb_called == 0); - ASSERT(sv_send_cb_called == 0); - - /* run the loop till all events are processed */ - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(sv_send_cb_called == 1); - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-udp-multicast-join.c b/libuv/test/test-udp-multicast-join.c deleted file mode 100644 index 686edf3..0000000 --- a/libuv/test/test-udp-multicast-join.c +++ /dev/null @@ -1,148 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include -#include - -#define CHECK_HANDLE(handle) \ - ASSERT((uv_udp_t*)(handle) == &server || (uv_udp_t*)(handle) == &client) - -static uv_udp_t server; -static uv_udp_t client; - -static int cl_recv_cb_called; - -static int sv_send_cb_called; - -static int close_cb_called; - -static void alloc_cb(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf) { - static char slab[65536]; - CHECK_HANDLE(handle); - ASSERT(suggested_size <= sizeof(slab)); - buf->base = slab; - buf->len = sizeof(slab); -} - - -static void close_cb(uv_handle_t* handle) { - CHECK_HANDLE(handle); - close_cb_called++; -} - - -static void sv_send_cb(uv_udp_send_t* req, int status) { - ASSERT(req != NULL); - ASSERT(status == 0); - CHECK_HANDLE(req->handle); - - sv_send_cb_called++; - - uv_close((uv_handle_t*) req->handle, close_cb); -} - - -static void cl_recv_cb(uv_udp_t* handle, - ssize_t nread, - const uv_buf_t* buf, - const struct sockaddr* addr, - unsigned flags) { - CHECK_HANDLE(handle); - ASSERT(flags == 0); - - cl_recv_cb_called++; - - if (nread < 0) { - ASSERT(0 && "unexpected error"); - } - - if (nread == 0) { - /* Returning unused buffer */ - /* Don't count towards cl_recv_cb_called */ - ASSERT(addr == NULL); - return; - } - - ASSERT(addr != NULL); - ASSERT(nread == 4); - ASSERT(!memcmp("PING", buf->base, nread)); - - /* we are done with the client handle, we can close it */ - uv_close((uv_handle_t*) &client, close_cb); -} - - -TEST_IMPL(udp_multicast_join) { - int r; - uv_udp_send_t req; - uv_buf_t buf; - struct sockaddr_in addr; - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - - r = uv_udp_init(uv_default_loop(), &server); - ASSERT(r == 0); - - r = uv_udp_init(uv_default_loop(), &client); - ASSERT(r == 0); - - /* bind to the desired port */ - r = uv_udp_bind(&client, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - - /* join the multicast channel */ - r = uv_udp_set_membership(&client, "239.255.0.1", NULL, UV_JOIN_GROUP); - ASSERT(r == 0); - - r = uv_udp_recv_start(&client, alloc_cb, cl_recv_cb); - ASSERT(r == 0); - - buf = uv_buf_init("PING", 4); - - /* server sends "PING" */ - r = uv_udp_send(&req, - &server, - &buf, - 1, - (const struct sockaddr*) &addr, - sv_send_cb); - ASSERT(r == 0); - - ASSERT(close_cb_called == 0); - ASSERT(cl_recv_cb_called == 0); - ASSERT(sv_send_cb_called == 0); - - /* run the loop till all events are processed */ - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(cl_recv_cb_called == 1); - ASSERT(sv_send_cb_called == 1); - ASSERT(close_cb_called == 2); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-udp-multicast-join6.c b/libuv/test/test-udp-multicast-join6.c deleted file mode 100644 index 9ba201a..0000000 --- a/libuv/test/test-udp-multicast-join6.c +++ /dev/null @@ -1,156 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include -#include - - -#define CHECK_HANDLE(handle) \ - ASSERT((uv_udp_t*)(handle) == &server || (uv_udp_t*)(handle) == &client) - -static uv_udp_t server; -static uv_udp_t client; - -static int cl_recv_cb_called; - -static int sv_send_cb_called; - -static int close_cb_called; - -static void alloc_cb(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf) { - static char slab[65536]; - CHECK_HANDLE(handle); - ASSERT(suggested_size <= sizeof(slab)); - buf->base = slab; - buf->len = sizeof(slab); -} - - -static void close_cb(uv_handle_t* handle) { - CHECK_HANDLE(handle); - close_cb_called++; -} - - -static void sv_send_cb(uv_udp_send_t* req, int status) { - ASSERT(req != NULL); - ASSERT(status == 0); - CHECK_HANDLE(req->handle); - - sv_send_cb_called++; - - uv_close((uv_handle_t*) req->handle, close_cb); -} - - -static void cl_recv_cb(uv_udp_t* handle, - ssize_t nread, - const uv_buf_t* buf, - const struct sockaddr* addr, - unsigned flags) { - CHECK_HANDLE(handle); - ASSERT(flags == 0); - - cl_recv_cb_called++; - - if (nread < 0) { - ASSERT(0 && "unexpected error"); - } - - if (nread == 0) { - /* Returning unused buffer */ - /* Don't count towards cl_recv_cb_called */ - ASSERT(addr == NULL); - return; - } - - ASSERT(addr != NULL); - ASSERT(nread == 4); - ASSERT(!memcmp("PING", buf->base, nread)); - - /* we are done with the client handle, we can close it */ - uv_close((uv_handle_t*) &client, close_cb); -} - - -TEST_IMPL(udp_multicast_join6) { - int r; - uv_udp_send_t req; - uv_buf_t buf; - struct sockaddr_in6 addr; - - if (!can_ipv6()) - RETURN_SKIP("IPv6 not supported"); - - ASSERT(0 == uv_ip6_addr("::1", TEST_PORT, &addr)); - - r = uv_udp_init(uv_default_loop(), &server); - ASSERT(r == 0); - - r = uv_udp_init(uv_default_loop(), &client); - ASSERT(r == 0); - - /* bind to the desired port */ - r = uv_udp_bind(&client, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - - /* join the multicast channel */ -#if defined(__APPLE__) - r = uv_udp_set_membership(&client, "ff02::1", "::1%lo0", UV_JOIN_GROUP); -#else - r = uv_udp_set_membership(&client, "ff02::1", NULL, UV_JOIN_GROUP); -#endif - ASSERT(r == 0); - - r = uv_udp_recv_start(&client, alloc_cb, cl_recv_cb); - ASSERT(r == 0); - - buf = uv_buf_init("PING", 4); - - /* server sends "PING" */ - r = uv_udp_send(&req, - &server, - &buf, - 1, - (const struct sockaddr*) &addr, - sv_send_cb); - ASSERT(r == 0); - - ASSERT(close_cb_called == 0); - ASSERT(cl_recv_cb_called == 0); - ASSERT(sv_send_cb_called == 0); - - /* run the loop till all events are processed */ - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(cl_recv_cb_called == 1); - ASSERT(sv_send_cb_called == 1); - ASSERT(close_cb_called == 2); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-udp-multicast-ttl.c b/libuv/test/test-udp-multicast-ttl.c deleted file mode 100644 index bed0ea1..0000000 --- a/libuv/test/test-udp-multicast-ttl.c +++ /dev/null @@ -1,94 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include -#include - -#define CHECK_HANDLE(handle) \ - ASSERT((uv_udp_t*)(handle) == &server || (uv_udp_t*)(handle) == &client) - -static uv_udp_t server; -static uv_udp_t client; - -static int sv_send_cb_called; -static int close_cb_called; - - -static void close_cb(uv_handle_t* handle) { - CHECK_HANDLE(handle); - close_cb_called++; -} - - -static void sv_send_cb(uv_udp_send_t* req, int status) { - ASSERT(req != NULL); - ASSERT(status == 0); - CHECK_HANDLE(req->handle); - - sv_send_cb_called++; - - uv_close((uv_handle_t*) req->handle, close_cb); -} - - -TEST_IMPL(udp_multicast_ttl) { - int r; - uv_udp_send_t req; - uv_buf_t buf; - struct sockaddr_in addr; - - r = uv_udp_init(uv_default_loop(), &server); - ASSERT(r == 0); - - ASSERT(0 == uv_ip4_addr("0.0.0.0", 0, &addr)); - r = uv_udp_bind(&server, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - - r = uv_udp_set_multicast_ttl(&server, 32); - ASSERT(r == 0); - - /* server sends "PING" */ - buf = uv_buf_init("PING", 4); - ASSERT(0 == uv_ip4_addr("239.255.0.1", TEST_PORT, &addr)); - r = uv_udp_send(&req, - &server, - &buf, - 1, - (const struct sockaddr*) &addr, - sv_send_cb); - ASSERT(r == 0); - - ASSERT(close_cb_called == 0); - ASSERT(sv_send_cb_called == 0); - - /* run the loop till all events are processed */ - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(sv_send_cb_called == 1); - ASSERT(close_cb_called == 1); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-udp-open.c b/libuv/test/test-udp-open.c deleted file mode 100644 index b2b6117..0000000 --- a/libuv/test/test-udp-open.c +++ /dev/null @@ -1,166 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" -#include -#include -#include - -#ifndef _WIN32 -# include -#endif - -static int send_cb_called = 0; -static int close_cb_called = 0; - -static uv_udp_send_t send_req; - - -static void startup(void) { -#ifdef _WIN32 - struct WSAData wsa_data; - int r = WSAStartup(MAKEWORD(2, 2), &wsa_data); - ASSERT(r == 0); -#endif -} - - -static uv_os_sock_t create_udp_socket(void) { - uv_os_sock_t sock; - - sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); -#ifdef _WIN32 - ASSERT(sock != INVALID_SOCKET); -#else - ASSERT(sock >= 0); -#endif - -#ifndef _WIN32 - { - /* Allow reuse of the port. */ - int yes = 1; - int r = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes); - ASSERT(r == 0); - } -#endif - - return sock; -} - - -static void alloc_cb(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf) { - static char slab[65536]; - ASSERT(suggested_size <= sizeof(slab)); - buf->base = slab; - buf->len = sizeof(slab); -} - - -static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); - close_cb_called++; -} - - -static void recv_cb(uv_udp_t* handle, - ssize_t nread, - const uv_buf_t* buf, - const struct sockaddr* addr, - unsigned flags) { - int r; - - if (nread < 0) { - ASSERT(0 && "unexpected error"); - } - - if (nread == 0) { - /* Returning unused buffer */ - /* Don't count towards sv_recv_cb_called */ - ASSERT(addr == NULL); - return; - } - - ASSERT(flags == 0); - - ASSERT(addr != NULL); - ASSERT(nread == 4); - ASSERT(memcmp("PING", buf->base, nread) == 0); - - r = uv_udp_recv_stop(handle); - ASSERT(r == 0); - - uv_close((uv_handle_t*) handle, close_cb); -} - - -static void send_cb(uv_udp_send_t* req, int status) { - ASSERT(req != NULL); - ASSERT(status == 0); - - send_cb_called++; -} - - -TEST_IMPL(udp_open) { - struct sockaddr_in addr; - uv_buf_t buf = uv_buf_init("PING", 4); - uv_udp_t client; - uv_os_sock_t sock; - int r; - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - - startup(); - sock = create_udp_socket(); - - r = uv_udp_init(uv_default_loop(), &client); - ASSERT(r == 0); - - r = uv_udp_open(&client, sock); - ASSERT(r == 0); - - r = uv_udp_bind(&client, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - - r = uv_udp_recv_start(&client, alloc_cb, recv_cb); - ASSERT(r == 0); - - r = uv_udp_send(&send_req, - &client, - &buf, - 1, - (const struct sockaddr*) &addr, - send_cb); - ASSERT(r == 0); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(send_cb_called == 1); - ASSERT(close_cb_called == 1); - - ASSERT(client.send_queue_size == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-udp-options.c b/libuv/test/test-udp-options.c deleted file mode 100644 index 0da1786..0000000 --- a/libuv/test/test-udp-options.c +++ /dev/null @@ -1,126 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include -#include - - -static int udp_options_test(const struct sockaddr* addr) { - static int invalid_ttls[] = { -1, 0, 256 }; - uv_loop_t* loop; - uv_udp_t h; - int i, r; - - loop = uv_default_loop(); - - r = uv_udp_init(loop, &h); - ASSERT(r == 0); - - uv_unref((uv_handle_t*)&h); /* don't keep the loop alive */ - - r = uv_udp_bind(&h, addr, 0); - ASSERT(r == 0); - - r = uv_udp_set_broadcast(&h, 1); - r |= uv_udp_set_broadcast(&h, 1); - r |= uv_udp_set_broadcast(&h, 0); - r |= uv_udp_set_broadcast(&h, 0); - ASSERT(r == 0); - - /* values 1-255 should work */ - for (i = 1; i <= 255; i++) { - r = uv_udp_set_ttl(&h, i); - ASSERT(r == 0); - } - - for (i = 0; i < (int) ARRAY_SIZE(invalid_ttls); i++) { - r = uv_udp_set_ttl(&h, invalid_ttls[i]); - ASSERT(r == UV_EINVAL); - } - - r = uv_udp_set_multicast_loop(&h, 1); - r |= uv_udp_set_multicast_loop(&h, 1); - r |= uv_udp_set_multicast_loop(&h, 0); - r |= uv_udp_set_multicast_loop(&h, 0); - ASSERT(r == 0); - - /* values 0-255 should work */ - for (i = 0; i <= 255; i++) { - r = uv_udp_set_multicast_ttl(&h, i); - ASSERT(r == 0); - } - - /* anything >255 should fail */ - r = uv_udp_set_multicast_ttl(&h, 256); - ASSERT(r == UV_EINVAL); - /* don't test ttl=-1, it's a valid value on some platforms */ - - r = uv_run(loop, UV_RUN_DEFAULT); - ASSERT(r == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - - -TEST_IMPL(udp_options) { - struct sockaddr_in addr; - - ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); - return udp_options_test((const struct sockaddr*) &addr); -} - - -TEST_IMPL(udp_options6) { - struct sockaddr_in6 addr; - - if (!can_ipv6()) - RETURN_SKIP("IPv6 not supported"); - - ASSERT(0 == uv_ip6_addr("::", TEST_PORT, &addr)); - return udp_options_test((const struct sockaddr*) &addr); -} - - -TEST_IMPL(udp_no_autobind) { - uv_loop_t* loop; - uv_udp_t h; - - loop = uv_default_loop(); - - ASSERT(0 == uv_udp_init(loop, &h)); - ASSERT(UV_EBADF == uv_udp_set_multicast_ttl(&h, 32)); - ASSERT(UV_EBADF == uv_udp_set_broadcast(&h, 1)); - ASSERT(UV_EBADF == uv_udp_set_ttl(&h, 1)); - ASSERT(UV_EBADF == uv_udp_set_multicast_loop(&h, 1)); - ASSERT(UV_EBADF == uv_udp_set_multicast_interface(&h, "0.0.0.0")); - - uv_close((uv_handle_t*) &h, NULL); - - ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-udp-send-and-recv.c b/libuv/test/test-udp-send-and-recv.c deleted file mode 100644 index 633a167..0000000 --- a/libuv/test/test-udp-send-and-recv.c +++ /dev/null @@ -1,214 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include -#include - -#define CHECK_HANDLE(handle) \ - ASSERT((uv_udp_t*)(handle) == &server || (uv_udp_t*)(handle) == &client) - -static uv_udp_t server; -static uv_udp_t client; - -static int cl_send_cb_called; -static int cl_recv_cb_called; - -static int sv_send_cb_called; -static int sv_recv_cb_called; - -static int close_cb_called; - - -static void alloc_cb(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf) { - static char slab[65536]; - CHECK_HANDLE(handle); - ASSERT(suggested_size <= sizeof(slab)); - buf->base = slab; - buf->len = sizeof(slab); -} - - -static void close_cb(uv_handle_t* handle) { - CHECK_HANDLE(handle); - ASSERT(1 == uv_is_closing(handle)); - close_cb_called++; -} - - -static void cl_recv_cb(uv_udp_t* handle, - ssize_t nread, - const uv_buf_t* buf, - const struct sockaddr* addr, - unsigned flags) { - CHECK_HANDLE(handle); - ASSERT(flags == 0); - - if (nread < 0) { - ASSERT(0 && "unexpected error"); - } - - if (nread == 0) { - /* Returning unused buffer */ - /* Don't count towards cl_recv_cb_called */ - ASSERT(addr == NULL); - return; - } - - ASSERT(addr != NULL); - ASSERT(nread == 4); - ASSERT(!memcmp("PONG", buf->base, nread)); - - cl_recv_cb_called++; - - uv_close((uv_handle_t*) handle, close_cb); -} - - -static void cl_send_cb(uv_udp_send_t* req, int status) { - int r; - - ASSERT(req != NULL); - ASSERT(status == 0); - CHECK_HANDLE(req->handle); - - r = uv_udp_recv_start(req->handle, alloc_cb, cl_recv_cb); - ASSERT(r == 0); - - cl_send_cb_called++; -} - - -static void sv_send_cb(uv_udp_send_t* req, int status) { - ASSERT(req != NULL); - ASSERT(status == 0); - CHECK_HANDLE(req->handle); - - uv_close((uv_handle_t*) req->handle, close_cb); - free(req); - - sv_send_cb_called++; -} - - -static void sv_recv_cb(uv_udp_t* handle, - ssize_t nread, - const uv_buf_t* rcvbuf, - const struct sockaddr* addr, - unsigned flags) { - uv_udp_send_t* req; - uv_buf_t sndbuf; - int r; - - if (nread < 0) { - ASSERT(0 && "unexpected error"); - } - - if (nread == 0) { - /* Returning unused buffer */ - /* Don't count towards sv_recv_cb_called */ - ASSERT(addr == NULL); - return; - } - - CHECK_HANDLE(handle); - ASSERT(flags == 0); - - ASSERT(addr != NULL); - ASSERT(nread == 4); - ASSERT(!memcmp("PING", rcvbuf->base, nread)); - - /* FIXME? `uv_udp_recv_stop` does what it says: recv_cb is not called - * anymore. That's problematic because the read buffer won't be returned - * either... Not sure I like that but it's consistent with `uv_read_stop`. - */ - r = uv_udp_recv_stop(handle); - ASSERT(r == 0); - - req = malloc(sizeof *req); - ASSERT(req != NULL); - - sndbuf = uv_buf_init("PONG", 4); - r = uv_udp_send(req, handle, &sndbuf, 1, addr, sv_send_cb); - ASSERT(r == 0); - - sv_recv_cb_called++; -} - - -TEST_IMPL(udp_send_and_recv) { - struct sockaddr_in addr; - uv_udp_send_t req; - uv_buf_t buf; - int r; - - ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); - - r = uv_udp_init(uv_default_loop(), &server); - ASSERT(r == 0); - - r = uv_udp_bind(&server, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - - r = uv_udp_recv_start(&server, alloc_cb, sv_recv_cb); - ASSERT(r == 0); - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - - r = uv_udp_init(uv_default_loop(), &client); - ASSERT(r == 0); - - /* client sends "PING", expects "PONG" */ - buf = uv_buf_init("PING", 4); - - r = uv_udp_send(&req, - &client, - &buf, - 1, - (const struct sockaddr*) &addr, - cl_send_cb); - ASSERT(r == 0); - - ASSERT(close_cb_called == 0); - ASSERT(cl_send_cb_called == 0); - ASSERT(cl_recv_cb_called == 0); - ASSERT(sv_send_cb_called == 0); - ASSERT(sv_recv_cb_called == 0); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(cl_send_cb_called == 1); - ASSERT(cl_recv_cb_called == 1); - ASSERT(sv_send_cb_called == 1); - ASSERT(sv_recv_cb_called == 1); - ASSERT(close_cb_called == 2); - - ASSERT(client.send_queue_size == 0); - ASSERT(server.send_queue_size == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-udp-send-immediate.c b/libuv/test/test-udp-send-immediate.c deleted file mode 100644 index 0999f6b..0000000 --- a/libuv/test/test-udp-send-immediate.c +++ /dev/null @@ -1,148 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include -#include - -#define CHECK_HANDLE(handle) \ - ASSERT((uv_udp_t*)(handle) == &server || (uv_udp_t*)(handle) == &client) - -static uv_udp_t server; -static uv_udp_t client; - -static int cl_send_cb_called; -static int sv_recv_cb_called; -static int close_cb_called; - - -static void alloc_cb(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf) { - static char slab[65536]; - CHECK_HANDLE(handle); - ASSERT(suggested_size <= sizeof(slab)); - buf->base = slab; - buf->len = sizeof(slab); -} - - -static void close_cb(uv_handle_t* handle) { - CHECK_HANDLE(handle); - ASSERT(1 == uv_is_closing(handle)); - close_cb_called++; -} - - -static void cl_send_cb(uv_udp_send_t* req, int status) { - ASSERT(req != NULL); - ASSERT(status == 0); - CHECK_HANDLE(req->handle); - - cl_send_cb_called++; -} - - -static void sv_recv_cb(uv_udp_t* handle, - ssize_t nread, - const uv_buf_t* rcvbuf, - const struct sockaddr* addr, - unsigned flags) { - if (nread < 0) { - ASSERT(0 && "unexpected error"); - } - - if (nread == 0) { - /* Returning unused buffer */ - /* Don't count towards sv_recv_cb_called */ - ASSERT(addr == NULL); - return; - } - - CHECK_HANDLE(handle); - ASSERT(flags == 0); - - ASSERT(addr != NULL); - ASSERT(nread == 4); - ASSERT(memcmp("PING", rcvbuf->base, nread) == 0 || - memcmp("PANG", rcvbuf->base, nread) == 0); - - if (++sv_recv_cb_called == 2) { - uv_close((uv_handle_t*) &server, close_cb); - uv_close((uv_handle_t*) &client, close_cb); - } -} - - -TEST_IMPL(udp_send_immediate) { - struct sockaddr_in addr; - uv_udp_send_t req1, req2; - uv_buf_t buf; - int r; - - ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); - - r = uv_udp_init(uv_default_loop(), &server); - ASSERT(r == 0); - - r = uv_udp_bind(&server, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - - r = uv_udp_recv_start(&server, alloc_cb, sv_recv_cb); - ASSERT(r == 0); - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - - r = uv_udp_init(uv_default_loop(), &client); - ASSERT(r == 0); - - /* client sends "PING", then "PANG" */ - buf = uv_buf_init("PING", 4); - - r = uv_udp_send(&req1, - &client, - &buf, - 1, - (const struct sockaddr*) &addr, - cl_send_cb); - ASSERT(r == 0); - - buf = uv_buf_init("PANG", 4); - - r = uv_udp_send(&req2, - &client, - &buf, - 1, - (const struct sockaddr*) &addr, - cl_send_cb); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(cl_send_cb_called == 2); - ASSERT(sv_recv_cb_called == 2); - ASSERT(close_cb_called == 2); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-udp-send-unreachable.c b/libuv/test/test-udp-send-unreachable.c deleted file mode 100644 index c650032..0000000 --- a/libuv/test/test-udp-send-unreachable.c +++ /dev/null @@ -1,150 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include -#include - -#define CHECK_HANDLE(handle) \ - ASSERT((uv_udp_t*)(handle) == &client) - -static uv_udp_t client; -static uv_timer_t timer; - -static int send_cb_called; -static int recv_cb_called; -static int close_cb_called; -static int alloc_cb_called; -static int timer_cb_called; - - -static void alloc_cb(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf) { - static char slab[65536]; - CHECK_HANDLE(handle); - ASSERT(suggested_size <= sizeof(slab)); - buf->base = slab; - buf->len = sizeof(slab); - alloc_cb_called++; -} - - -static void close_cb(uv_handle_t* handle) { - ASSERT(1 == uv_is_closing(handle)); - close_cb_called++; -} - - -static void send_cb(uv_udp_send_t* req, int status) { - ASSERT(req != NULL); - ASSERT(status == 0); - CHECK_HANDLE(req->handle); - send_cb_called++; -} - - -static void recv_cb(uv_udp_t* handle, - ssize_t nread, - const uv_buf_t* rcvbuf, - const struct sockaddr* addr, - unsigned flags) { - CHECK_HANDLE(handle); - recv_cb_called++; - - if (nread < 0) { - ASSERT(0 && "unexpected error"); - } else if (nread == 0) { - /* Returning unused buffer */ - ASSERT(addr == NULL); - } else { - ASSERT(addr != NULL); - } -} - - -static void timer_cb(uv_timer_t* h) { - ASSERT(h == &timer); - timer_cb_called++; - uv_close((uv_handle_t*) &client, close_cb); - uv_close((uv_handle_t*) h, close_cb); -} - - -TEST_IMPL(udp_send_unreachable) { - struct sockaddr_in addr; - struct sockaddr_in addr2; - uv_udp_send_t req1, req2; - uv_buf_t buf; - int r; - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT_2, &addr2)); - - r = uv_timer_init( uv_default_loop(), &timer ); - ASSERT(r == 0); - - r = uv_timer_start( &timer, timer_cb, 1000, 0 ); - ASSERT(r == 0); - - r = uv_udp_init(uv_default_loop(), &client); - ASSERT(r == 0); - - r = uv_udp_bind(&client, (const struct sockaddr*) &addr2, 0); - ASSERT(r == 0); - - r = uv_udp_recv_start(&client, alloc_cb, recv_cb); - ASSERT(r == 0); - - /* client sends "PING", then "PANG" */ - buf = uv_buf_init("PING", 4); - - r = uv_udp_send(&req1, - &client, - &buf, - 1, - (const struct sockaddr*) &addr, - send_cb); - ASSERT(r == 0); - - buf = uv_buf_init("PANG", 4); - - r = uv_udp_send(&req2, - &client, - &buf, - 1, - (const struct sockaddr*) &addr, - send_cb); - ASSERT(r == 0); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(send_cb_called == 2); - ASSERT(recv_cb_called == alloc_cb_called); - ASSERT(timer_cb_called == 1); - ASSERT(close_cb_called == 2); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-udp-try-send.c b/libuv/test/test-udp-try-send.c deleted file mode 100644 index 7b6de36..0000000 --- a/libuv/test/test-udp-try-send.c +++ /dev/null @@ -1,133 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include -#include - -#ifdef _WIN32 - -TEST_IMPL(udp_try_send) { - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -#else /* !_WIN32 */ - -#define CHECK_HANDLE(handle) \ - ASSERT((uv_udp_t*)(handle) == &server || (uv_udp_t*)(handle) == &client) - -static uv_udp_t server; -static uv_udp_t client; - -static int sv_recv_cb_called; - -static int close_cb_called; - - -static void alloc_cb(uv_handle_t* handle, - size_t suggested_size, - uv_buf_t* buf) { - static char slab[65536]; - CHECK_HANDLE(handle); - ASSERT(suggested_size <= sizeof(slab)); - buf->base = slab; - buf->len = sizeof(slab); -} - - -static void close_cb(uv_handle_t* handle) { - CHECK_HANDLE(handle); - ASSERT(uv_is_closing(handle)); - close_cb_called++; -} - - -static void sv_recv_cb(uv_udp_t* handle, - ssize_t nread, - const uv_buf_t* rcvbuf, - const struct sockaddr* addr, - unsigned flags) { - ASSERT(nread > 0); - - if (nread == 0) { - ASSERT(addr == NULL); - return; - } - - ASSERT(nread == 4); - ASSERT(addr != NULL); - - ASSERT(memcmp("EXIT", rcvbuf->base, nread) == 0); - uv_close((uv_handle_t*) handle, close_cb); - uv_close((uv_handle_t*) &client, close_cb); - - sv_recv_cb_called++; -} - - -TEST_IMPL(udp_try_send) { - struct sockaddr_in addr; - static char buffer[64 * 1024]; - uv_buf_t buf; - int r; - - ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); - - r = uv_udp_init(uv_default_loop(), &server); - ASSERT(r == 0); - - r = uv_udp_bind(&server, (const struct sockaddr*) &addr, 0); - ASSERT(r == 0); - - r = uv_udp_recv_start(&server, alloc_cb, sv_recv_cb); - ASSERT(r == 0); - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - - r = uv_udp_init(uv_default_loop(), &client); - ASSERT(r == 0); - - buf = uv_buf_init(buffer, sizeof(buffer)); - r = uv_udp_try_send(&client, &buf, 1, (const struct sockaddr*) &addr); - ASSERT(r == UV_EMSGSIZE); - - buf = uv_buf_init("EXIT", 4); - r = uv_udp_try_send(&client, &buf, 1, (const struct sockaddr*) &addr); - ASSERT(r == 4); - - uv_run(uv_default_loop(), UV_RUN_DEFAULT); - - ASSERT(close_cb_called == 2); - ASSERT(sv_recv_cb_called == 1); - - ASSERT(client.send_queue_size == 0); - ASSERT(server.send_queue_size == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -#endif /* !_WIN32 */ diff --git a/libuv/test/test-walk-handles.c b/libuv/test/test-walk-handles.c deleted file mode 100644 index 4b0ca6e..0000000 --- a/libuv/test/test-walk-handles.c +++ /dev/null @@ -1,77 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include - -static char magic_cookie[] = "magic cookie"; -static int seen_timer_handle; -static uv_timer_t timer; - - -static void walk_cb(uv_handle_t* handle, void* arg) { - ASSERT(arg == (void*)magic_cookie); - - if (handle == (uv_handle_t*)&timer) { - seen_timer_handle++; - } else { - ASSERT(0 && "unexpected handle"); - } -} - - -static void timer_cb(uv_timer_t* handle) { - ASSERT(handle == &timer); - - uv_walk(handle->loop, walk_cb, magic_cookie); - uv_close((uv_handle_t*)handle, NULL); -} - - -TEST_IMPL(walk_handles) { - uv_loop_t* loop; - int r; - - loop = uv_default_loop(); - - r = uv_timer_init(loop, &timer); - ASSERT(r == 0); - - r = uv_timer_start(&timer, timer_cb, 1, 0); - ASSERT(r == 0); - - /* Start event loop, expect to see the timer handle in walk_cb. */ - ASSERT(seen_timer_handle == 0); - r = uv_run(loop, UV_RUN_DEFAULT); - ASSERT(r == 0); - ASSERT(seen_timer_handle == 1); - - /* Loop is finished, walk_cb should not see our timer handle. */ - seen_timer_handle = 0; - uv_walk(loop, walk_cb, magic_cookie); - ASSERT(seen_timer_handle == 0); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/test/test-watcher-cross-stop.c b/libuv/test/test-watcher-cross-stop.c deleted file mode 100644 index 910ed0f..0000000 --- a/libuv/test/test-watcher-cross-stop.c +++ /dev/null @@ -1,103 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "uv.h" -#include "task.h" - -#include -#include - -/* NOTE: Number should be big enough to trigger this problem */ -static uv_udp_t sockets[2500]; -static uv_udp_send_t reqs[ARRAY_SIZE(sockets)]; -static char slab[1]; -static unsigned int recv_cb_called; -static unsigned int send_cb_called; -static unsigned int close_cb_called; - -static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) { - buf->base = slab; - buf->len = sizeof(slab); -} - - -static void recv_cb(uv_udp_t* handle, - ssize_t nread, - const uv_buf_t* buf, - const struct sockaddr* addr, - unsigned flags) { - recv_cb_called++; -} - - -static void send_cb(uv_udp_send_t* req, int status) { - send_cb_called++; -} - - -static void close_cb(uv_handle_t* handle) { - close_cb_called++; -} - - -TEST_IMPL(watcher_cross_stop) { - uv_loop_t* loop = uv_default_loop(); - unsigned int i; - struct sockaddr_in addr; - uv_buf_t buf; - char big_string[1024]; - - TEST_FILE_LIMIT(ARRAY_SIZE(sockets) + 32); - - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - memset(big_string, 'A', sizeof(big_string)); - buf = uv_buf_init(big_string, sizeof(big_string)); - - for (i = 0; i < ARRAY_SIZE(sockets); i++) { - ASSERT(0 == uv_udp_init(loop, &sockets[i])); - ASSERT(0 == uv_udp_bind(&sockets[i], - (const struct sockaddr*) &addr, - UV_UDP_REUSEADDR)); - ASSERT(0 == uv_udp_recv_start(&sockets[i], alloc_cb, recv_cb)); - ASSERT(0 == uv_udp_send(&reqs[i], - &sockets[i], - &buf, - 1, - (const struct sockaddr*) &addr, - send_cb)); - } - - while (recv_cb_called == 0) - uv_run(loop, UV_RUN_ONCE); - - for (i = 0; i < ARRAY_SIZE(sockets); i++) - uv_close((uv_handle_t*) &sockets[i], close_cb); - - ASSERT(recv_cb_called > 0); - - uv_run(loop, UV_RUN_DEFAULT); - - ASSERT(ARRAY_SIZE(sockets) == send_cb_called); - ASSERT(ARRAY_SIZE(sockets) == close_cb_called); - - MAKE_VALGRIND_HAPPY(); - return 0; -} diff --git a/libuv/uv.gyp b/libuv/uv.gyp deleted file mode 100644 index d93f66a..0000000 --- a/libuv/uv.gyp +++ /dev/null @@ -1,485 +0,0 @@ -{ - 'target_defaults': { - 'conditions': [ - ['OS != "win"', { - 'defines': [ - '_LARGEFILE_SOURCE', - '_FILE_OFFSET_BITS=64', - ], - 'conditions': [ - ['OS=="solaris"', { - 'cflags': [ '-pthreads' ], - }], - ['OS not in "solaris android"', { - 'cflags': [ '-pthread' ], - }], - ], - }], - ], - 'xcode_settings': { - 'WARNING_CFLAGS': [ '-Wall', '-Wextra', '-Wno-unused-parameter' ], - 'OTHER_CFLAGS': [ '-g', '--std=gnu89', '-pedantic' ], - } - }, - - 'targets': [ - { - 'target_name': 'libuv', - 'type': '<(uv_library)', - 'include_dirs': [ - 'include', - 'src/', - ], - 'direct_dependent_settings': { - 'include_dirs': [ 'include' ], - 'conditions': [ - ['OS != "win"', { - 'defines': [ - '_LARGEFILE_SOURCE', - '_FILE_OFFSET_BITS=64', - ], - }], - ['OS == "mac"', { - 'defines': [ '_DARWIN_USE_64_BIT_INODE=1' ], - }], - ['OS == "linux"', { - 'defines': [ '_POSIX_C_SOURCE=200112' ], - }], - ], - }, - 'sources': [ - 'common.gypi', - 'include/uv.h', - 'include/tree.h', - 'include/uv-errno.h', - 'include/uv-threadpool.h', - 'include/uv-version.h', - 'src/fs-poll.c', - 'src/heap-inl.h', - 'src/inet.c', - 'src/queue.h', - 'src/threadpool.c', - 'src/uv-common.c', - 'src/uv-common.h', - 'src/version.c' - ], - 'conditions': [ - [ 'OS=="win"', { - 'defines': [ - '_WIN32_WINNT=0x0600', - '_GNU_SOURCE', - ], - 'sources': [ - 'include/uv-win.h', - 'src/win/async.c', - 'src/win/atomicops-inl.h', - 'src/win/core.c', - 'src/win/dl.c', - 'src/win/error.c', - 'src/win/fs.c', - 'src/win/fs-event.c', - 'src/win/getaddrinfo.c', - 'src/win/getnameinfo.c', - 'src/win/handle.c', - 'src/win/handle-inl.h', - 'src/win/internal.h', - 'src/win/loop-watcher.c', - 'src/win/pipe.c', - 'src/win/thread.c', - 'src/win/poll.c', - 'src/win/process.c', - 'src/win/process-stdio.c', - 'src/win/req.c', - 'src/win/req-inl.h', - 'src/win/signal.c', - 'src/win/stream.c', - 'src/win/stream-inl.h', - 'src/win/tcp.c', - 'src/win/tty.c', - 'src/win/timer.c', - 'src/win/udp.c', - 'src/win/util.c', - 'src/win/winapi.c', - 'src/win/winapi.h', - 'src/win/winsock.c', - 'src/win/winsock.h', - ], - 'link_settings': { - 'libraries': [ - '-ladvapi32', - '-liphlpapi', - '-lpsapi', - '-lshell32', - '-lws2_32' - ], - }, - }, { # Not Windows i.e. POSIX - 'cflags': [ - '-g', - '--std=gnu89', - '-pedantic', - '-Wall', - '-Wextra', - '-Wno-unused-parameter', - ], - 'sources': [ - 'include/uv-unix.h', - 'include/uv-linux.h', - 'include/uv-sunos.h', - 'include/uv-darwin.h', - 'include/uv-bsd.h', - 'include/uv-aix.h', - 'src/unix/async.c', - 'src/unix/atomic-ops.h', - 'src/unix/core.c', - 'src/unix/dl.c', - 'src/unix/fs.c', - 'src/unix/getaddrinfo.c', - 'src/unix/getnameinfo.c', - 'src/unix/internal.h', - 'src/unix/loop.c', - 'src/unix/loop-watcher.c', - 'src/unix/pipe.c', - 'src/unix/poll.c', - 'src/unix/process.c', - 'src/unix/signal.c', - 'src/unix/spinlock.h', - 'src/unix/stream.c', - 'src/unix/tcp.c', - 'src/unix/thread.c', - 'src/unix/timer.c', - 'src/unix/tty.c', - 'src/unix/udp.c', - ], - 'link_settings': { - 'libraries': [ '-lm' ], - 'conditions': [ - ['OS=="solaris"', { - 'ldflags': [ '-pthreads' ], - }], - ['OS != "solaris" and OS != "android"', { - 'ldflags': [ '-pthread' ], - }], - ], - }, - 'conditions': [ - ['uv_library=="shared_library"', { - 'cflags': [ '-fPIC' ], - }], - ['uv_library=="shared_library" and OS!="mac"', { - 'link_settings': { - # Must correspond with UV_VERSION_MAJOR and UV_VERSION_MINOR - # in include/uv-version.h - 'libraries': [ '-Wl,-soname,libuv.so.1.0' ], - }, - }], - ], - }], - [ 'OS in "linux mac android"', { - 'sources': [ 'src/unix/proctitle.c' ], - }], - [ 'OS=="mac"', { - 'sources': [ - 'src/unix/darwin.c', - 'src/unix/fsevents.c', - 'src/unix/darwin-proctitle.c', - ], - 'defines': [ - '_DARWIN_USE_64_BIT_INODE=1', - '_DARWIN_UNLIMITED_SELECT=1', - ] - }], - [ 'OS!="mac"', { - # Enable on all platforms except OS X. The antique gcc/clang that - # ships with Xcode emits waaaay too many false positives. - 'cflags': [ '-Wstrict-aliasing' ], - }], - [ 'OS=="linux"', { - 'defines': [ '_GNU_SOURCE' ], - 'sources': [ - 'src/unix/linux-core.c', - 'src/unix/linux-inotify.c', - 'src/unix/linux-syscalls.c', - 'src/unix/linux-syscalls.h', - ], - 'link_settings': { - 'libraries': [ '-ldl', '-lrt' ], - }, - }], - [ 'OS=="android"', { - 'sources': [ - 'src/unix/linux-core.c', - 'src/unix/linux-inotify.c', - 'src/unix/linux-syscalls.c', - 'src/unix/linux-syscalls.h', - 'src/unix/pthread-fixes.c', - 'src/unix/android-ifaddrs.c' - ], - 'link_settings': { - 'libraries': [ '-ldl' ], - }, - }], - [ 'OS=="solaris"', { - 'sources': [ 'src/unix/sunos.c' ], - 'defines': [ - '__EXTENSIONS__', - '_XOPEN_SOURCE=500', - ], - 'link_settings': { - 'libraries': [ - '-lkstat', - '-lnsl', - '-lsendfile', - '-lsocket', - ], - }, - }], - [ 'OS=="aix"', { - 'sources': [ 'src/unix/aix.c' ], - 'defines': [ - '_ALL_SOURCE', - '_XOPEN_SOURCE=500', - '_LINUX_SOURCE_COMPAT', - ], - 'link_settings': { - 'libraries': [ - '-lperfstat', - ], - }, - }], - [ 'OS=="freebsd" or OS=="dragonflybsd"', { - 'sources': [ 'src/unix/freebsd.c' ], - }], - [ 'OS=="openbsd"', { - 'sources': [ 'src/unix/openbsd.c' ], - }], - [ 'OS=="netbsd"', { - 'sources': [ 'src/unix/netbsd.c' ], - }], - [ 'OS in "freebsd dragonflybsd openbsd netbsd".split()', { - 'link_settings': { - 'libraries': [ '-lkvm' ], - }, - }], - [ 'OS in "mac freebsd dragonflybsd openbsd netbsd".split()', { - 'sources': [ 'src/unix/kqueue.c' ], - }], - ['uv_library=="shared_library"', { - 'defines': [ 'BUILDING_UV_SHARED=1' ] - }], - ] - }, - - { - 'target_name': 'run-tests', - 'type': 'executable', - 'dependencies': [ 'libuv' ], - 'sources': [ - 'test/blackhole-server.c', - 'test/echo-server.c', - 'test/run-tests.c', - 'test/runner.c', - 'test/runner.h', - 'test/test-get-loadavg.c', - 'test/task.h', - 'test/test-active.c', - 'test/test-async.c', - 'test/test-async-null-cb.c', - 'test/test-callback-stack.c', - 'test/test-callback-order.c', - 'test/test-close-fd.c', - 'test/test-close-order.c', - 'test/test-connection-fail.c', - 'test/test-cwd-and-chdir.c', - 'test/test-default-loop-close.c', - 'test/test-delayed-accept.c', - 'test/test-error.c', - 'test/test-embed.c', - 'test/test-emfile.c', - 'test/test-fail-always.c', - 'test/test-fs.c', - 'test/test-fs-event.c', - 'test/test-get-currentexe.c', - 'test/test-get-memory.c', - 'test/test-getaddrinfo.c', - 'test/test-getnameinfo.c', - 'test/test-getsockname.c', - 'test/test-handle-fileno.c', - 'test/test-hrtime.c', - 'test/test-idle.c', - 'test/test-ip6-addr.c', - 'test/test-ipc.c', - 'test/test-ipc-send-recv.c', - 'test/test-list.h', - 'test/test-loop-handles.c', - 'test/test-loop-alive.c', - 'test/test-loop-close.c', - 'test/test-loop-stop.c', - 'test/test-loop-time.c', - 'test/test-loop-configure.c', - 'test/test-walk-handles.c', - 'test/test-watcher-cross-stop.c', - 'test/test-multiple-listen.c', - 'test/test-osx-select.c', - 'test/test-pass-always.c', - 'test/test-ping-pong.c', - 'test/test-pipe-bind-error.c', - 'test/test-pipe-connect-error.c', - 'test/test-pipe-getsockname.c', - 'test/test-pipe-sendmsg.c', - 'test/test-pipe-server-close.c', - 'test/test-pipe-close-stdout-read-stdin.c', - 'test/test-platform-output.c', - 'test/test-poll.c', - 'test/test-poll-close.c', - 'test/test-poll-close-doesnt-corrupt-stack.c', - 'test/test-poll-closesocket.c', - 'test/test-process-title.c', - 'test/test-ref.c', - 'test/test-run-nowait.c', - 'test/test-run-once.c', - 'test/test-semaphore.c', - 'test/test-shutdown-close.c', - 'test/test-shutdown-eof.c', - 'test/test-shutdown-twice.c', - 'test/test-signal.c', - 'test/test-signal-multiple-loops.c', - 'test/test-socket-buffer-size.c', - 'test/test-spawn.c', - 'test/test-fs-poll.c', - 'test/test-stdio-over-pipes.c', - 'test/test-tcp-bind-error.c', - 'test/test-tcp-bind6-error.c', - 'test/test-tcp-close.c', - 'test/test-tcp-close-accept.c', - 'test/test-tcp-close-while-connecting.c', - 'test/test-tcp-connect-error-after-write.c', - 'test/test-tcp-shutdown-after-write.c', - 'test/test-tcp-flags.c', - 'test/test-tcp-connect-error.c', - 'test/test-tcp-connect-timeout.c', - 'test/test-tcp-connect6-error.c', - 'test/test-tcp-open.c', - 'test/test-tcp-write-to-half-open-connection.c', - 'test/test-tcp-write-after-connect.c', - 'test/test-tcp-writealot.c', - 'test/test-tcp-try-write.c', - 'test/test-tcp-unexpected-read.c', - 'test/test-tcp-read-stop.c', - 'test/test-tcp-write-queue-order.c', - 'test/test-threadpool.c', - 'test/test-threadpool-cancel.c', - 'test/test-thread-equal.c', - 'test/test-mutexes.c', - 'test/test-thread.c', - 'test/test-barrier.c', - 'test/test-condvar.c', - 'test/test-timer-again.c', - 'test/test-timer-from-check.c', - 'test/test-timer.c', - 'test/test-tty.c', - 'test/test-udp-bind.c', - 'test/test-udp-dgram-too-big.c', - 'test/test-udp-ipv6.c', - 'test/test-udp-open.c', - 'test/test-udp-options.c', - 'test/test-udp-send-and-recv.c', - 'test/test-udp-send-immediate.c', - 'test/test-udp-send-unreachable.c', - 'test/test-udp-multicast-join.c', - 'test/test-udp-multicast-join6.c', - 'test/test-dlerror.c', - 'test/test-udp-multicast-ttl.c', - 'test/test-ip4-addr.c', - 'test/test-ip6-addr.c', - 'test/test-udp-multicast-interface.c', - 'test/test-udp-multicast-interface6.c', - 'test/test-udp-try-send.c', - ], - 'conditions': [ - [ 'OS=="win"', { - 'sources': [ - 'test/runner-win.c', - 'test/runner-win.h' - ], - 'libraries': [ '-lws2_32' ] - }, { # POSIX - 'defines': [ '_GNU_SOURCE' ], - 'sources': [ - 'test/runner-unix.c', - 'test/runner-unix.h', - ], - }], - [ 'OS=="solaris"', { # make test-fs.c compile, needs _POSIX_C_SOURCE - 'defines': [ - '__EXTENSIONS__', - '_XOPEN_SOURCE=500', - ], - }], - [ 'OS=="aix"', { # make test-fs.c compile, needs _POSIX_C_SOURCE - 'defines': [ - '_ALL_SOURCE', - '_XOPEN_SOURCE=500', - ], - }], - ], - 'msvs-settings': { - 'VCLinkerTool': { - 'SubSystem': 1, # /subsystem:console - }, - }, - }, - - { - 'target_name': 'run-benchmarks', - 'type': 'executable', - 'dependencies': [ 'libuv' ], - 'sources': [ - 'test/benchmark-async.c', - 'test/benchmark-async-pummel.c', - 'test/benchmark-fs-stat.c', - 'test/benchmark-getaddrinfo.c', - 'test/benchmark-list.h', - 'test/benchmark-loop-count.c', - 'test/benchmark-million-async.c', - 'test/benchmark-million-timers.c', - 'test/benchmark-multi-accept.c', - 'test/benchmark-ping-pongs.c', - 'test/benchmark-pound.c', - 'test/benchmark-pump.c', - 'test/benchmark-sizes.c', - 'test/benchmark-spawn.c', - 'test/benchmark-thread.c', - 'test/benchmark-tcp-write-batch.c', - 'test/benchmark-udp-pummel.c', - 'test/dns-server.c', - 'test/echo-server.c', - 'test/blackhole-server.c', - 'test/run-benchmarks.c', - 'test/runner.c', - 'test/runner.h', - 'test/task.h', - ], - 'conditions': [ - [ 'OS=="win"', { - 'sources': [ - 'test/runner-win.c', - 'test/runner-win.h', - ], - 'libraries': [ '-lws2_32' ] - }, { # POSIX - 'defines': [ '_GNU_SOURCE' ], - 'sources': [ - 'test/runner-unix.c', - 'test/runner-unix.h', - ] - }] - ], - 'msvs-settings': { - 'VCLinkerTool': { - 'SubSystem': 1, # /subsystem:console - }, - }, - }, - ] -} diff --git a/libuv/vcbuild.bat b/libuv/vcbuild.bat deleted file mode 100644 index d3b7aa1..0000000 --- a/libuv/vcbuild.bat +++ /dev/null @@ -1,145 +0,0 @@ -@echo off - -cd %~dp0 - -if /i "%1"=="help" goto help -if /i "%1"=="--help" goto help -if /i "%1"=="-help" goto help -if /i "%1"=="/help" goto help -if /i "%1"=="?" goto help -if /i "%1"=="-?" goto help -if /i "%1"=="--?" goto help -if /i "%1"=="/?" goto help - -@rem Process arguments. -set config= -set target=Build -set noprojgen= -set nobuild= -set run= -set target_arch=ia32 -set vs_toolset=x86 -set platform=WIN32 -set library=static_library - -:next-arg -if "%1"=="" goto args-done -if /i "%1"=="debug" set config=Debug&goto arg-ok -if /i "%1"=="release" set config=Release&goto arg-ok -if /i "%1"=="test" set run=run-tests.exe&goto arg-ok -if /i "%1"=="bench" set run=run-benchmarks.exe&goto arg-ok -if /i "%1"=="clean" set target=Clean&goto arg-ok -if /i "%1"=="noprojgen" set noprojgen=1&goto arg-ok -if /i "%1"=="nobuild" set nobuild=1&goto arg-ok -if /i "%1"=="x86" set target_arch=ia32&set platform=WIN32&set vs_toolset=x86&goto arg-ok -if /i "%1"=="ia32" set target_arch=ia32&set platform=WIN32&set vs_toolset=x86&goto arg-ok -if /i "%1"=="x64" set target_arch=x64&set platform=x64&set vs_toolset=x64&goto arg-ok -if /i "%1"=="shared" set library=shared_library&goto arg-ok -if /i "%1"=="static" set library=static_library&goto arg-ok -:arg-ok -shift -goto next-arg -:args-done - -if defined WindowsSDKDir goto select-target -if defined VCINSTALLDIR goto select-target - -@rem Look for Visual Studio 2013 -if not defined VS120COMNTOOLS goto vc-set-2012 -if not exist "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2012 -call "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" %vs_toolset% -set GYP_MSVS_VERSION=2013 -goto select-target - -:vc-set-2012 -@rem Look for Visual Studio 2012 -if not defined VS110COMNTOOLS goto vc-set-2010 -if not exist "%VS110COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2010 -call "%VS110COMNTOOLS%\..\..\vc\vcvarsall.bat" %vs_toolset% -set GYP_MSVS_VERSION=2012 -goto select-target - -:vc-set-2010 -@rem Look for Visual Studio 2010 -if not defined VS100COMNTOOLS goto vc-set-2008 -if not exist "%VS100COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2008 -call "%VS100COMNTOOLS%\..\..\vc\vcvarsall.bat" %vs_toolset% -set GYP_MSVS_VERSION=2010 -goto select-target - -:vc-set-2008 -@rem Look for Visual Studio 2008 -if not defined VS90COMNTOOLS goto vc-set-notfound -if not exist "%VS90COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-notfound -call "%VS90COMNTOOLS%\..\..\vc\vcvarsall.bat" %vs_toolset% -set GYP_MSVS_VERSION=2008 -goto select-target - -:vc-set-notfound -echo Warning: Visual Studio not found - -:select-target -if not "%config%"=="" goto project-gen -if "%run%"=="run-tests.exe" set config=Debug& goto project-gen -if "%run%"=="run-benchmarks.exe" set config=Release& goto project-gen -set config=Debug - -:project-gen -@rem Skip project generation if requested. -if defined noprojgen goto msbuild - -@rem Generate the VS project. -if exist build\gyp goto have_gyp -echo git clone https://git.chromium.org/external/gyp.git build/gyp -git clone https://git.chromium.org/external/gyp.git build/gyp -if errorlevel 1 goto gyp_install_failed -goto have_gyp - -:gyp_install_failed -echo Failed to download gyp. Make sure you have git installed, or -echo manually install gyp into %~dp0build\gyp. -exit /b 1 - -:have_gyp -if not defined PYTHON set PYTHON=python -"%PYTHON%" gyp_uv.py -Dtarget_arch=%target_arch% -Duv_library=%library% -if errorlevel 1 goto create-msvs-files-failed -if not exist uv.sln goto create-msvs-files-failed -echo Project files generated. - -:msbuild -@rem Skip project generation if requested. -if defined nobuild goto run - -@rem Check if VS build env is available -if defined VCINSTALLDIR goto msbuild-found -if defined WindowsSDKDir goto msbuild-found -echo Build skipped. To build, this file needs to run from VS cmd prompt. -goto run - -@rem Build the sln with msbuild. -:msbuild-found -msbuild uv.sln /t:%target% /p:Configuration=%config% /p:Platform="%platform%" /clp:NoSummary;NoItemAndPropertyList;Verbosity=minimal /nologo -if errorlevel 1 exit /b 1 - -:run -@rem Run tests if requested. -if "%run%"=="" goto exit -if not exist %config%\%run% goto exit -echo running '%config%\%run%' -%config%\%run% -goto exit - -:create-msvs-files-failed -echo Failed to create vc project files. -exit /b 1 - -:help -echo vcbuild.bat [debug/release] [test/bench] [clean] [noprojgen] [nobuild] [x86/x64] [static/shared] -echo Examples: -echo vcbuild.bat : builds debug build -echo vcbuild.bat test : builds debug build and runs tests -echo vcbuild.bat release bench: builds release build and runs benchmarks -goto exit - -:exit diff --git a/source/about.rst b/source/about.rst deleted file mode 100644 index 8efa517..0000000 --- a/source/about.rst +++ /dev/null @@ -1,25 +0,0 @@ -About -===== - -`Nikhil Marathe `_ started writing this book one -afternoon (June 16, 2012) when he didn't feel like programming. He had recently -been stung by the lack of good documentation on libuv while working on -`node-taglib `_. Although reference -documentation was present, there were no comprehensive tutorials. This book is -the output of that need and tries to be accurate. That said, the book may have -mistakes. Pull requests are encouraged. You may also `email him -`_ if you find an error. - -Nikhil is indebted to Marc Lehmann's comprehensive `man page -`_ about libev which -describes much of the semantics of the two libraries. - -This book was made using `Sphinx `_ and `vim -`_. - -Licensing ---------- - -The contents of this book are licensed as `Creative Commons - Attribution -`_. All code is in the **public -domain**. diff --git a/source/basics.rst b/source/basics.rst deleted file mode 100644 index 55798bf..0000000 --- a/source/basics.rst +++ /dev/null @@ -1,188 +0,0 @@ -Basics of libuv -=============== - -libuv enforces an **asynchronous**, **event-driven** style of programming. Its -core job is to provide an event loop and callback based notifications of I/O -and other activities. libuv offers core utilities like timers, non-blocking -networking support, asynchronous file system access, child processes and more. - -Event loops ------------ - -In event-driven programming, an application expresses interest in certain events -and respond to them when they occur. The responsibility of gathering events -from the operating system or monitoring other sources of events is handled by -libuv, and the user can register callbacks to be invoked when an event occurs. -The event-loop usually keeps running *forever*. In pseudocode: - -.. code-block:: python - - while there are still events to process: - e = get the next event - if there is a callback associated with e: - call the callback - -Some examples of events are: - -* File is ready for writing -* A socket has data ready to be read -* A timer has timed out - -This event loop is encapsulated by ``uv_run()`` -- the end-all function when using -libuv. - -The most common activity of systems programs is to deal with input and output, -rather than a lot of number-crunching. The problem with using conventional -input/output functions (``read``, ``fprintf``, etc.) is that they are -**blocking**. The actual write to a hard disk or reading from a network, takes -a disproportionately long time compared to the speed of the processor. The -functions don't return until the task is done, so that your program is doing -nothing. For programs which require high performance this is a major roadblock -as other activities and other I/O operations are kept waiting. - -One of the standard solutions is to use threads. Each blocking I/O operation is -started in a separate thread (or in a thread pool). When the blocking function -gets invoked in the thread, the processor can schedule another thread to run, -which actually needs the CPU. - -The approach followed by libuv uses another style, which is the **asynchronous, -non-blocking** style. Most modern operating systems provide event notification -subsystems. For example, a normal ``read`` call on a socket would block until -the sender actually sent something. Instead, the application can request the -operating system to watch the socket and put an event notification in the -queue. The application can inspect the events at its convenience (perhaps doing -some number crunching before to use the processor to the maximum) and grab the -data. It is **asynchronous** because the application expressed interest at one -point, then used the data at another point (in time and space). It is -**non-blocking** because the application process was free to do other tasks. -This fits in well with libuv's event-loop approach, since the operating system -events can be treated as just another libuv event. The non-blocking ensures -that other events can continue to be handled as fast as they come in [#]_. - -.. NOTE:: - - How the I/O is run in the background is not of our concern, but due to the - way our computer hardware works, with the thread as the basic unit of the - processor, libuv and OSes will usually run background/worker threads and/or - polling to perform tasks in a non-blocking manner. - -Bert Belder, one of the libuv core developers has a small video explaining the -architecture of libuv and its background. If you have no prior experience with -either libuv or libev, it is a quick, useful watch. - -libuv's event loop is explained in more detail in the `documentation -`_. - -.. raw:: html - - - -Hello World ------------ - -With the basics out of the way, lets write our first libuv program. It does -nothing, except start a loop which will exit immediately. - -.. rubric:: helloworld/main.c -.. literalinclude:: ../code/helloworld/main.c - :linenos: - -This program quits immediately because it has no events to process. A libuv -event loop has to be told to watch out for events using the various API -functions. - -Starting with libuv v1.0, users should allocate the memory for the loops before -initializing it with ``uv_loop_init(uv_loop_t *)``. This allows you to plug in -custom memory management. Remember to de-initialize the loop using -``uv_loop_close(uv_loop_t *)`` and then delete the storage. The examples never -close loops since the program quits after the loop ends and the system will -reclaim memory. Production grade projects, especially long running systems -programs, should take care to release correctly. - -Default loop -++++++++++++ - -A default loop is provided by libuv and can be accessed using -``uv_default_loop()``. You should use this loop if you only want a single -loop. - -.. note:: - - node.js uses the default loop as its main loop. If you are writing bindings - you should be aware of this. - -.. _libuv-error-handling: - -Error handling --------------- - -Initialization functions or synchronous functions which may fail return a negative number on error. Async functions that may fail will pass a status parameter to their callbacks. The error messages are defined as ``UV_E*`` `constants`_. - -.. _constants: http://docs.libuv.org/en/v1.x/errors.html#error-constants - -You can use the ``uv_strerror(int)`` and ``uv_err_name(int)`` functions -to get a ``const char *`` describing the error or the error name respectively. - -I/O read callbacks (such as for files and sockets) are passed a parameter ``nread``. If ``nread`` is less than 0, there was an error (UV_EOF is the end of file error, which you may want to handle differently). - -Handles and Requests --------------------- - -libuv works by the user expressing interest in particular events. This is -usually done by creating a **handle** to an I/O device, timer or process. -Handles are opaque structs named as ``uv_TYPE_t`` where type signifies what the -handle is used for. - -.. rubric:: libuv watchers -.. literalinclude:: ../libuv/include/uv.h - :lines: 197-230 - -Handles represent long-lived objects. Async operations on such handles are -identified using **requests**. A request is short-lived (usually used across -only one callback) and usually indicates one I/O operation on a handle. -Requests are used to preserve context between the initiation and the callback -of individual actions. For example, an UDP socket is represented by -a ``uv_udp_t``, while individual writes to the socket use a ``uv_udp_send_t`` -structure that is passed to the callback after the write is done. - -Handles are setup by a corresponding:: - - uv_TYPE_init(uv_loop_t *, uv_TYPE_t *) - -function. - -Callbacks are functions which are called by libuv whenever an event the watcher -is interested in has taken place. Application specific logic will usually be -implemented in the callback. For example, an IO watcher's callback will receive -the data read from a file, a timer callback will be triggered on timeout and so -on. - -Idling -++++++ - -Here is an example of using an idle handle. The callback is called once on -every turn of the event loop. A use case for idle handles is discussed in -:doc:`utilities`. Let us use an idle watcher to look at the watcher life cycle -and see how ``uv_run()`` will now block because a watcher is present. The idle -watcher is stopped when the count is reached and ``uv_run()`` exits since no -event watchers are active. - -.. rubric:: idle-basic/main.c -.. literalinclude:: ../code/idle-basic/main.c - :emphasize-lines: 6,10,14-17 - -Storing context -+++++++++++++++ - -In callback based programming style you'll often want to pass some 'context' -- -application specific information -- between the call site and the callback. All -handles and requests have a ``void* data`` member which you can set to the -context and cast back in the callback. This is a common pattern used throughout -the C library ecosystem. In addition ``uv_loop_t`` also has a similar data -member. - ----- - -.. [#] Depending on the capacity of the hardware of course. diff --git a/source/conf.py b/source/conf.py index 01fa2c3..636b18f 100644 --- a/source/conf.py +++ b/source/conf.py @@ -25,10 +25,10 @@ # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.todo', 'sphinx.ext.pngmath', 'sphinx.ext.mathjax', 'sphinx.ext.ifconfig'] +extensions = [] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = [] # The suffix of source filenames. source_suffix = '.rst' @@ -122,7 +122,7 @@ # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. diff --git a/source/eventloops.rst b/source/eventloops.rst deleted file mode 100644 index 2413163..0000000 --- a/source/eventloops.rst +++ /dev/null @@ -1,48 +0,0 @@ -Advanced event loops -==================== - -libuv provides considerable user control over event loops, and you can achieve -interesting results by juggling multiple loops. You can also embed libuv's -event loop into another event loop based library -- imagine a Qt based UI, and -Qt's event loop driving a libuv backend which does intensive system level -tasks. - -Stopping an event loop -~~~~~~~~~~~~~~~~~~~~~~ - -``uv_stop()`` can be used to stop an event loop. The earliest the loop will -stop running is *on the next iteration*, possibly later. This means that events -that are ready to be processed in this iteration of the loop will still be -processed, so ``uv_stop()`` can't be used as a kill switch. When ``uv_stop()`` -is called, the loop **won't** block for i/o on this iteration. The semantics of -these things can be a bit difficult to understand, so let's look at -``uv_run()`` where all the control flow occurs. - -.. rubric:: src/unix/core.c - uv_run -.. literalinclude:: ../libuv/src/unix/core.c - :linenos: - :lines: 304-324 - :emphasize-lines: 10,19,21 - -``stop_flag`` is set by ``uv_stop()``. Now all libuv callbacks are invoked -within the event loop, which is why invoking ``uv_stop()`` in them will still -lead to this iteration of the loop occurring. First libuv updates timers, then -runs pending timer, idle and prepare callbacks, and invokes any pending I/O -callbacks. If you were to call ``uv_stop()`` in any of them, ``stop_flag`` -would be set. This causes ``uv_backend_timeout()`` to return ``0``, which is -why the loop does not block on I/O. If on the other hand, you called -``uv_stop()`` in one of the check handlers, I/O has already finished and is not -affected. - -``uv_stop()`` is useful to shutdown a loop when a result has been computed or -there is an error, without having to ensure that all handlers are stopped one -by one. - -Here is a simple example that stops the loop and demonstrates how the current -iteration of the loop still takes places. - -.. rubric:: uvstop/main.c -.. literalinclude:: ../code/uvstop/main.c - :linenos: - :emphasize-lines: 11 - diff --git a/source/filesystem.rst b/source/filesystem.rst deleted file mode 100644 index f4004c4..0000000 --- a/source/filesystem.rst +++ /dev/null @@ -1,287 +0,0 @@ -Filesystem -========== - -Simple filesystem read/write is achieved using the ``uv_fs_*`` functions and the -``uv_fs_t`` struct. - -.. note:: - - The libuv filesystem operations are different from :doc:`socket operations - `. Socket operations use the non-blocking operations provided - by the operating system. Filesystem operations use blocking functions - internally, but invoke these functions in a `thread pool`_ and notify - watchers registered with the event loop when application interaction is - required. - -.. _thread pool: http://docs.libuv.org/en/v1.x/threadpool.html#thread-pool-work-scheduling - -All filesystem functions have two forms - *synchronous* and *asynchronous*. - -The *synchronous* forms automatically get called (and **block**) if the -callback is null. The return value of functions is a :ref:`libuv error code -`. This is usually only useful for synchronous calls. -The *asynchronous* form is called when a callback is passed and the return -value is 0. - -Reading/Writing files ---------------------- - -A file descriptor is obtained using - -.. code-block:: c - - int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int mode, uv_fs_cb cb) - -``flags`` and ``mode`` are standard -`Unix flags `_. -libuv takes care of converting to the appropriate Windows flags. - -File descriptors are closed using - -.. code-block:: c - - int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) - - -Filesystem operation callbacks have the signature: - -.. code-block:: c - - void callback(uv_fs_t* req); - -Let's see a simple implementation of ``cat``. We start with registering -a callback for when the file is opened: - -.. rubric:: uvcat/main.c - opening a file -.. literalinclude:: ../code/uvcat/main.c - :linenos: - :lines: 41-53 - :emphasize-lines: 4, 6-7 - -The ``result`` field of a ``uv_fs_t`` is the file descriptor in case of the -``uv_fs_open`` callback. If the file is successfully opened, we start reading it. - -.. rubric:: uvcat/main.c - read callback -.. literalinclude:: ../code/uvcat/main.c - :linenos: - :lines: 26-40 - :emphasize-lines: 2,8,12 - -In the case of a read call, you should pass an *initialized* buffer which will -be filled with data before the read callback is triggered. The ``uv_fs_*`` -operations map almost directly to certain POSIX functions, so EOF is indicated -in this case by ``result`` being 0. In the case of streams or pipes, the -``UV_EOF`` constant would have been passed as a status instead. - -Here you see a common pattern when writing asynchronous programs. The -``uv_fs_close()`` call is performed synchronously. *Usually tasks which are -one-off, or are done as part of the startup or shutdown stage are performed -synchronously, since we are interested in fast I/O when the program is going -about its primary task and dealing with multiple I/O sources*. For solo tasks -the performance difference usually is negligible and may lead to simpler code. - -Filesystem writing is similarly simple using ``uv_fs_write()``. *Your callback -will be triggered after the write is complete*. In our case the callback -simply drives the next read. Thus read and write proceed in lockstep via -callbacks. - -.. rubric:: uvcat/main.c - write callback -.. literalinclude:: ../code/uvcat/main.c - :linenos: - :lines: 16-24 - :emphasize-lines: 6 - -.. warning:: - - Due to the way filesystems and disk drives are configured for performance, - a write that 'succeeds' may not be committed to disk yet. - -We set the dominos rolling in ``main()``: - -.. rubric:: uvcat/main.c -.. literalinclude:: ../code/uvcat/main.c - :linenos: - :lines: 55- - :emphasize-lines: 2 - -.. warning:: - - The ``uv_fs_req_cleanup()`` function must always be called on filesystem - requests to free internal memory allocations in libuv. - -Filesystem operations ---------------------- - -All the standard filesystem operations like ``unlink``, ``rmdir``, ``stat`` are -supported asynchronously and have intuitive argument order. They follow the -same patterns as the read/write/open calls, returning the result in the -``uv_fs_t.result`` field. The full list: - -.. rubric:: Filesystem operations -.. literalinclude:: ../libuv/include/uv.h - :lines: 1084-1195 - -.. _buffers-and-streams: - -Buffers and Streams -------------------- - -The basic I/O handle in libuv is the stream (``uv_stream_t``). TCP sockets, UDP -sockets, and pipes for file I/O and IPC are all treated as stream subclasses. - -Streams are initialized using custom functions for each subclass, then operated -upon using - -.. code-block:: c - - int uv_read_start(uv_stream_t*, uv_alloc_cb alloc_cb, uv_read_cb read_cb); - int uv_read_stop(uv_stream_t*); - int uv_write(uv_write_t* req, uv_stream_t* handle, - const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb); - -The stream based functions are simpler to use than the filesystem ones and -libuv will automatically keep reading from a stream when ``uv_read_start()`` is -called once, until ``uv_read_stop()`` is called. - -The discrete unit of data is the buffer -- ``uv_buf_t``. This is simply -a collection of a pointer to bytes (``uv_buf_t.base``) and the length -(``uv_buf_t.len``). The ``uv_buf_t`` is lightweight and passed around by value. -What does require management is the actual bytes, which have to be allocated -and freed by the application. - -.. ERROR:: - - THIS PROGRAM DOES NOT ALWAYS WORK, NEED SOMETHING BETTER** - -To demonstrate streams we will need to use ``uv_pipe_t``. This allows streaming -local files [#]_. Here is a simple tee utility using libuv. Doing all operations -asynchronously shows the power of evented I/O. The two writes won't block each -other, but we have to be careful to copy over the buffer data to ensure we don't -free a buffer until it has been written. - -The program is to be executed as:: - - ./uvtee - -We start off opening pipes on the files we require. libuv pipes to a file are -opened as bidirectional by default. - -.. rubric:: uvtee/main.c - read on pipes -.. literalinclude:: ../code/uvtee/main.c - :linenos: - :lines: 61-80 - :emphasize-lines: 4,5,15 - -The third argument of ``uv_pipe_init()`` should be set to 1 for IPC using named -pipes. This is covered in :doc:`processes`. The ``uv_pipe_open()`` call -associates the pipe with the file descriptor, in this case ``0`` (standard -input). - -We start monitoring ``stdin``. The ``alloc_buffer`` callback is invoked as new -buffers are required to hold incoming data. ``read_stdin`` will be called with -these buffers. - -.. rubric:: uvtee/main.c - reading buffers -.. literalinclude:: ../code/uvtee/main.c - :linenos: - :lines: 19-22,44-60 - -The standard ``malloc`` is sufficient here, but you can use any memory allocation -scheme. For example, node.js uses its own slab allocator which associates -buffers with V8 objects. - -The read callback ``nread`` parameter is less than 0 on any error. This error -might be EOF, in which case we close all the streams, using the generic close -function ``uv_close()`` which deals with the handle based on its internal type. -Otherwise ``nread`` is a non-negative number and we can attempt to write that -many bytes to the output streams. Finally remember that buffer allocation and -deallocation is application responsibility, so we free the data. - -The allocation callback may return a buffer with length zero if it fails to -allocate memory. In this case, the read callback is invoked with error -UV_ENOBUFS. libuv will continue to attempt to read the stream though, so you -must explicitly call ``uv_close()`` if you want to stop when allocation fails. - -The read callback may be called with ``nread = 0``, indicating that at this -point there is nothing to be read. Most applications will just ignore this. - -.. rubric:: uvtee/main.c - Write to pipe -.. literalinclude:: ../code/uvtee/main.c - :linenos: - :lines: 9-13,23-42 - -``write_data()`` makes a copy of the buffer obtained from read. This buffer -does not get passed through to the write callback trigged on write completion. To -get around this we wrap a write request and a buffer in ``write_req_t`` and -unwrap it in the callbacks. We make a copy so we can free the two buffers from -the two calls to ``write_data`` independently of each other. While acceptable -for a demo program like this, you'll probably want smarter memory management, -like reference counted buffers or a pool of buffers in any major application. - -.. WARNING:: - - If your program is meant to be used with other programs it may knowingly or - unknowingly be writing to a pipe. This makes it susceptible to `aborting on - receiving a SIGPIPE`_. It is a good idea to insert:: - - signal(SIGPIPE, SIG_IGN) - - in the initialization stages of your application. - -.. _aborting on receiving a SIGPIPE: http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#The_special_problem_of_SIGPIPE - -File change events ------------------- - -All modern operating systems provide APIs to put watches on individual files or -directories and be informed when the files are modified. libuv wraps common -file change notification libraries [#fsnotify]_. This is one of the more -inconsistent parts of libuv. File change notification systems are themselves -extremely varied across platforms so getting everything working everywhere is -difficult. To demonstrate, I'm going to build a simple utility which runs -a command whenever any of the watched files change:: - - ./onchange [file2] ... - -The file change notification is started using ``uv_fs_event_init()``: - -.. rubric:: onchange/main.c - The setup -.. literalinclude:: ../code/onchange/main.c - :linenos: - :lines: 26- - :emphasize-lines: 15 - -The third argument is the actual file or directory to monitor. The last -argument, ``flags``, can be: - -.. literalinclude:: ../libuv/include/uv.h - :lines: 1299, 1308, 1315 - -``UV_FS_EVENT_WATCH_ENTRY`` and ``UV_FS_EVENT_STAT`` don't do anything (yet). -``UV_FS_EVENT_RECURSIVE`` will start watching subdirectories as well on -supported platforms. - -The callback will receive the following arguments: - - #. ``uv_fs_event_t *handle`` - The handle. The ``path`` field of the handle - is the file on which the watch was set. - #. ``const char *filename`` - If a directory is being monitored, this is the - file which was changed. Only non-``null`` on Linux and Windows. May be ``null`` - even on those platforms. - #. ``int flags`` - one of ``UV_RENAME`` or ``UV_CHANGE``, or a bitwise OR of - both. - #. ``int status`` - Currently 0. - -In our example we simply print the arguments and run the command using -``system()``. - -.. rubric:: onchange/main.c - file change notification callback -.. literalinclude:: ../code/onchange/main.c - :linenos: - :lines: 9-24 - ----- - -.. [#fsnotify] inotify on Linux, FSEvents on Darwin, kqueue on BSDs, - ReadDirectoryChangesW on Windows, event ports on Solaris, unsupported on Cygwin -.. [#] see :ref:`pipes` diff --git a/source/index.rst b/source/index.rst index 5c9a2b6..81d2f6e 100644 --- a/source/index.rst +++ b/source/index.rst @@ -1,36 +1,4 @@ -.. An Introduction to libuv documentation master file, created by - sphinx-quickstart on Sat Jun 16 16:39:14 2012. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. +Content Moved +============= -Table of Contents -================= - -.. toctree:: - :maxdepth: 2 - - introduction - basics - filesystem - networking - threads - processes - eventloops - utilities - about - -Alternate formats ------------------ - -The book is also available in: - -.. raw:: html - - +Now maintained at . diff --git a/source/introduction.rst b/source/introduction.rst deleted file mode 100644 index f57cdd9..0000000 --- a/source/introduction.rst +++ /dev/null @@ -1,75 +0,0 @@ -Introduction -============ - -This 'book' is a small set of tutorials about using libuv_ as -a high performance evented I/O library which offers the same API on Windows and Unix. - -It is meant to cover the main areas of libuv, but is not a comprehensive -reference discussing every function and data structure. The `official libuv -documentation`_ may be consulted for full details. - -.. _official libuv documentation: http://docs.libuv.org/en/v1.x/ - -This book is still a work in progress, so sections may be incomplete, but -I hope you will enjoy it as it grows. - -Who this book is for --------------------- - -If you are reading this book, you are either: - -1) a systems programmer, creating low-level programs such as daemons or network - services and clients. You have found that the event loop approach is well - suited for your application and decided to use libuv. - -2) a node.js module writer, who wants to wrap platform APIs - written in C or C++ with a set of (a)synchronous APIs that are exposed to - JavaScript. You will use libuv purely in the context of node.js. For - this you will require some other resources as the book does not cover parts - specific to v8/node.js. - -This book assumes that you are comfortable with the C programming language. - -Background ----------- - -The node.js_ project began in 2009 as a JavaScript environment decoupled -from the browser. Using Google's V8_ and Marc Lehmann's libev_, node.js -combined a model of I/O -- evented -- with a language that was well suited to -the style of programming; due to the way it had been shaped by browsers. As -node.js grew in popularity, it was important to make it work on Windows, but -libev ran only on Unix. The Windows equivalent of kernel event notification -mechanisms like kqueue or (e)poll is IOCP. libuv was an abstraction around libev -or IOCP depending on the platform, providing users an API based on libev. -In the node-v0.9.0 version of libuv `libev was removed`_. - -Since then libuv has continued to mature and become a high quality standalone -library for system programming. Users outside of node.js include Mozilla's -Rust_ programming language, and a variety_ of language bindings. - -This book and the code is based on libuv version `v1.3.0`_. - -Code ----- - -All the code from this book is included as part of the source of the book on -Github. `Clone`_/`Download`_ the book, then build libuv:: - - cd libuv - ./autogen.sh - ./configure - make - -There is no need to ``make install``. To build the examples run ``make`` in the -``code/`` directory. - -.. _Clone: https://github.com/nikhilm/uvbook -.. _Download: https://github.com/nikhilm/uvbook/downloads -.. _v1.3.0: https://github.com/libuv/libuv/tags -.. _V8: http://code.google.com/p/v8/ -.. _libev: http://software.schmorp.de/pkg/libev.html -.. _libuv: https://github.com/libuv/libuv -.. _node.js: http://www.nodejs.org -.. _libev was removed: https://github.com/joyent/libuv/issues/485 -.. _Rust: http://rust-lang.org -.. _variety: https://github.com/libuv/libuv/wiki/Projects-that-use-libuv diff --git a/source/networking.rst b/source/networking.rst deleted file mode 100644 index f3463df..0000000 --- a/source/networking.rst +++ /dev/null @@ -1,249 +0,0 @@ -Networking -========== - -Networking in libuv is not much different from directly using the BSD socket -interface, some things are easier, all are non-blocking, but the concepts stay -the same. In addition libuv offers utility functions to abstract the annoying, -repetitive and low-level tasks like setting up sockets using the BSD socket -structures, DNS lookup, and tweaking various socket parameters. - -The ``uv_tcp_t`` and ``uv_udp_t`` structures are used for network I/O. - -.. NOTE:: - - The code samples in this chapter exist to show certain libuv APIs. They are - not examples of good quality code. They leak memory and don't always close - connections properly. - -TCP ---- - -TCP is a connection oriented, stream protocol and is therefore based on the -libuv streams infrastructure. - -Server -++++++ - -Server sockets proceed by: - -1. ``uv_tcp_init`` the TCP handle. -2. ``uv_tcp_bind`` it. -3. Call ``uv_listen`` on the handle to have a callback invoked whenever a new - connection is established by a client. -4. Use ``uv_accept`` to accept the connection. -5. Use :ref:`stream operations ` to communicate with the - client. - -Here is a simple echo server - -.. rubric:: tcp-echo-server/main.c - The listen socket -.. literalinclude:: ../code/tcp-echo-server/main.c - :linenos: - :lines: 68- - :emphasize-lines: 4-5,7-10 - -You can see the utility function ``uv_ip4_addr`` being used to convert from -a human readable IP address, port pair to the sockaddr_in structure required by -the BSD socket APIs. The reverse can be obtained using ``uv_ip4_name``. - -.. NOTE:: - - There are ``uv_ip6_*`` analogues for the ip4 functions. - -Most of the setup functions are synchronous since they are CPU-bound. -``uv_listen`` is where we return to libuv's callback style. The second -arguments is the backlog queue -- the maximum length of queued connections. - -When a connection is initiated by clients, the callback is required to set up -a handle for the client socket and associate the handle using ``uv_accept``. -In this case we also establish interest in reading from this stream. - -.. rubric:: tcp-echo-server/main.c - Accepting the client -.. literalinclude:: ../code/tcp-echo-server/main.c - :linenos: - :lines: 51-66 - :emphasize-lines: 9-10 - -The remaining set of functions is very similar to the streams example and can -be found in the code. Just remember to call ``uv_close`` when the socket isn't -required. This can be done even in the ``uv_listen`` callback if you are not -interested in accepting the connection. - -Client -++++++ - -Where you do bind/listen/accept on the server, on the client side it's simply -a matter of calling ``uv_tcp_connect``. The same ``uv_connect_cb`` style -callback of ``uv_listen`` is used by ``uv_tcp_connect``. Try:: - - uv_tcp_t* socket = (uv_tcp_t*)malloc(sizeof(uv_tcp_t)); - uv_tcp_init(loop, socket); - - uv_connect_t* connect = (uv_connect_t*)malloc(sizeof(uv_connect_t)); - - struct sockaddr_in dest; - uv_ip4_addr("127.0.0.1", 80, &dest); - - uv_tcp_connect(connect, socket, (const struct sockaddr*)&dest, on_connect); - -where ``on_connect`` will be called after the connection is established. The -callback receives the ``uv_connect_t`` struct, which has a member ``.handle`` -pointing to the socket. - -UDP ---- - -The `User Datagram Protocol`_ offers connectionless, unreliable network -communication. Hence libuv doesn't offer a stream. Instead libuv provides -non-blocking UDP support via the `uv_udp_t` handle (for receiving) and -`uv_udp_send_t` request (for sending) and related functions. That said, the -actual API for reading/writing is very similar to normal stream reads. To look -at how UDP can be used, the example shows the first stage of obtaining an IP -address from a `DHCP`_ server -- DHCP Discover. - -.. note:: - - You will have to run `udp-dhcp` as **root** since it uses well known port - numbers below 1024. - -.. rubric:: udp-dhcp/main.c - Setup and send UDP packets -.. literalinclude:: ../code/udp-dhcp/main.c - :linenos: - :lines: 7-11,104- - :emphasize-lines: 8,10-11,17-18,21 - -.. note:: - - The IP address ``0.0.0.0`` is used to bind to all interfaces. The IP - address ``255.255.255.255`` is a broadcast address meaning that packets - will be sent to all interfaces on the subnet. port ``0`` means that the OS - randomly assigns a port. - -First we setup the receiving socket to bind on all interfaces on port 68 (DHCP -client) and start a read on it. This will read back responses from any DHCP -server that replies. We use the UV_UDP_REUSEADDR flag to play nice with any -other system DHCP clients that are running on this computer on the same port. -Then we setup a similar send socket and use ``uv_udp_send`` to send -a *broadcast message* on port 67 (DHCP server). - -It is **necessary** to set the broadcast flag, otherwise you will get an -``EACCES`` error [#]_. The exact message being sent is not relevant to this -book and you can study the code if you are interested. As usual the read and -write callbacks will receive a status code of < 0 if something went wrong. - -Since UDP sockets are not connected to a particular peer, the read callback -receives an extra parameter about the sender of the packet. - -``nread`` may be zero if there is no more data to be read. If ``addr`` is NULL, -it indicates there is nothing to read (the callback shouldn't do anything), if -not NULL, it indicates that an empty datagram was received from the host at -``addr``. The ``flags`` parameter may be ``UV_UDP_PARTIAL`` if the buffer -provided by your allocator was not large enough to hold the data. *In this case -the OS will discard the data that could not fit* (That's UDP for you!). - -.. rubric:: udp-dhcp/main.c - Reading packets -.. literalinclude:: ../code/udp-dhcp/main.c - :linenos: - :lines: 17-40 - :emphasize-lines: 1,23 - -UDP Options -+++++++++++ - -Time-to-live -~~~~~~~~~~~~ - -The TTL of packets sent on the socket can be changed using ``uv_udp_set_ttl``. - -IPv6 stack only -~~~~~~~~~~~~~~~ - -IPv6 sockets can be used for both IPv4 and IPv6 communication. If you want to -restrict the socket to IPv6 only, pass the ``UV_UDP_IPV6ONLY`` flag to -``uv_udp_bind`` [#]_. - -Multicast -~~~~~~~~~ - -A socket can (un)subscribe to a multicast group using: - -.. literalinclude:: ../libuv/include/uv.h - :lines: 594-597 - -where ``membership`` is ``UV_JOIN_GROUP`` or ``UV_LEAVE_GROUP``. - -The concepts of multicasting are nicely explained in `this guide`_. - -.. _this guide: http://www.tldp.org/HOWTO/Multicast-HOWTO-2.html - -Local loopback of multicast packets is enabled by default [#]_, use -``uv_udp_set_multicast_loop`` to switch it off. - -The packet time-to-live for multicast packets can be changed using -``uv_udp_set_multicast_ttl``. - -Querying DNS ------------- - -libuv provides asynchronous DNS resolution. For this it provides its own -``getaddrinfo`` replacement [#]_. In the callback you can -perform normal socket operations on the retrieved addresses. Let's connect to -Freenode to see an example of DNS resolution. - -.. rubric:: dns/main.c -.. literalinclude:: ../code/dns/main.c - :linenos: - :lines: 61- - :emphasize-lines: 12 - -If ``uv_getaddrinfo`` returns non-zero, something went wrong in the setup and -your callback won't be invoked at all. All arguments can be freed immediately -after ``uv_getaddrinfo`` returns. The `hostname`, `servname` and `hints` -structures are documented in `the getaddrinfo man page `_. The -callback can be ``NULL`` in which case the function will run synchronously. - -In the resolver callback, you can pick any IP from the linked list of ``struct -addrinfo(s)``. This also demonstrates ``uv_tcp_connect``. It is necessary to -call ``uv_freeaddrinfo`` in the callback. - -.. rubric:: dns/main.c -.. literalinclude:: ../code/dns/main.c - :linenos: - :lines: 42-60 - :emphasize-lines: 8,16 - -libuv also provides the inverse `uv_getnameinfo`_. - -.. _uv_getnameinfo: http://docs.libuv.org/en/v1.x/dns.html#c.uv_getnameinfo - -Network interfaces ------------------- - -Information about the system's network interfaces can be obtained through libuv -using ``uv_interface_addresses``. This simple program just prints out all the -interface details so you get an idea of the fields that are available. This is -useful to allow your service to bind to IP addresses when it starts. - -.. rubric:: interfaces/main.c -.. literalinclude:: ../code/interfaces/main.c - :linenos: - :emphasize-lines: 9,17 - -``is_internal`` is true for loopback interfaces. Note that if a physical -interface has multiple IPv4/IPv6 addresses, the name will be reported multiple -times, with each address being reported once. - -.. _c-ares: http://c-ares.haxx.se -.. _getaddrinfo: http://www.kernel.org/doc/man-pages/online/pages/man3/getaddrinfo.3.html - -.. _User Datagram Protocol: http://en.wikipedia.org/wiki/User_Datagram_Protocol -.. _DHCP: http://tools.ietf.org/html/rfc2131 - ----- - -.. [#] http://beej.us/guide/bgnet/output/html/multipage/advanced.html#broadcast -.. [#] on Windows only supported on Windows Vista and later. -.. [#] http://www.tldp.org/HOWTO/Multicast-HOWTO-6.html#ss6.1 -.. [#] libuv use the system ``getaddrinfo`` in the libuv threadpool. libuv - v0.8.0 and earlier also included c-ares_ as an alternative, but this has been - removed in v0.9.0. diff --git a/source/processes.rst b/source/processes.rst deleted file mode 100644 index bbe13bc..0000000 --- a/source/processes.rst +++ /dev/null @@ -1,389 +0,0 @@ -Processes -========= - -libuv offers considerable child process management, abstracting the platform -differences and allowing communication with the child process using streams or -named pipes. - -A common idiom in Unix is for every process to do one thing and do it well. In -such a case, a process often uses multiple child processes to achieve tasks -(similar to using pipes in shells). A multi-process model with messages -may also be easier to reason about compared to one with threads and shared -memory. - -A common refrain against event-based programs is that they cannot take -advantage of multiple cores in modern computers. In a multi-threaded program -the kernel can perform scheduling and assign different threads to different -cores, improving performance. But an event loop has only one thread. The -workaround can be to launch multiple processes instead, with each process -running an event loop, and each process getting assigned to a separate CPU -core. - -Spawning child processes ------------------------- - -The simplest case is when you simply want to launch a process and know when it -exits. This is achieved using ``uv_spawn``. - -.. rubric:: spawn/main.c -.. literalinclude:: ../code/spawn/main.c - :linenos: - :lines: 6-8,15- - :emphasize-lines: 11,13-17 - -.. NOTE:: - - ``options`` is implicitly initialized with zeros since it is a global - variable. If you change ``options`` to a local variable, remember to - initialize it to null out all unused fields:: - - uv_process_options_t options = {0}; - -The ``uv_process_t`` struct only acts as the handle, all options are set via -``uv_process_options_t``. To simply launch a process, you need to set only the -``file`` and ``args`` fields. ``file`` is the program to execute. Since -``uv_spawn`` uses execvp_ internally, there is no need to supply the full -path. Finally as per underlying conventions, **the arguments array has to be -one larger than the number of arguments, with the last element being NULL**. - -.. _execvp: http://www.kernel.org/doc/man-pages/online/pages/man3/exec.3.html - -After the call to ``uv_spawn``, ``uv_process_t.pid`` will contain the process -ID of the child process. - -The exit callback will be invoked with the *exit status* and the type of *signal* -which caused the exit. - -.. rubric:: spawn/main.c -.. literalinclude:: ../code/spawn/main.c - :linenos: - :lines: 9-12 - :emphasize-lines: 3 - -It is **required** to close the process watcher after the process exits. - -Changing process parameters ---------------------------- - -Before the child process is launched you can control the execution environment -using fields in ``uv_process_options_t``. - -Change execution directory -++++++++++++++++++++++++++ - -Set ``uv_process_options_t.cwd`` to the corresponding directory. - -Set environment variables -+++++++++++++++++++++++++ - -``uv_process_options_t.env`` is a null-terminated array of strings, each of the -form ``VAR=VALUE`` used to set up the environment variables for the process. Set -this to ``NULL`` to inherit the environment from the parent (this) process. - -Option flags -++++++++++++ - -Setting ``uv_process_options_t.flags`` to a bitwise OR of the following flags, -modifies the child process behaviour: - -* ``UV_PROCESS_SETUID`` - sets the child's execution user ID to ``uv_process_options_t.uid``. -* ``UV_PROCESS_SETGID`` - sets the child's execution group ID to ``uv_process_options_t.gid``. - -Changing the UID/GID is only supported on Unix, ``uv_spawn`` will fail on -Windows with ``UV_ENOTSUP``. - -* ``UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS`` - No quoting or escaping of - ``uv_process_options_t.args`` is done on Windows. Ignored on Unix. -* ``UV_PROCESS_DETACHED`` - Starts the child process in a new session, which - will keep running after the parent process exits. See example below. - -Detaching processes -------------------- - -Passing the flag ``UV_PROCESS_DETACHED`` can be used to launch daemons, or -child processes which are independent of the parent so that the parent exiting -does not affect it. - -.. rubric:: detach/main.c -.. literalinclude:: ../code/detach/main.c - :linenos: - :lines: 9-30 - :emphasize-lines: 12,19 - -Just remember that the handle is still monitoring the child, so your program -won't exit. Use ``uv_unref()`` if you want to be more *fire-and-forget*. - -Sending signals to processes ----------------------------- - -libuv wraps the standard ``kill(2)`` system call on Unix and implements one -with similar semantics on Windows, with *one caveat*: all of ``SIGTERM``, -``SIGINT`` and ``SIGKILL``, lead to termination of the process. The signature -of ``uv_kill`` is:: - - uv_err_t uv_kill(int pid, int signum); - -For processes started using libuv, you may use ``uv_process_kill`` instead, -which accepts the ``uv_process_t`` watcher as the first argument, rather than -the pid. In this case, **remember to call** ``uv_close`` on the watcher. - -Signals -------- - -libuv provides wrappers around Unix signals with `some Windows support -`_ as well. - -Use ``uv_signal_init()`` to initialize -a handle and associate it with a loop. To listen for particular signals on -that handler, use ``uv_signal_start()`` with the handler function. Each handler -can only be associated with one signal number, with subsequent calls to -``uv_signal_start()`` overwriting earlier associations. Use ``uv_signal_stop()`` to -stop watching. Here is a small example demonstrating the various possibilities: - -.. rubric:: signal/main.c -.. literalinclude:: ../code/signal/main.c - :linenos: - :emphasize-lines: 17-18,27-28 - -.. NOTE:: - - ``uv_run(loop, UV_RUN_NOWAIT)`` is similar to ``uv_run(loop, UV_RUN_ONCE)`` - in that it will process only one event. UV_RUN_ONCE blocks if there are no - pending events, while UV_RUN_NOWAIT will return immediately. We use NOWAIT - so that one of the loops isn't starved because the other one has no pending - activity. - -Send ``SIGUSR1`` to the process, and you'll find the handler being invoked -4 times, one for each ``uv_signal_t``. The handler just stops each handle, -so that the program exits. This sort of dispatch to all handlers is very -useful. A server using multiple event loops could ensure that all data was -safely saved before termination, simply by every loop adding a watcher for -``SIGINT``. - -Child Process I/O ------------------ - -A normal, newly spawned process has its own set of file descriptors, with 0, -1 and 2 being ``stdin``, ``stdout`` and ``stderr`` respectively. Sometimes you -may want to share file descriptors with the child. For example, perhaps your -applications launches a sub-command and you want any errors to go in the log -file, but ignore ``stdout``. For this you'd like to have ``stderr`` of the -child be the same as the stderr of the parent. In this case, libuv supports -*inheriting* file descriptors. In this sample, we invoke the test program, -which is: - -.. rubric:: proc-streams/test.c -.. literalinclude:: ../code/proc-streams/test.c - -The actual program ``proc-streams`` runs this while sharing only ``stderr``. -The file descriptors of the child process are set using the ``stdio`` field in -``uv_process_options_t``. First set the ``stdio_count`` field to the number of -file descriptors being set. ``uv_process_options_t.stdio`` is an array of -``uv_stdio_container_t``, which is: - -.. literalinclude:: ../libuv/include/uv.h - :lines: 826-834 - -where flags can have several values. Use ``UV_IGNORE`` if it isn't going to be -used. If the first three ``stdio`` fields are marked as ``UV_IGNORE`` they'll -redirect to ``/dev/null``. - -Since we want to pass on an existing descriptor, we'll use ``UV_INHERIT_FD``. -Then we set the ``fd`` to ``stderr``. - -.. rubric:: proc-streams/main.c -.. literalinclude:: ../code/proc-streams/main.c - :linenos: - :lines: 15-17,27- - :emphasize-lines: 6,10,11,12 - -If you run ``proc-stream`` you'll see that only the line "This is stderr" will -be displayed. Try marking ``stdout`` as being inherited and see the output. - -It is dead simple to apply this redirection to streams. By setting ``flags`` -to ``UV_INHERIT_STREAM`` and setting ``data.stream`` to the stream in the -parent process, the child process can treat that stream as standard I/O. This -can be used to implement something like CGI_. - -.. _CGI: http://en.wikipedia.org/wiki/Common_Gateway_Interface - -A sample CGI script/executable is: - -.. rubric:: cgi/tick.c -.. literalinclude:: ../code/cgi/tick.c - -The CGI server combines the concepts from this chapter and :doc:`networking` so -that every client is sent ten ticks after which that connection is closed. - -.. rubric:: cgi/main.c -.. literalinclude:: ../code/cgi/main.c - :linenos: - :lines: 49-63 - :emphasize-lines: 10 - -Here we simply accept the TCP connection and pass on the socket (*stream*) to -``invoke_cgi_script``. - -.. rubric:: cgi/main.c -.. literalinclude:: ../code/cgi/main.c - :linenos: - :lines: 16, 25-45 - :emphasize-lines: 8-9,18,20 - -The ``stdout`` of the CGI script is set to the socket so that whatever our tick -script prints, gets sent to the client. By using processes, we can offload the -read/write buffering to the operating system, so in terms of convenience this -is great. Just be warned that creating processes is a costly task. - -.. _pipes: - -Pipes ------ - -libuv's ``uv_pipe_t`` structure is slightly confusing to Unix programmers, -because it immediately conjures up ``|`` and `pipe(7)`_. But ``uv_pipe_t`` is -not related to anonymous pipes, rather it is an IPC mechanism. ``uv_pipe_t`` -can be backed by a `Unix Domain Socket`_ or `Windows Named Pipe`_ to allow -multiple processes to communicate. This is discussed below. - -.. _pipe(7): http://www.kernel.org/doc/man-pages/online/pages/man7/pipe.7.html -.. _Unix Domain Socket: http://www.kernel.org/doc/man-pages/online/pages/man7/unix.7.html -.. _Windows Named Pipe: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365590(v=vs.85).aspx - -Parent-child IPC -++++++++++++++++ - -A parent and child can have one or two way communication over a pipe created by -settings ``uv_stdio_container_t.flags`` to a bit-wise combination of -``UV_CREATE_PIPE`` and ``UV_READABLE_PIPE`` or ``UV_WRITABLE_PIPE``. The -read/write flag is from the perspective of the child process. - -Arbitrary process IPC -+++++++++++++++++++++ - -Since domain sockets [#]_ can have a well known name and a location in the -file-system they can be used for IPC between unrelated processes. The D-BUS_ -system used by open source desktop environments uses domain sockets for event -notification. Various applications can then react when a contact comes online -or new hardware is detected. The MySQL server also runs a domain socket on -which clients can interact with it. - -.. _D-BUS: http://www.freedesktop.org/wiki/Software/dbus - -When using domain sockets, a client-server pattern is usually followed with the -creator/owner of the socket acting as the server. After the initial setup, -messaging is no different from TCP, so we'll re-use the echo server example. - -.. rubric:: pipe-echo-server/main.c -.. literalinclude:: ../code/pipe-echo-server/main.c - :linenos: - :lines: 70- - :emphasize-lines: 5,10,14 - -We name the socket ``echo.sock`` which means it will be created in the local -directory. This socket now behaves no different from TCP sockets as far as -the stream API is concerned. You can test this server using `socat`_:: - - $ socat - /path/to/socket - -A client which wants to connect to a domain socket will use:: - - void uv_pipe_connect(uv_connect_t *req, uv_pipe_t *handle, const char *name, uv_connect_cb cb); - -where ``name`` will be ``echo.sock`` or similar. - -.. _socat: http://www.dest-unreach.org/socat/ - -Sending file descriptors over pipes -+++++++++++++++++++++++++++++++++++ - -The cool thing about domain sockets is that file descriptors can be exchanged -between processes by sending them over a domain socket. This allows processes -to hand off their I/O to other processes. Applications include load-balancing -servers, worker processes and other ways to make optimum use of CPU. libuv only -supports sending **TCP sockets or other pipes** over pipes for now. - -To demonstrate, we will look at a echo server implementation that hands of -clients to worker processes in a round-robin fashion. This program is a bit -involved, and while only snippets are included in the book, it is recommended -to read the full code to really understand it. - -The worker process is quite simple, since the file-descriptor is handed over to -it by the master. - -.. rubric:: multi-echo-server/worker.c -.. literalinclude:: ../code/multi-echo-server/worker.c - :linenos: - :lines: 7-9,81- - :emphasize-lines: 6-8 - -``queue`` is the pipe connected to the master process on the other end, along -which new file descriptors get sent. It is important to set the ``ipc`` -argument of ``uv_pipe_init`` to 1 to indicate this pipe will be used for -inter-process communication! Since the master will write the file handle to the -standard input of the worker, we connect the pipe to ``stdin`` using -``uv_pipe_open``. - -.. rubric:: multi-echo-server/worker.c -.. literalinclude:: ../code/multi-echo-server/worker.c - :linenos: - :lines: 51-79 - :emphasize-lines: 10,15,20 - -First we call ``uv_pipe_pending_count()`` to ensure that a handle is available -to read out. If your program could deal with different types of handles, -``uv_pipe_pending_type()`` can be used to determine the type. -Although ``accept`` seems odd in this code, it actually makes sense. What -``accept`` traditionally does is get a file descriptor (the client) from -another file descriptor (The listening socket). Which is exactly what we do -here. Fetch the file descriptor (``client``) from ``queue``. From this point -the worker does standard echo server stuff. - -Turning now to the master, let's take a look at how the workers are launched to -allow load balancing. - -.. rubric:: multi-echo-server/main.c -.. literalinclude:: ../code/multi-echo-server/main.c - :linenos: - :lines: 9-13 - -The ``child_worker`` structure wraps the process, and the pipe between the -master and the individual process. - -.. rubric:: multi-echo-server/main.c -.. literalinclude:: ../code/multi-echo-server/main.c - :linenos: - :lines: 51,61-95 - :emphasize-lines: 17,20-21 - -In setting up the workers, we use the nifty libuv function ``uv_cpu_info`` to -get the number of CPUs so we can launch an equal number of workers. Again it is -important to initialize the pipe acting as the IPC channel with the third -argument as 1. We then indicate that the child process' ``stdin`` is to be -a readable pipe (from the point of view of the child). Everything is -straightforward till here. The workers are launched and waiting for file -descriptors to be written to their standard input. - -It is in ``on_new_connection`` (the TCP infrastructure is initialized in -``main()``), that we accept the client socket and pass it along to the next -worker in the round-robin. - -.. rubric:: multi-echo-server/main.c -.. literalinclude:: ../code/multi-echo-server/main.c - :linenos: - :lines: 31-49 - :emphasize-lines: 9,12-13 - -The ``uv_write2`` call handles all the abstraction and it is simply a matter of -passing in the handle (``client``) as the right argument. With this our -multi-process echo server is operational. - -Thanks to Kyle for `pointing out`_ that ``uv_write2()`` requires a non-empty -buffer even when sending handles. - -.. _pointing out: https://github.com/nikhilm/uvbook/issues/56 - ----- - -.. [#] In this section domain sockets stands in for named pipes on Windows as - well. diff --git a/source/threads.rst b/source/threads.rst deleted file mode 100644 index 4117cc7..0000000 --- a/source/threads.rst +++ /dev/null @@ -1,379 +0,0 @@ -Threads -======= - -Wait a minute? Why are we on threads? Aren't event loops supposed to be **the -way** to do *web-scale programming*? Well... no. Threads are still the medium in -which processors do their jobs. Threads are therefore mighty useful sometimes, even -though you might have to wade through various synchronization primitives. - -Threads are used internally to fake the asynchronous nature of all of the system -calls. libuv also uses threads to allow you, the application, to perform a task -asynchronously that is actually blocking, by spawning a thread and collecting -the result when it is done. - -Today there are two predominant thread libraries: the Windows threads -implementation and POSIX's `pthreads`_. libuv's thread API is analogous to -the pthreads API and often has similar semantics. - -A notable aspect of libuv's thread facilities is that it is a self contained -section within libuv. Whereas other features intimately depend on the event -loop and callback principles, threads are complete agnostic, they block as -required, signal errors directly via return values, and, as shown in the -:ref:`first example `, don't even require a running -event loop. - -libuv's thread API is also very limited since the semantics and syntax of -threads are different on all platforms, with different levels of completeness. - -This chapter makes the following assumption: **There is only one event loop, -running in one thread (the main thread)**. No other thread interacts -with the event loop (except using ``uv_async_send``). - -Core thread operations ----------------------- - -There isn't much here, you just start a thread using ``uv_thread_create()`` and -wait for it to close using ``uv_thread_join()``. - -.. _thread-create-example: - -.. rubric:: thread-create/main.c -.. literalinclude:: ../code/thread-create/main.c - :linenos: - :lines: 26-37 - :emphasize-lines: 3-7 - -.. tip:: - - ``uv_thread_t`` is just an alias for ``pthread_t`` on Unix, but this is an - implementation detail, avoid depending on it to always be true. - -The second parameter is the function which will serve as the entry point for -the thread, the last parameter is a ``void *`` argument which can be used to pass -custom parameters to the thread. The function ``hare`` will now run in a separate -thread, scheduled pre-emptively by the operating system: - -.. rubric:: thread-create/main.c -.. literalinclude:: ../code/thread-create/main.c - :linenos: - :lines: 6-14 - :emphasize-lines: 2 - -Unlike ``pthread_join()`` which allows the target thread to pass back a value to -the calling thread using a second parameter, ``uv_thread_join()`` does not. To -send values use :ref:`inter-thread-communication`. - -Synchronization Primitives --------------------------- - -This section is purposely spartan. This book is not about threads, so I only -catalogue any surprises in the libuv APIs here. For the rest you can look at -the pthreads `man pages `_. - -Mutexes -~~~~~~~ - -The mutex functions are a **direct** map to the pthread equivalents. - -.. rubric:: libuv mutex functions -.. literalinclude:: ../libuv/include/uv.h - :lines: 1355-1360 - -The ``uv_mutex_init()`` and ``uv_mutex_trylock()`` functions will return 0 on -success, and an error code otherwise. - -If `libuv` has been compiled with debugging enabled, ``uv_mutex_destroy()``, -``uv_mutex_lock()`` and ``uv_mutex_unlock()`` will ``abort()`` on error. -Similarly ``uv_mutex_trylock()`` will abort if the error is anything *other -than* ``EAGAIN`` or ``EBUSY``. - -Recursive mutexes are supported by some platforms, but you should not rely on -them. The BSD mutex implementation will raise an error if a thread which has -locked a mutex attempts to lock it again. For example, a construct like:: - - uv_mutex_lock(a_mutex); - uv_thread_create(thread_id, entry, (void *)a_mutex); - uv_mutex_lock(a_mutex); - // more things here - -can be used to wait until another thread initializes some stuff and then -unlocks ``a_mutex`` but will lead to your program crashing if in debug mode, or -return an error in the second call to ``uv_mutex_lock()``. - -.. note:: - - Mutexes on linux support attributes for a recursive mutex, but the API is - not exposed via libuv. - -Locks -~~~~~ - -Read-write locks are a more granular access mechanism. Two readers can access -shared memory at the same time. A writer may not acquire the lock when it is -held by a reader. A reader or writer may not acquire a lock when a writer is -holding it. Read-write locks are frequently used in databases. Here is a toy -example. - -.. rubric:: locks/main.c - simple rwlocks -.. literalinclude:: ../code/locks/main.c - :linenos: - :emphasize-lines: 13,16,27,31,42,55 - -Run this and observe how the readers will sometimes overlap. In case of -multiple writers, schedulers will usually give them higher priority, so if you -add two writers, you'll see that both writers tend to finish first before the -readers get a chance again. - -We also use barriers in the above example so that the main thread can wait for -all readers and writers to indicate they have ended. - -Others -~~~~~~ - -libuv also supports semaphores_, `condition variables`_ and barriers_ with APIs -very similar to their pthread counterparts. - -.. _semaphores: http://en.wikipedia.org/wiki/Semaphore_(programming) -.. _condition variables: http://en.wikipedia.org/wiki/Condition_variable#Waiting_and_signaling -.. _barriers: http://en.wikipedia.org/wiki/Barrier_(computer_science) - -In addition, libuv provides a convenience function ``uv_once()``. Multiple -threads can attempt to call ``uv_once()`` with a given guard and a function -pointer, **only the first one will win, the function will be called once and -only once**:: - - /* Initialize guard */ - static uv_once_t once_only = UV_ONCE_INIT; - - int i = 0; - - void increment() { - i++; - } - - void thread1() { - /* ... work */ - uv_once(once_only, increment); - } - - void thread2() { - /* ... work */ - uv_once(once_only, increment); - } - - int main() { - /* ... spawn threads */ - } - -After all threads are done, ``i == 1``. - -.. _libuv-work-queue: - -libuv v0.11.11 onwards also added a ``uv_key_t`` struct and api_ for -thread-local storage. - -.. _api: http://docs.libuv.org/en/v1.x/threading.html#thread-local-storage - -libuv work queue ----------------- - -``uv_queue_work()`` is a convenience function that allows an application to run -a task in a separate thread, and have a callback that is triggered when the -task is done. A seemingly simple function, what makes ``uv_queue_work()`` -tempting is that it allows potentially any third-party libraries to be used -with the event-loop paradigm. When you use event loops, it is *imperative to -make sure that no function which runs periodically in the loop thread blocks -when performing I/O or is a serious CPU hog*, because this means that the loop -slows down and events are not being handled at full capacity. - -However, a lot of existing code out there features blocking functions (for example -a routine which performs I/O under the hood) to be used with threads if you -want responsiveness (the classic 'one thread per client' server model), and -getting them to play with an event loop library generally involves rolling your -own system of running the task in a separate thread. libuv just provides -a convenient abstraction for this. - -Here is a simple example inspired by `node.js is cancer`_. We are going to -calculate fibonacci numbers, sleeping a bit along the way, but run it in -a separate thread so that the blocking and CPU bound task does not prevent the -event loop from performing other activities. - -.. rubric:: queue-work/main.c - lazy fibonacci -.. literalinclude:: ../code/queue-work/main.c - :linenos: - :lines: 17-29 - -The actual task function is simple, nothing to show that it is going to be -run in a separate thread. The ``uv_work_t`` structure is the clue. You can pass -arbitrary data through it using the ``void* data`` field and use it to -communicate to and from the thread. But be sure you are using proper locks if -you are changing things while both threads may be running. - -The trigger is ``uv_queue_work``: - -.. rubric:: queue-work/main.c -.. literalinclude:: ../code/queue-work/main.c - :linenos: - :lines: 31-44 - :emphasize-lines: 40 - -The thread function will be launched in a separate thread, passed the -``uv_work_t`` structure and once the function returns, the *after* function -will be called on the thread the event loop is running in. It will be passed -the same structure. - -For writing wrappers to blocking libraries, a common :ref:`pattern ` -is to use a baton to exchange data. - -Since libuv version `0.9.4` an additional function, ``uv_cancel()``, is -available. This allows you to cancel tasks on the libuv work queue. Only tasks -that *are yet to be started* can be cancelled. If a task has *already started -executing, or it has finished executing*, ``uv_cancel()`` **will fail**. - -``uv_cancel()`` is useful to cleanup pending tasks if the user requests -termination. For example, a music player may queue up multiple directories to -be scanned for audio files. If the user terminates the program, it should quit -quickly and not wait until all pending requests are run. - -Let's modify the fibonacci example to demonstrate ``uv_cancel()``. We first set -up a signal handler for termination. - -.. rubric:: queue-cancel/main.c -.. literalinclude:: ../code/queue-cancel/main.c - :linenos: - :lines: 43- - -When the user triggers the signal by pressing ``Ctrl+C`` we send -``uv_cancel()`` to all the workers. ``uv_cancel()`` will return ``0`` for those that are already executing or finished. - -.. rubric:: queue-cancel/main.c -.. literalinclude:: ../code/queue-cancel/main.c - :linenos: - :lines: 33-41 - :emphasize-lines: 6 - -For tasks that do get cancelled successfully, the *after* function is called -with ``status`` set to ``UV_ECANCELED``. - -.. rubric:: queue-cancel/main.c -.. literalinclude:: ../code/queue-cancel/main.c - :linenos: - :lines: 28-31 - :emphasize-lines: 2 - -``uv_cancel()`` can also be used with ``uv_fs_t`` and ``uv_getaddrinfo_t`` -requests. For the filesystem family of functions, ``uv_fs_t.errorno`` will be -set to ``UV_ECANCELED``. - -.. TIP:: - - A well designed program would have a way to terminate long running workers - that have already started executing. Such a worker could periodically check - for a variable that only the main process sets to signal termination. - -.. _inter-thread-communication: - -Inter-thread communication --------------------------- - -Sometimes you want various threads to actually send each other messages *while* -they are running. For example you might be running some long duration task in -a separate thread (perhaps using ``uv_queue_work``) but want to notify progress -to the main thread. This is a simple example of having a download manager -informing the user of the status of running downloads. - -.. rubric:: progress/main.c -.. literalinclude:: ../code/progress/main.c - :linenos: - :lines: 7-8,34- - :emphasize-lines: 2,11 - -The async thread communication works *on loops* so although any thread can be -the message sender, only threads with libuv loops can be receivers (or rather -the loop is the receiver). libuv will invoke the callback (``print_progress``) -with the async watcher whenever it receives a message. - -.. warning:: - - It is important to realize that since the message send is *async*, the callback - may be invoked immediately after ``uv_async_send`` is called in another - thread, or it may be invoked after some time. libuv may also combine - multiple calls to ``uv_async_send`` and invoke your callback only once. The - only guarantee that libuv makes is -- The callback function is called *at - least once* after the call to ``uv_async_send``. If you have no pending - calls to ``uv_async_send``, the callback won't be called. If you make two - or more calls, and libuv hasn't had a chance to run the callback yet, it - *may* invoke your callback *only once* for the multiple invocations of - ``uv_async_send``. Your callback will never be called twice for just one - event. - -.. rubric:: progress/main.c -.. literalinclude:: ../code/progress/main.c - :linenos: - :lines: 10-23 - :emphasize-lines: 7-8 - -In the download function, we modify the progress indicator and queue the message -for delivery with ``uv_async_send``. Remember: ``uv_async_send`` is also -non-blocking and will return immediately. - -.. rubric:: progress/main.c -.. literalinclude:: ../code/progress/main.c - :linenos: - :lines: 30-33 - -The callback is a standard libuv pattern, extracting the data from the watcher. - -Finally it is important to remember to clean up the watcher. - -.. rubric:: progress/main.c -.. literalinclude:: ../code/progress/main.c - :linenos: - :lines: 25-28 - :emphasize-lines: 3 - -After this example, which showed the abuse of the ``data`` field, bnoordhuis_ -pointed out that using the ``data`` field is not thread safe, and -``uv_async_send()`` is actually only meant to wake up the event loop. Use -a mutex or rwlock to ensure accesses are performed in the right order. - -.. note:: - - mutexes and rwlocks **DO NOT** work inside a signal handler, whereas - ``uv_async_send`` does. - -One use case where ``uv_async_send`` is required is when interoperating with -libraries that require thread affinity for their functionality. For example in -node.js, a v8 engine instance, contexts and its objects are bound to the thread -that the v8 instance was started in. Interacting with v8 data structures from -another thread can lead to undefined results. Now consider some node.js module -which binds a third party library. It may go something like this: - -1. In node, the third party library is set up with a JavaScript callback to be - invoked for more information:: - - var lib = require('lib'); - lib.on_progress(function() { - console.log("Progress"); - }); - - lib.do(); - - // do other stuff - -2. ``lib.do`` is supposed to be non-blocking but the third party lib is - blocking, so the binding uses ``uv_queue_work``. - -3. The actual work being done in a separate thread wants to invoke the progress - callback, but cannot directly call into v8 to interact with JavaScript. So - it uses ``uv_async_send``. - -4. The async callback, invoked in the main loop thread, which is the v8 thread, - then interacts with v8 to invoke the JavaScript callback. - -.. _pthreads: http://man7.org/linux/man-pages/man7/pthreads.7.html - ----- - -.. _node.js is cancer: http://teddziuba.github.io/2011/10/node-js-is-cancer.html -.. _bnoordhuis: https://github.com/bnoordhuis diff --git a/source/utilities.rst b/source/utilities.rst deleted file mode 100644 index fe3c0da..0000000 --- a/source/utilities.rst +++ /dev/null @@ -1,433 +0,0 @@ -Utilities -========= - -This chapter catalogues tools and techniques which are useful for common tasks. -The `libev man page`_ already covers some patterns which can be adopted to -libuv through simple API changes. It also covers parts of the libuv API that -don't require entire chapters dedicated to them. - -Timers ------- - -Timers invoke the callback after a certain time has elapsed since the timer was -started. libuv timers can also be set to invoke at regular intervals instead of -just once. - -Simple use is to init a watcher and start it with a ``timeout``, and optional ``repeat``. -Timers can be stopped at any time. - -.. code-block:: c - - uv_timer_t timer_req; - - uv_timer_init(loop, &timer_req); - uv_timer_start(&timer_req, callback, 5000, 2000); - -will start a repeating timer, which first starts 5 seconds (the ``timeout``) after the execution -of ``uv_timer_start``, then repeats every 2 seconds (the ``repeat``). Use: - -.. code-block:: c - - uv_timer_stop(&timer_req); - -to stop the timer. This can be used safely from within the callback as well. - -The repeat interval can be modified at any time with:: - - uv_timer_set_repeat(uv_timer_t *timer, int64_t repeat); - -which will take effect **when possible**. If this function is called from -a timer callback, it means: - -* If the timer was non-repeating, the timer has already been stopped. Use - ``uv_timer_start`` again. -* If the timer is repeating, the next timeout has already been scheduled, so - the old repeat interval will be used once more before the timer switches to - the new interval. - -The utility function:: - - int uv_timer_again(uv_timer_t *) - -applies **only to repeating timers** and is equivalent to stopping the timer -and then starting it with both initial ``timeout`` and ``repeat`` set to the -old ``repeat`` value. If the timer hasn't been started it fails (error code -``UV_EINVAL``) and returns -1. - -An actual timer example is in the :ref:`reference count section -`. - -.. _reference-count: - -Event loop reference count --------------------------- - -The event loop only runs as long as there are active handles. This system -works by having every handle increase the reference count of the event loop -when it is started and decreasing the reference count when stopped. It is also -possible to manually change the reference count of handles using:: - - void uv_ref(uv_handle_t*); - void uv_unref(uv_handle_t*); - -These functions can be used to allow a loop to exit even when a watcher is -active or to use custom objects to keep the loop alive. - -The latter can be used with interval timers. You might have a garbage collector -which runs every X seconds, or your network service might send a heartbeat to -others periodically, but you don't want to have to stop them along all clean -exit paths or error scenarios. Or you want the program to exit when all your -other watchers are done. In that case just unref the timer immediately after -creation so that if it is the only watcher running then ``uv_run`` will still -exit. - -This is also used in node.js where some libuv methods are being bubbled up to -the JS API. A ``uv_handle_t`` (the superclass of all watchers) is created per -JS object and can be ref/unrefed. - -.. rubric:: ref-timer/main.c -.. literalinclude:: ../code/ref-timer/main.c - :linenos: - :lines: 5-8, 17- - :emphasize-lines: 9 - -We initialize the garbage collector timer, then immediately ``unref`` it. -Observe how after 9 seconds, when the fake job is done, the program -automatically exits, even though the garbage collector is still running. - -Idler pattern -------------- - -The callbacks of idle handles are invoked once per event loop. The idle -callback can be used to perform some very low priority activity. For example, -you could dispatch a summary of the daily application performance to the -developers for analysis during periods of idleness, or use the application's -CPU time to perform SETI calculations :) An idle watcher is also useful in -a GUI application. Say you are using an event loop for a file download. If the -TCP socket is still being established and no other events are present your -event loop will pause (**block**), which means your progress bar will freeze -and the user will face an unresponsive application. In such a case queue up and -idle watcher to keep the UI operational. - -.. rubric:: idle-compute/main.c -.. literalinclude:: ../code/idle-compute/main.c - :linenos: - :lines: 5-9, 34- - :emphasize-lines: 13 - -Here we initialize the idle watcher and queue it up along with the actual -events we are interested in. ``crunch_away`` will now be called repeatedly -until the user types something and presses Return. Then it will be interrupted -for a brief amount as the loop deals with the input data, after which it will -keep calling the idle callback again. - -.. rubric:: idle-compute/main.c -.. literalinclude:: ../code/idle-compute/main.c - :linenos: - :lines: 10-19 - -.. _baton: - -Passing data to worker thread ------------------------------ - -When using ``uv_queue_work`` you'll usually need to pass complex data through -to the worker thread. The solution is to use a ``struct`` and set -``uv_work_t.data`` to point to it. A slight variation is to have the -``uv_work_t`` itself as the first member of this struct (called a baton [#]_). -This allows cleaning up the work request and all the data in one free call. - -.. code-block:: c - :linenos: - :emphasize-lines: 2 - - struct ftp_baton { - uv_work_t req; - char *host; - int port; - char *username; - char *password; - } - -.. code-block:: c - :linenos: - :emphasize-lines: 2 - - ftp_baton *baton = (ftp_baton*) malloc(sizeof(ftp_baton)); - baton->req.data = (void*) baton; - baton->host = strdup("my.webhost.com"); - baton->port = 21; - // ... - - uv_queue_work(loop, &baton->req, ftp_session, ftp_cleanup); - -Here we create the baton and queue the task. - -Now the task function can extract the data it needs: - -.. code-block:: c - :linenos: - :emphasize-lines: 2, 12 - - void ftp_session(uv_work_t *req) { - ftp_baton *baton = (ftp_baton*) req->data; - - fprintf(stderr, "Connecting to %s\n", baton->host); - } - - void ftp_cleanup(uv_work_t *req) { - ftp_baton *baton = (ftp_baton*) req->data; - - free(baton->host); - // ... - free(baton); - } - -We then free the baton which also frees the watcher. - -External I/O with polling -------------------------- - -Usually third-party libraries will handle their own I/O, and keep track of -their sockets and other files internally. In this case it isn't possible to use -the standard stream I/O operations, but the library can still be integrated -into the libuv event loop. All that is required is that the library allow you -to access the underlying file descriptors and provide functions that process -tasks in small increments as decided by your application. Some libraries though -will not allow such access, providing only a standard blocking function which -will perform the entire I/O transaction and only then return. It is unwise to -use these in the event loop thread, use the :ref:`libuv-work-queue` instead. Of -course, this will also mean losing granular control on the library. - -The ``uv_poll`` section of libuv simply watches file descriptors using the -operating system notification mechanism. In some sense, all the I/O operations -that libuv implements itself are also backed by ``uv_poll`` like code. Whenever -the OS notices a change of state in file descriptors being polled, libuv will -invoke the associated callback. - -Here we will walk through a simple download manager that will use libcurl_ to -download files. Rather than give all control to libcurl, we'll instead be -using the libuv event loop, and use the non-blocking, async multi_ interface to -progress with the download whenever libuv notifies of I/O readiness. - -.. _libcurl: http://curl.haxx.se/libcurl/ -.. _multi: http://curl.haxx.se/libcurl/c/libcurl-multi.html - -.. rubric:: uvwget/main.c - The setup -.. literalinclude:: ../code/uvwget/main.c - :linenos: - :lines: 1-9,140- - :emphasize-lines: 7,21,24-25 - -The way each library is integrated with libuv will vary. In the case of -libcurl, we can register two callbacks. The socket callback ``handle_socket`` -is invoked whenever the state of a socket changes and we have to start polling -it. ``start_timeout`` is called by libcurl to notify us of the next timeout -interval, after which we should drive libcurl forward regardless of I/O status. -This is so that libcurl can handle errors or do whatever else is required to -get the download moving. - -Our downloader is to be invoked as:: - - $ ./uvwget [url1] [url2] ... - -So we add each argument as an URL - -.. rubric:: uvwget/main.c - Adding urls -.. literalinclude:: ../code/uvwget/main.c - :linenos: - :lines: 39-56 - :emphasize-lines: 13-14 - -We let libcurl directly write the data to a file, but much more is possible if -you so desire. - -``start_timeout`` will be called immediately the first time by libcurl, so -things are set in motion. This simply starts a libuv `timer `_ which -drives ``curl_multi_socket_action`` with ``CURL_SOCKET_TIMEOUT`` whenever it -times out. ``curl_multi_socket_action`` is what drives libcurl, and what we -call whenever sockets change state. But before we go into that, we need to poll -on sockets whenever ``handle_socket`` is called. - -.. rubric:: uvwget/main.c - Setting up polling -.. literalinclude:: ../code/uvwget/main.c - :linenos: - :lines: 102-140 - :emphasize-lines: 9,11,15,21,24 - -We are interested in the socket fd ``s``, and the ``action``. For every socket -we create a ``uv_poll_t`` handle if it doesn't exist, and associate it with the -socket using ``curl_multi_assign``. This way ``socketp`` points to it whenever -the callback is invoked. - -In the case that the download is done or fails, libcurl requests removal of the -poll. So we stop and free the poll handle. - -Depending on what events libcurl wishes to watch for, we start polling with -``UV_READABLE`` or ``UV_WRITABLE``. Now libuv will invoke the poll callback -whenever the socket is ready for reading or writing. Calling ``uv_poll_start`` -multiple times on the same handle is acceptable, it will just update the events -mask with the new value. ``curl_perform`` is the crux of this program. - -.. rubric:: uvwget/main.c - Driving libcurl. -.. literalinclude:: ../code/uvwget/main.c - :linenos: - :lines: 81-95 - :emphasize-lines: 2,6-7,12,18,20 - -The first thing we do is to stop the timer, since there has been some progress -in the interval. Then depending on what event triggered the callback, we set -the correct flags. Then we call ``curl_multi_socket_action`` with the socket -that progressed and the flags informing about what events happened. At this -point libcurl does all of its internal tasks in small increments, and will -attempt to return as fast as possible, which is exactly what an evented program -wants in its main thread. libcurl keeps queueing messages into its own queue -about transfer progress. In our case we are only interested in transfers that -are completed. So we extract these messages, and clean up handles whose -transfers are done. - -.. rubric:: uvwget/main.c - Reading transfer status. -.. literalinclude:: ../code/uvwget/main.c - :linenos: - :lines: 58-79 - :emphasize-lines: 6,9-10,13-14 - -Check & Prepare watchers ------------------------- - -TODO - -Loading libraries ------------------ - -libuv provides a cross platform API to dynamically load `shared libraries`_. -This can be used to implement your own plugin/extension/module system and is -used by node.js to implement ``require()`` support for bindings. The usage is -quite simple as long as your library exports the right symbols. Be careful with -sanity and security checks when loading third party code, otherwise your -program will behave unpredictably. This example implements a very simple -plugin system which does nothing except print the name of the plugin. - -Let us first look at the interface provided to plugin authors. - -.. rubric:: plugin/plugin.h -.. literalinclude:: ../code/plugin/plugin.h - :linenos: - -You can similarly add more functions that plugin authors can use to do useful -things in your application [#]_. A sample plugin using this API is: - -.. rubric:: plugin/hello.c -.. literalinclude:: ../code/plugin/hello.c - :linenos: - -Our interface defines that all plugins should have an ``initialize`` function -which will be called by the application. This plugin is compiled as a shared -library and can be loaded by running our application:: - - $ ./plugin libhello.dylib - Loading libhello.dylib - Registered plugin "Hello World!" - -.. NOTE:: - - The shared library filename will be different depending on platforms. On - Linux it is ``libhello.so``. - -This is done by using ``uv_dlopen`` to first load the shared library -``libhello.dylib``. Then we get access to the ``initialize`` function using -``uv_dlsym`` and invoke it. - -.. rubric:: plugin/main.c -.. literalinclude:: ../code/plugin/main.c - :linenos: - :lines: 7- - :emphasize-lines: 15, 18, 24 - -``uv_dlopen`` expects a path to the shared library and sets the opaque -``uv_lib_t`` pointer. It returns 0 on success, -1 on error. Use ``uv_dlerror`` -to get the error message. - -``uv_dlsym`` stores a pointer to the symbol in the second argument in the third -argument. ``init_plugin_function`` is a function pointer to the sort of -function we are looking for in the application's plugins. - -.. _shared libraries: http://en.wikipedia.org/wiki/Shared_library#Shared_libraries - -TTY ---- - -Text terminals have supported basic formatting for a long time, with a `pretty -standardised`_ command set. This formatting is often used by programs to -improve the readability of terminal output. For example ``grep --colour``. -libuv provides the ``uv_tty_t`` abstraction (a stream) and related functions to -implement the ANSI escape codes across all platforms. By this I mean that libuv -converts ANSI codes to the Windows equivalent, and provides functions to get -terminal information. - -.. _pretty standardised: http://en.wikipedia.org/wiki/ANSI_escape_sequences - -The first thing to do is to initialize a ``uv_tty_t`` with the file descriptor -it reads/writes from. This is achieved with:: - - int uv_tty_init(uv_loop_t*, uv_tty_t*, uv_file fd, int readable) - -Set ``readable`` to true if you plan to use ``uv_read_start()`` on the stream. - -It is then best to use ``uv_tty_set_mode`` to set the mode to *normal* -which enables most TTY formatting, flow-control and other settings. Other_ modes -are also available. - -.. _Other: http://docs.libuv.org/en/v1.x/tty.html#c.uv_tty_mode_t - -Remember to call ``uv_tty_reset_mode`` when your program exits to restore the -state of the terminal. Just good manners. Another set of good manners is to be -aware of redirection. If the user redirects the output of your command to -a file, control sequences should not be written as they impede readability and -``grep``. To check if the file descriptor is indeed a TTY, call -``uv_guess_handle`` with the file descriptor and compare the return value with -``UV_TTY``. - -Here is a simple example which prints white text on a red background: - -.. rubric:: tty/main.c -.. literalinclude:: ../code/tty/main.c - :linenos: - :emphasize-lines: 11-12,14,17,27 - -The final TTY helper is ``uv_tty_get_winsize()`` which is used to get the -width and height of the terminal and returns ``0`` on success. Here is a small -program which does some animation using the function and character position -escape codes. - -.. rubric:: tty-gravity/main.c -.. literalinclude:: ../code/tty-gravity/main.c - :linenos: - :emphasize-lines: 19,25,38 - -The escape codes are: - -====== ======================= -Code Meaning -====== ======================= -*2* J Clear part of the screen, 2 is entire screen -H Moves cursor to certain position, default top-left -*n* B Moves cursor down by n lines -*n* C Moves cursor right by n columns -m Obeys string of display settings, in this case green background (40+2), white text (30+7) -====== ======================= - -As you can see this is very useful to produce nicely formatted output, or even -console based arcade games if that tickles your fancy. For fancier control you -can try `ncurses`_. - -.. _ncurses: http://www.gnu.org/software/ncurses/ncurses.html - ----- - -.. [#] I was first introduced to the term baton in this context, in Konstantin - Käfer's excellent slides on writing node.js bindings -- - http://kkaefer.github.com/node-cpp-modules/#baton -.. [#] mfp is My Fancy Plugin - -.. _libev man page: http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#COMMON_OR_USEFUL_IDIOMS_OR_BOTH