Add outside/libuv-v1.7.5

This commit is contained in:
John Franklin 2015-10-25 02:37:00 -05:00 committed by Raymond Pasco
parent 975fb71bb8
commit 58085e3203
330 changed files with 85979 additions and 0 deletions

75
outside/libuv-v1.7.5/.gitignore vendored Normal file
View File

@ -0,0 +1,75 @@
*.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/
# Clion / IntelliJ project files
/.idea/
*.xcodeproj
*.xcworkspace
# make dist output
libuv-*.tar.*

View File

@ -0,0 +1,38 @@
Aaron Bieber <qbit@deftly.net> <deftly@gmail.com>
Alan Gutierrez <alan@prettyrobots.com> <alan@blogometer.com>
Andrius Bentkus <andrius.bentkus@gmail.com> <toxedvirus@gmail.com>
Bert Belder <bertbelder@gmail.com> <info@2bs.nl>
Bert Belder <bertbelder@gmail.com> <user@ChrUbuntu.(none)>
Brandon Philips <brandon.philips@rackspace.com> <brandon@ifup.org>
Brian White <mscdex@mscdex.net>
Brian White <mscdex@mscdex.net> <mscdex@gmail.com>
Caleb James DeLisle <cjd@hyperboria.ca> <cjd@cjdns.fr>
Christoph Iserlohn <christoph.iserlohn@innoq.com>
Devchandra Meetei Leishangthem <dlmeetei@gmail.com>
Fedor Indutny <fedor.indutny@gmail.com> <fedor@indutny.com>
Frank Denis <github@pureftpd.org>
Isaac Z. Schlueter <i@izs.me>
Jason Williams <necmon@yahoo.com>
Justin Venus <justin.venus@gmail.com> <justin.venus@orbitz.com>
Keno Fischer <kenof@stanford.edu> <kfischer+github@college.harvard.edu>
Keno Fischer <kenof@stanford.edu> <kfischer@college.harvard.edu>
Leith Bade <leith@leithalweapon.geek.nz> <leith@mapbox.com>
Leonard Hecker <leonard.hecker91@gmail.com> <leonard@hecker.io>
Maciej Małecki <maciej.malecki@notimplemented.org> <me@mmalecki.com>
Marc Schlaich <marc.schlaich@googlemail.com> <marc.schlaich@gmail.com>
Michael <michael_dawson@ca.ibm.com>
Michael Neumann <mneumann@think.localnet> <mneumann@ntecs.de>
Rasmus Christian Pedersen <zerhacken@yahoo.com>
Rasmus Christian Pedersen <zerhacken@yahoo.com> <ruysch@outlook.com>
Robert Mustacchi <rm@joyent.com> <rm@fingolfin.org>
Ryan Dahl <ryan@joyent.com> <ry@tinyclouds.org>
Ryan Emery <seebees@gmail.com>
Sam Roberts <vieuxtech@gmail.com> <sam@strongloop.com>
San-Tai Hsu <vanilla@fatpipi.com>
Santiago Gimeno <santiago.gimeno@quantion.es> <santiago.gimeno@gmail.com>
Saúl Ibarra Corretgé <saghul@gmail.com>
Shigeki Ohtsu <ohtsu@iij.ad.jp> <ohtsu@ohtsu.org>
Timothy J. Fontaine <tjfontaine@gmail.com>
Yasuhiro Matsumoto <mattn.jp@gmail.com>
Yazhong Liu <yorkiefixer@gmail.com>
Yuki Okumura <mjt@cltn.org>

View File

@ -0,0 +1,227 @@
# Authors ordered by first contribution.
Ryan Dahl <ryan@joyent.com>
Bert Belder <bertbelder@gmail.com>
Josh Roesslein <jroesslein@gmail.com>
Alan Gutierrez <alan@prettyrobots.com>
Joshua Peek <josh@joshpeek.com>
Igor Zinkovsky <igorzi@microsoft.com>
San-Tai Hsu <vanilla@fatpipi.com>
Ben Noordhuis <info@bnoordhuis.nl>
Henry Rawas <henryr@schakra.com>
Robert Mustacchi <rm@joyent.com>
Matt Stevens <matt@alloysoft.com>
Paul Querna <pquerna@apache.org>
Shigeki Ohtsu <ohtsu@iij.ad.jp>
Tom Hughes <tom.hughes@palm.com>
Peter Bright <drpizza@quiscalusmexicanus.org>
Jeroen Janssen <jeroen.janssen@gmail.com>
Andrea Lattuada <ndr.lattuada@gmail.com>
Augusto Henrique Hentz <ahhentz@gmail.com>
Clifford Heath <clifford.heath@gmail.com>
Jorge Chamorro Bieling <jorge@jorgechamorro.com>
Luis Lavena <luislavena@gmail.com>
Matthew Sporleder <msporleder@gmail.com>
Erick Tryzelaar <erick.tryzelaar@gmail.com>
Isaac Z. Schlueter <i@izs.me>
Pieter Noordhuis <pcnoordhuis@gmail.com>
Marek Jelen <marek@jelen.biz>
Fedor Indutny <fedor.indutny@gmail.com>
Saúl Ibarra Corretgé <saghul@gmail.com>
Felix Geisendörfer <felix@debuggable.com>
Yuki Okumura <mjt@cltn.org>
Roman Shtylman <shtylman@gmail.com>
Frank Denis <github@pureftpd.org>
Carter Allen <CarterA@opt-6.com>
Tj Holowaychuk <tj@vision-media.ca>
Shimon Doodkin <helpmepro1@gmail.com>
Ryan Emery <seebees@gmail.com>
Bruce Mitchener <bruce.mitchener@gmail.com>
Maciej Małecki <maciej.malecki@notimplemented.org>
Yasuhiro Matsumoto <mattn.jp@gmail.com>
Daisuke Murase <typester@cpan.org>
Paddy Byers <paddy.byers@gmail.com>
Dan VerWeire <dverweire@gmail.com>
Brandon Benvie <brandon@bbenvie.com>
Brandon Philips <brandon.philips@rackspace.com>
Nathan Rajlich <nathan@tootallnate.net>
Charlie McConnell <charlie@charlieistheman.com>
Vladimir Dronnikov <dronnikov@gmail.com>
Aaron Bieber <qbit@deftly.net>
Bulat Shakirzyanov <mallluhuct@gmail.com>
Brian White <mscdex@mscdex.net>
Erik Dubbelboer <erik@dubbelboer.com>
Keno Fischer <kenof@stanford.edu>
Ira Cooper <Ira.Cooper@mathworks.com>
Andrius Bentkus <andrius.bentkus@gmail.com>
Iñaki Baz Castillo <ibc@aliax.net>
Mark Cavage <mark.cavage@joyent.com>
George Yohng <georgegh@oss3d.com>
Xidorn Quan <quanxunzhen@gmail.com>
Roman Neuhauser <rneuhauser@suse.cz>
Shuhei Tanuma <shuhei.tanuma@gmail.com>
Bryan Cantrill <bcantrill@acm.org>
Trond Norbye <trond.norbye@gmail.com>
Tim Holy <holy@wustl.edu>
Prancesco Pertugio <meh@schizofreni.co>
Leonard Hecker <leonard.hecker91@gmail.com>
Andrew Paprocki <andrew@ishiboo.com>
Luigi Grilli <luigi.grilli@gmail.com>
Shannen Saez <shannenlaptop@gmail.com>
Artur Adib <arturadib@gmail.com>
Hiroaki Nakamura <hnakamur@gmail.com>
Ting-Yu Lin <ph.minamo@cytisan.com>
Stephen Gallagher <sgallagh@redhat.com>
Shane Holloway <shane.holloway@ieee.org>
Andrew Shaffer <darawk@gmail.com>
Vlad Tudose <vlad.tudose@intel.com>
Ben Leslie <benno@benno.id.au>
Tim Bradshaw <tfb@cley.com>
Timothy J. Fontaine <tjfontaine@gmail.com>
Marc Schlaich <marc.schlaich@googlemail.com>
Brian Mazza <louseman@gmail.com>
Elliot Saba <staticfloat@gmail.com>
Ben Kelly <ben@wanderview.com>
Nils Maier <maierman@web.de>
Nicholas Vavilov <vvnicholas@gmail.com>
Miroslav Bajtoš <miro.bajtos@gmail.com>
Sean Silva <chisophugis@gmail.com>
Wynn Wilkes <wynnw@movenetworks.com>
Andrei Sedoi <bsnote@gmail.com>
Alex Crichton <alex@alexcrichton.com>
Brent Cook <brent@boundary.com>
Brian Kaisner <bkize1@gmail.com>
Luca Bruno <lucab@debian.org>
Reini Urban <rurban@cpanel.net>
Maks Naumov <maksqwe1@ukr.net>
Sean Farrell <sean.farrell@rioki.org>
Chris Bank <cbank@adobe.com>
Geert Jansen <geertj@gmail.com>
Christoph Iserlohn <christoph.iserlohn@innoq.com>
Steven Kabbes <stevenkabbes@gmail.com>
Alex Gaynor <alex.gaynor@gmail.com>
huxingyi <huxingyi@msn.com>
Tenor Biel <tenorbiel@gmail.com>
Andrej Manduch <AManduch@gmail.com>
Joshua Neuheisel <joshua@neuheisel.us>
Alexis Campailla <alexis@janeasystems.com>
Yazhong Liu <yorkiefixer@gmail.com>
Sam Roberts <vieuxtech@gmail.com>
River Tarnell <river@loreley.flyingparchment.org.uk>
Nathan Sweet <nathanjsweet@gmail.com>
Trevor Norris <trev.norris@gmail.com>
Oguz Bastemur <obastemur@gmail.com>
Dylan Cali <calid1984@gmail.com>
Austin Foxley <austinf@cetoncorp.com>
Benjamin Saunders <ben.e.saunders@gmail.com>
Geoffry Song <goffrie@gmail.com>
Rasmus Christian Pedersen <ruysch@outlook.com>
William Light <wrl@illest.net>
Oleg Efimov <o.efimov@corp.badoo.com>
Lars Gierth <larsg@systemli.org>
Rasmus Christian Pedersen <zerhacken@yahoo.com>
Justin Venus <justin.venus@gmail.com>
Kristian Evensen <kristian.evensen@gmail.com>
Linus Mårtensson <linus.martensson@sonymobile.com>
Navaneeth Kedaram Nambiathan <navaneethkn@gmail.com>
Yorkie <yorkiefixer@gmail.com>
StarWing <weasley.wx@gmail.com>
thierry-FreeBSD <thierry@FreeBSD.org>
Isaiah Norton <isaiah.norton@gmail.com>
Raul Martins <raulms.martins@gmail.com>
David Capello <davidcapello@gmail.com>
Paul Tan <pyokagan@gmail.com>
Javier Hernández <jhernandez@emergya.com>
Tonis Tiigi <tonistiigi@gmail.com>
Norio Kobota <nori.0428@gmail.com>
李港平 <chopdown@gmail.com>
Chernyshev Viacheslav <astellar@ro.ru>
Stephen von Takach <steve@advancedcontrol.com.au>
JD Ballard <jd@pixelandline.com>
Luka Perkov <luka.perkov@sartura.hr>
Ryan Cole <ryan@rycole.com>
HungMingWu <u9089000@gmail.com>
Jay Satiro <raysatiro@yahoo.com>
Leith Bade <leith@leithalweapon.geek.nz>
Peter Atashian <retep998@gmail.com>
Tim Cooper <tim.cooper@layeh.com>
Caleb James DeLisle <cjd@hyperboria.ca>
Jameson Nash <vtjnash@gmail.com>
Graham Lee <ghmlee@ghmlee.com>
Andrew Low <Andrew_Low@ca.ibm.com>
Pavel Platto <hinidu@gmail.com>
Tony Kelman <tony@kelman.net>
John Firebaugh <john.firebaugh@gmail.com>
lilohuang <lilohuang@hotmail.com>
Paul Goldsmith <paul.goldsmith@aplink.net>
Julien Gilli <julien.gilli@joyent.com>
Michael Hudson-Doyle <michael.hudson@linaro.org>
Recep ASLANTAS <m@recp.me>
Rob Adams <readams@readams.net>
Zachary Newman <znewman01@gmail.com>
Robin Hahling <robin.hahling@gw-computing.net>
Jeff Widman <jeff@jeffwidman.com>
cjihrig <cjihrig@gmail.com>
Tomasz Kołodziejski <tkolodziejski@mozilla.com>
Unknown W. Brackets <checkins@unknownbrackets.org>
Emmanuel Odeke <odeke@ualberta.ca>
Mikhail Mukovnikov <yndi@me.com>
Thorsten Lorenz <thlorenz@gmx.de>
Yuri D'Elia <yuri.delia@eurac.edu>
Manos Nikolaidis <manos@shadowrobot.com>
Elijah Andrews <elijah@busbud.com>
Michael Ira Krufky <m.krufky@samsung.com>
Helge Deller <deller@gmx.de>
Joey Geralnik <jgeralnik@gmail.com>
Tim Caswell <tim@creationix.com>
Logan Rosen <loganrosen@gmail.com>
Kenneth Perry <thothonegan@gmail.com>
John Marino <marino@FreeBSD.org>
Alexey Melnichuk <mimir@newmail.ru>
Johan Bergström <bugs@bergstroem.nu>
Alex Mo <almosnow@gmail.com>
Luis Martinez de Bartolome <lasote@gmail.com>
Michael Penick <michael.penick@datastax.com>
Michael <michael_dawson@ca.ibm.com>
Massimiliano Torromeo <massimiliano.torromeo@gmail.com>
TomCrypto <thomas.beneteau@yahoo.fr>
Brett Vickers <brett@beevik.com>
Ole André Vadla Ravnås <oleavr@gmail.com>
Kazuho Oku <kazuhooku@gmail.com>
Ryan Phillips <ryan.phillips@rackspace.com>
Brian Green <briangreenery@gmail.com>
Devchandra Meetei Leishangthem <dlmeetei@gmail.com>
Corey Farrell <git@cfware.com>
Per Nilsson <pni@qlik.com>
Alan Rogers <alanjrogers@me.com>
Daryl Haresign <github@daryl.haresign.com>
Rui Abreu Ferreira <raf-ep@gmx.com>
João Reis <reis@janeasystems.com>
farblue68 <farblue68@gmail.com>
Jason Williams <necmon@yahoo.com>
Igor Soarez <igorsoarez@gmail.com>
Miodrag Milanovic <mmicko@gmail.com>
Cheng Zhao <zcbenz@gmail.com>
Michael Neumann <mneumann@think.localnet>
Stefano Cristiano <stefanocristiano82@gmail.com>
heshamsafi <hesham.safi.eldeen@gmail.com>
A. Hauptmann <andreashauptmann@t-online.de>
John McNamee <jpm@microwiz.com>
Yosuke Furukawa <yosuke.furukawa@gmail.com>
Santiago Gimeno <santiago.gimeno@quantion.es>
guworks <ground.up.works@gmail.com>
RossBencina <rossb@audiomulch.com>
Roger A. Light <roger@atchoo.org>
chenttuuvv <chenttuuvv@yahoo.com>
Richard Lau <riclau@uk.ibm.com>
ronkorving <rkorving@wizcorp.jp>
Corbin Simpson <MostAwesomeDude@gmail.com>
Zachary Hamm <zsh@imipolexg.org>
Karl Skomski <karl@skomski.com>
Jeremy Whitlock <jwhitlock@apache.org>
Willem Thiart <himself@willemthiart.com>
Ben Trask <bentrask@comcast.net>
Jianghua Yang <jianghua.yjh@alibaba-inc.com>
Colin Snover <github.com@zetafleet.com>
Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
Eli Skeggs <skeggse@gmail.com>
nmushell <nmushell@bloomberg.net>

View File

@ -0,0 +1,166 @@
# 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 `include/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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,46 @@
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.

View File

@ -0,0 +1,36 @@
# Project Maintainers
libuv is currently managed by the following individuals:
* **Ben Noordhuis** ([@bnoordhuis](https://github.com/bnoordhuis))
- GPG key: D77B 1E34 243F BAF0 5F8E 9CC3 4F55 C8C8 46AB 89B9 (pubkey-bnoordhuis)
* **Bert Belder** ([@piscisaureus](https://github.com/piscisaureus))
* **Fedor Indutny** ([@indutny](https://github.com/indutny))
- GPG key: AF2E EA41 EC34 47BF DD86 FED9 D706 3CCE 19B7 E890 (pubkey-indutny)
* **Saúl Ibarra Corretgé** ([@saghul](https://github.com/saghul))
- GPG key: FDF5 1936 4458 319F A823 3DC9 410E 5553 AE9B C059 (pubkey-saghul)
## Storing a maintainer key in Git
It's quite handy to store a maintainer's signature as a git blob, and have
that object tagged and signed with such key.
Export your public key:
$ gpg --armor --export saghul@gmail.com > saghul.asc
Store it as a blob on the repo:
$ git hash-object -w saghul.asc
The previous command returns a hash, copy it. For the sake of this explanation,
we'll assume it's 'abcd1234'. Storing the blob in git is not enough, it could
be garbage collected since nothing references it, so we'll create a tag for it:
$ git tag -s pubkey-saghul abcd1234
Commit the changes and push:
$ git push origin pubkey-saghul

View File

@ -0,0 +1,343 @@
# Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
#
# 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 -luserenv
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-homedir.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-connect-multiple.c \
test/test-pipe-connect-prepare.c \
test/test-pipe-getsockname.c \
test/test-pipe-pending-instances.c \
test/test-pipe-sendmsg.c \
test/test-pipe-server-close.c \
test/test-pipe-close-stdout-read-stdin.c \
test/test-pipe-set-non-blocking.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-create-socket-early.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-oob.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-write-fail.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-create-socket-early.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
include_HEADERS += include/uv-aix.h
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

View File

@ -0,0 +1,84 @@
# Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
#
# 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 $@ $<

View File

@ -0,0 +1,245 @@
![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).
The [tests and benchmarks](https://github.com/libuv/libuv/tree/master/test)
also serve as API specification and usage examples.
### Other resources
* [An Introduction to libuv](http://nikhilm.github.com/uvbook/)
&mdash; An overview of libuv with tutorials.
* [LXJS 2012 talk](http://www.youtube.com/watch?v=nGn60vDSxQ4)
&mdash; High-level introductory talk about libuv.
* [libuv-dox](https://github.com/thlorenz/libuv-dox)
&mdash; Documenting types and methods of libuv, mostly by reading uv.h.
* [learnuv](https://github.com/thlorenz/learnuv)
&mdash; Learn uv for fun and profit, a self guided workshop to libuv.
These resources are not handled by libuv maintainers and might be out of
date. Please verify it before opening new issues.
## Downloading
libuv can be downloaded either from the
[GitHub repository](https://github.com/libuv/libuv)
or from the [downloads site](http://dist.libuv.org/dist/).
Starting with libuv 1.7.0, binaries for Windows are also provided. This is to
be considered EXPERIMENTAL.
Before verifying the git tags or signature files, importing the relevant keys
is necessary. Key IDs are listed in the
[MAINTAINERS](https://github.com/libuv/libuv/blob/master/MAINTAINERS.md)
file, but are also available as git blob objects for easier use.
Importing a key the usual way:
$ gpg --keyserver pool.sks-keyservers.net \
--recv-keys AE9BC059
Importing a key from a git blob object:
$ git show pubkey-saghul | gpg --import
### Verifying releases
Git tags are signed with the developer's key, they can be verified as follows:
$ git verify-tag v1.6.1
Starting with libuv 1.7.0, the tarballs stored in the
[downloads site](http://dist.libuv.org/dist/) are signed and an accomanying
signature file sit alongside each. Once both the release tarball and the
signature file are downloaded, the file can be verified as follows:
$ gpg --verify libuv-1.7.0.tar.gz.sign
## 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
### 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.
### Using Ninja
To use ninja for build on ninja supported platforms, run:
$ ./gyp_uv.py -f ninja
$ ninja -C out/Debug #for debug build OR
$ ninja -C out/Release
### 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.
AIX 6 and later using GCC toolchain (see notes).
### AIX Notes
AIX support for filesystem events requires the non-default IBM `bos.ahafs`
package to be installed. This package provides the AIX Event Infrastructure
that is detected by `autoconf`.
[IBM documentation](http://www.ibm.com/developerworks/aix/library/au-aix_event_infrastructure/)
describes the package in more detail.
AIX support for filesystem events is not compiled when building with `gyp`.
## 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

View File

@ -0,0 +1,20 @@
#!/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-21
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 -f make-android
fi

View File

@ -0,0 +1,36 @@
version: v1.7.5.build{build}
install:
- cinst -y nsis
matrix:
fast_finish: true
allow_failures:
- platform: x86
configuration: Release
- platform: x64
configuration: Release
platform:
- x86
- x64
configuration:
- Release
build_script:
# Fixed tag version number if using a tag.
- cmd: if "%APPVEYOR_REPO_TAG%" == "true" set APPVEYOR_BUILD_VERSION=%APPVEYOR_REPO_TAG_NAME%
# vcbuild overwrites the platform variable.
- cmd: set ARCH=%platform%
- cmd: vcbuild.bat release %ARCH% shared
after_build:
- '"%PROGRAMFILES(x86)%\NSIS\makensis" /DVERSION=%APPVEYOR_BUILD_VERSION% /DARCH=%ARCH% libuv.nsi'
artifacts:
- name: Installer
path: 'libuv-*.exe'
cache:
- C:\projects\libuv\build\gyp

46
outside/libuv-v1.7.5/autogen.sh Executable file
View File

@ -0,0 +1,46 @@
#!/bin/sh
# Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
#
# 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

View File

@ -0,0 +1,234 @@
#!/bin/sh
# Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
#
# 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-homedir.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-oob.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

View File

@ -0,0 +1,211 @@
{
'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 == "android"', {
'cflags': [ '-fPIE' ],
'ldflags': [ '-fPIE', '-pie' ]
}]
]
},
'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 dragonflybsd 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' ]
}],
],
},
}

View File

@ -0,0 +1,68 @@
# Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
#
# 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.7.5], [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_HEADERS([sys/ahafs_evProds.h])
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

View File

@ -0,0 +1,178 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = build
SRCDIR = src
# User-friendly check for sphinx-build
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
endif
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SRCDIR)
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SRCDIR)
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
help:
@echo "Please use \`make <target>' where <target> 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 " latexpdf to make LaTeX files and run them through pdflatex"
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of 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)"
clean:
rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@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.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/libuv"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/libuv"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
latexpdfja:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
xml:
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
@echo
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."

View File

@ -0,0 +1,243 @@
@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 ^<target^>` where ^<target^> 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

View File

@ -0,0 +1,57 @@
.. _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.

View File

@ -0,0 +1,46 @@
.. _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* loop, 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.

View File

@ -0,0 +1,348 @@
# -*- 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('sphinx-plugins'))
# -- 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 = ['manpage']
# 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
# "<project> v<release> 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 <link> 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

View File

@ -0,0 +1,137 @@
.. _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 where 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
across 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 <http://blog.libtorrent.org/2012/10/asynchronous-disk-io/>`_.
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.

View File

@ -0,0 +1,44 @@
.. _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:: int 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.

View File

@ -0,0 +1,108 @@
.. _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.
.. c:member:: char[NI_MAXHOST] uv_getnameinfo_t.host
Char array containing the resulting host. It's null terminated.
.. versionchanged:: 1.3.0 the field is declared as public.
.. c:member:: char[NI_MAXSERV] uv_getnameinfo_t.service
Char array containing the resulting service. It's null terminated.
.. versionchanged:: 1.3.0 the field is declared as public.
.. 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 :man:`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 :man:`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.

View File

@ -0,0 +1,331 @@
.. _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. Leaks a few bytes
of memory when you call it with an unknown error code.
.. c:function:: const char* uv_err_name(int err)
Returns the error name for the given error code. Leaks a few bytes
of memory when you call it with an unknown error code.

View File

@ -0,0 +1,290 @@
.. _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 :man:`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 :man:`open(2)`.
.. note::
On Windows libuv uses `CreateFileW` and thus the file is always opened
in binary mode. Because of this the O_BINARY and O_TEXT flags are not
supported.
.. 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 :man:`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 :man:`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 :man:`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 :man:`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 :man:`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 :man:`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 :man:`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.
.. note::
Unlike `scandir(3)`, this function does not return the "." and ".." entries.
.. note::
On Linux, getting the type of an entry is only supported by some filesystems (btrfs, ext2,
ext3 and ext4 at the time of this writing), check the :man:`getdents(2)` man page.
.. 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 :man:`stat(2)`, :man:`fstat(2)` and :man:`fstat(2)` respectively.
.. 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 :man:`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 :man:`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 :man:`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 :man:`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 :man:`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 :man:`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 :man:`chmod(2)` and :man:`fchmod(2)` respectively.
.. 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 :man:`utime(2)` and :man:`futime(2)` respectively.
.. 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 :man:`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 :man:`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 :man:`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 :man:`chown(2)` and :man:`fchown(2)` respectively.
.. note::
These functions are not implemented on Windows.
.. seealso:: The :c:type:`uv_req_t` API functions also apply.

View File

@ -0,0 +1,108 @@
.. _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 and Windows.
.. 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.

View File

@ -0,0 +1,72 @@
.. _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.

View File

@ -0,0 +1,181 @@
.. _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.

View File

@ -0,0 +1,54 @@
.. _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* loop, 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.

View File

@ -0,0 +1,95 @@
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 <https://github.com/libuv/libuv>`_!
.. _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 <http://dist.libuv.org/dist/>`_.
Installation
------------
Installation instructions can be found on `the README <https://github.com/libuv/libuv/blob/master/README.md>`_.
Upgrading
---------
Migration guides for different libuv versions, starting with 1.0.
.. toctree::
:maxdepth: 1
migration_010_100
Documentation
-------------
.. toctree::
:maxdepth: 1
design
errors
version
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

View File

@ -0,0 +1,166 @@
.. _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. Returns non-zero if :c:func:`uv_stop`
was called and there are still active handles or requests. Returns
zero in all other cases.
- 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`.

View File

@ -0,0 +1,244 @@
.. _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.

View File

@ -0,0 +1,290 @@
.. _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:member:: char* uv_buf_t.base
Pointer to the base of the buffer. Readonly.
.. c:member:: size_t uv_buf_t.len
Total bytes in the buffer. Readonly.
.. note::
On Windows this field is ULONG.
.. c:type:: void* (*uv_malloc_func)(size_t size)
Replacement function for :man:`malloc(3)`.
See :c:func:`uv_replace_allocator`.
.. c:type:: void* (*uv_realloc_func)(void* ptr, size_t size)
Replacement function for :man:`realloc(3)`.
See :c:func:`uv_replace_allocator`.
.. c:type:: void* (*uv_calloc_func)(size_t count, size_t size)
Replacement function for :man:`calloc(3)`.
See :c:func:`uv_replace_allocator`.
.. c:type:: void (*uv_free_func)(void* ptr)
Replacement function for :man:`free(3)`.
See :c:func:`uv_replace_allocator`.
.. 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 a `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 :man:`isatty(3)` equivalent functionality use this function and test
for ``UV_TTY``.
.. c:function:: int uv_replace_allocator(uv_malloc_func malloc_func, uv_realloc_func realloc_func, uv_calloc_func calloc_func, uv_free_func free_func)
.. versionadded:: 1.6.0
Override the use of the standard library's :man:`malloc(3)`,
:man:`calloc(3)`, :man:`realloc(3)`, :man:`free(3)`, memory allocation
functions.
This function must be called before any other libuv function is called or
after all resources have been freed and thus libuv doesn't reference
any allocated memory chunk.
On success, it returns 0, if any of the function pointers is NULL it
returns UV_EINVAL.
.. warning:: There is no protection against changing the allocator multiple
times. If the user changes it they are responsible for making
sure the allocator is changed while no memory was allocated with
the previous allocator, or that they are compatible.
.. 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: `<http://en.wikipedia.org/wiki/Load_(computing)>`_
.. 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 :man:`inet_ntop(3)`
and :man:`inet_pton(3)`. 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.
.. c:function:: int uv_os_homedir(char* buffer, size_t* size)
Gets the current user's home directory. On Windows, `uv_os_homedir()` first
checks the `USERPROFILE` environment variable using
`GetEnvironmentVariableW()`. If `USERPROFILE` is not set,
`GetUserProfileDirectoryW()` is called. On all other operating systems,
`uv_os_homedir()` first checks the `HOME` environment variable using
:man:`getenv(3)`. If `HOME` is not set, :man:`getpwuid_r(3)` is called. The
user's home directory is stored in `buffer`. When `uv_os_homedir()` is
called, `size` indicates the maximum size of `buffer`. On success or
`UV_ENOBUFS` failure, `size` is set to the string length of `buffer`.
.. warning::
`uv_os_homedir()` is not thread safe.
.. versionadded:: 1.6.0
.. 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.

View File

@ -0,0 +1,104 @@
.. _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* loop, 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* handle, 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.
.. note::
The passed file descriptor or HANDLE is not checked for its type, but
it's required that it represents a valid pipe.
.. 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.

View File

@ -0,0 +1,103 @@
.. _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 :man:`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 :man:`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.

View File

@ -0,0 +1,46 @@
.. _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.

View File

@ -0,0 +1,225 @@
.. _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.

View File

@ -0,0 +1,82 @@
.. _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_req_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.

View File

@ -0,0 +1,77 @@
.. _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* loop, 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.

View File

@ -0,0 +1,46 @@
# encoding: utf-8
#
# Copyright (c) 2013 Dariusz Dwornikowski. All rights reserved.
#
# Adapted from https://github.com/tdi/sphinxcontrib-manpage
# License: Apache 2
#
import re
from docutils import nodes, utils
from docutils.parsers.rst.roles import set_classes
from string import Template
def make_link_node(rawtext, app, name, manpage_num, options):
ref = app.config.man_url_regex
if not ref:
ref = "http://linux.die.net/man/%s/%s" % (manpage_num, name)
else:
s = Template(ref)
ref = s.substitute(num=manpage_num, topic=name)
set_classes(options)
node = nodes.reference(rawtext, "%s(%s)" % (name, manpage_num), refuri=ref, **options)
return node
def man_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
app = inliner.document.settings.env.app
p = re.compile("([a-zA-Z0-9_\.-_]+)\((\d)\)")
m = p.match(text)
manpage_num = m.group(2)
name = m.group(1)
node = make_link_node(rawtext, app, name, manpage_num, options)
return [node], []
def setup(app):
app.info('Initializing manpage plugin')
app.add_role('man', man_role)
app.add_config_value('man_url_regex', None, 'env')
return

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<string>Template: White (2014-02-28 09:41)</string>
<string>M6.2.2-1878-1</string>
</array>
</plist>

View File

@ -0,0 +1 @@
F69E9CD9-EEF1-4223-9DA4-A1EA7FE112BA

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

View File

@ -0,0 +1,219 @@
.. _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 or < 0 on error. 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 be 0, which does *not* indicate an error or EOF. This
is equivalent to ``EAGAIN`` or ``EWOULDBLOCK`` under ``read(2)``.
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 :man:`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* stream, uv_alloc_cb alloc_cb, uv_read_cb read_cb)
Read data from an incoming stream. The :c:type:`uv_read_cb` callback will
be made several times until there is no more data to read or
:c:func:`uv_read_stop` is called.
.. 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.
This function is idempotent and may be safely called on a stopped stream.
.. 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 only works on Windows for :c:type:`uv_pipe_t` handles.
On UNIX platforms, all :c:type:`uv_stream_t` handles are supported.
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.
.. versionchanged:: 1.4.0 UNIX implementation added.
.. seealso:: The :c:type:`uv_handle_t` API functions also apply.

View File

@ -0,0 +1,108 @@
.. _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* loop, uv_tcp_t* handle)
Initialize the handle. No socket is created as of yet.
.. c:function:: int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* handle, unsigned int flags)
Initialize the handle with the specified flags. At the moment the lower 8 bits
of the `flags` parameter are used as the socket domain. A socket will be created
for the given domain. If the specified domain is ``AF_UNSPEC`` no socket is created,
just like :c:func:`uv_tcp_init`.
.. versionadded:: 1.7.0
.. 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.
.. note::
The passed file descriptor or SOCKET is not checked for its type, but
it's required that it represents a valid stream socket.
.. 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` can 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.

View File

@ -0,0 +1,160 @@
.. _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)
.. versionchanged:: 1.4.1 returns a UV_E* error code on failure
.. 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)

View File

@ -0,0 +1,67 @@
.. _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.
.. note::
Note that even though a global thread pool which is shared across all events
loops is used, the functions are not thread safe.
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.

View File

@ -0,0 +1,76 @@
.. _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 interval value in milliseconds. The timer will be scheduled
to run on the given interval, regardless of the callback execution
duration, and will follow normal timer semantics in the case of a
time-slice overrun.
For example, if a 50ms repeating timer first runs for 17ms, it will be
scheduled to run again 33ms later. If other tasks consume more than the
33ms following the first timer callback, then the callback will run as soon
as possible.
.. 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.

View File

@ -0,0 +1,93 @@
.. _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* loop, uv_tty_t* handle, 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.
.. versionchanged:: 1.5.0: trying to initialize a TTY stream with a file
descriptor that refers to a file returns `UV_EINVAL`
on UNIX.
.. c:function:: int uv_tty_set_mode(uv_tty_t* handle, 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* handle, 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.

View File

@ -0,0 +1,295 @@
.. _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* loop, uv_udp_t* handle)
Initialize a new UDP handle. The actual socket is created lazily.
Returns 0 on success.
.. c:function:: int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags)
Initialize the handle with the specified flags. At the moment the lower 8 bits
of the `flags` parameter are used as the socket domain. A socket will be created
for the given domain. If the specified domain is ``AF_UNSPEC`` no socket is created,
just like :c:func:`uv_udp_init`.
.. versionadded:: 1.7.0
.. 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.
.. note::
The passed file descriptor or SOCKET is not checked for its type, but
it's required that it represents a valid datagram socket.
.. 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.

View File

@ -0,0 +1,60 @@
.. _version:
Version-checking macros and functions
=====================================
Starting with version 1.0.0 libuv follows the `semantic versioning`_
scheme. This means that new APIs can be introduced throughout the lifetime of
a major release. In this section you'll find all macros and functions that
will allow you to write or compile code conditionally, in order to work with
multiple libuv versions.
.. _semantic versioning: http://semver.org
Macros
------
.. c:macro:: UV_VERSION_MAJOR
libuv version's major number.
.. c:macro:: UV_VERSION_MINOR
libuv version's minor number.
.. c:macro:: UV_VERSION_PATCH
libuv version's patch number.
.. c:macro:: UV_VERSION_IS_RELEASE
Set to 1 to indicate a release version of libuv, 0 for a development
snapshot.
.. c:macro:: UV_VERSION_SUFFIX
libuv version suffix. Certain development releases such as Release Candidates
might have a suffix such as "rc".
.. c:macro:: UV_VERSION_HEX
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 be 0x010203.
.. versionadded:: 1.7.0
Functions
---------
.. c:function:: unsigned int uv_version(void)
Returns :c:macro:`UV_VERSION_HEX`.
.. c:function:: const char* uv_version_string(void)
Returns the libuv version number as a string. For non-release versions the
version suffix is included.

96
outside/libuv-v1.7.5/gyp_uv.py Executable file
View File

@ -0,0 +1,96 @@
#!/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)

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 64 KiB

View File

@ -0,0 +1,54 @@
/*
* 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 <net/if.h>. Note that if <net/if.h> 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 <sys/cdefs.h>
__BEGIN_DECLS
extern int getifaddrs(struct ifaddrs **ifap);
extern void freeifaddrs(struct ifaddrs *ifa);
__END_DECLS
#endif

View File

@ -0,0 +1,72 @@
/* 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 <pthread.h>
/*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 */

View File

@ -0,0 +1,247 @@
// 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 <limits.h>
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
// compiling for ARM we should wrap <wchar.h> 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 <wchar.h>
#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 <wchar.h>
#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_ ]

View File

@ -0,0 +1,768 @@
/*-
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* 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_ */

View File

@ -0,0 +1,32 @@
/* 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 */

View File

@ -0,0 +1,34 @@
/* 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 */

View File

@ -0,0 +1,61 @@
/* 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 <mach/mach.h>
# include <mach/task.h>
# include <mach/semaphore.h>
# include <TargetConditionals.h>
# 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 */

View File

@ -0,0 +1,418 @@
/* 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 <errno.h>
#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
/* EHOSTDOWN is not visible on BSD-like systems when _POSIX_C_SOURCE is
* defined. Fortunately, its value is always 64 so it's possible albeit
* icky to hard-code it.
*/
#if defined(EHOSTDOWN) && !defined(_WIN32)
# define UV__EHOSTDOWN (-EHOSTDOWN)
#elif defined(__APPLE__) || \
defined(__DragonFly__) || \
defined(__FreeBSD__) || \
defined(__NetBSD__) || \
defined(__OpenBSD__)
# define UV__EHOSTDOWN (-64)
#else
# define UV__EHOSTDOWN (-4031)
#endif
#endif /* UV_ERRNO_H_ */

View File

@ -0,0 +1,34 @@
/* 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 */

View File

@ -0,0 +1,44 @@
/* 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 <sys/port.h>
#include <port.h>
/* 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 */

View File

@ -0,0 +1,37 @@
/* 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_ */

View File

@ -0,0 +1,383 @@
/* 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 <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <termios.h>
#include <pwd.h>
#include <semaphore.h>
#include <pthread.h>
#ifdef __ANDROID__
#include "pthread-fixes.h"
#endif
#include <signal.h>
#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 */

View File

@ -0,0 +1,43 @@
/* 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 7
#define UV_VERSION_PATCH 5
#define UV_VERSION_IS_RELEASE 1
#define UV_VERSION_SUFFIX ""
#define UV_VERSION_HEX ((UV_VERSION_MAJOR << 16) | \
(UV_VERSION_MINOR << 8) | \
(UV_VERSION_PATCH))
#endif /* UV_VERSION_H */

View File

@ -0,0 +1,653 @@
/* 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 <winsock2.h>
#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
#include <mswsock.h>
#include <ws2tcpip.h>
#include <windows.h>
#include <process.h>
#include <signal.h>
#include <sys/stat.h>
#if defined(_MSC_VER) && _MSC_VER < 1600
# include "stdint-msvc2008.h"
#else
# include <stdint.h>
#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 {
struct {
unsigned int num_readers_;
CRITICAL_SECTION num_readers_lock_;
HANDLE write_semaphore_;
} state_;
/* TODO: remove me in v2.x. */
struct {
SRWLOCK unused_;
} unused1_;
/* TODO: remove me in v2.x. */
struct {
uv_mutex_t unused1_;
uv_mutex_t unused2_;
} unused2_;
} 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 HAVE_DIRENT_TYPES
#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; \
} io; \
} u; \
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 } conn; \
struct { uv_stream_server_fields } serv; \
} stream;
#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 } serv; \
struct { uv_tcp_connection_fields } conn; \
} tcp;
#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 } serv; \
struct { uv_pipe_connection_fields } conn; \
} pipe;
/* 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; \
} rd; \
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; \
} wr; \
} tty;
#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; \
} file; \
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]; \
} info; \
struct { \
double atime; \
double mtime; \
} time; \
} fs;
#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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,86 @@
; NSIS installer script for libuv
!include "MUI2.nsh"
Name "libuv"
OutFile "libuv-${ARCH}-${VERSION}.exe"
!include "x64.nsh"
# Default install location, for 32-bit files
InstallDir "$PROGRAMFILES\libuv"
# Override install and registry locations if this is a 64-bit install.
function .onInit
${If} ${ARCH} == "x64"
SetRegView 64
StrCpy $INSTDIR "$PROGRAMFILES64\libuv"
${EndIf}
functionEnd
;--------------------------------
; Installer pages
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
;--------------------------------
; Uninstaller pages
!insertmacro MUI_UNPAGE_WELCOME
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_UNPAGE_FINISH
;--------------------------------
; Languages
!insertmacro MUI_LANGUAGE "English"
;--------------------------------
; Installer sections
Section "Files" SecInstall
SectionIn RO
SetOutPath "$INSTDIR"
File "Release\*.dll"
File "Release\*.lib"
File "LICENSE"
File "README.md"
SetOutPath "$INSTDIR\include"
File "include\uv.h"
File "include\uv-errno.h"
File "include\uv-threadpool.h"
File "include\uv-version.h"
File "include\uv-win.h"
File "include\tree.h"
WriteUninstaller "$INSTDIR\Uninstall.exe"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\libuv-${ARCH}-${VERSION}" "DisplayName" "libuv-${ARCH}-${VERSION}"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\libuv-${ARCH}-${VERSION}" "UninstallString" "$\"$INSTDIR\Uninstall.exe$\""
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\libuv-${ARCH}-${VERSION}" "QuietUninstallString" "$\"$INSTDIR\Uninstall.exe$\" /S"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\libuv-${ARCH}-${VERSION}" "HelpLink" "http://libuv.org/"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\libuv-${ARCH}-${VERSION}" "URLInfoAbout" "http://libuv.org/"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\libuv-${ARCH}-${VERSION}" "DisplayVersion" "${VERSION}"
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\libuv-${ARCH}-${VERSION}" "NoModify" "1"
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\libuv-${ARCH}-${VERSION}" "NoRepair" "1"
SectionEnd
Section "Uninstall"
Delete "$INSTDIR\libuv.dll"
Delete "$INSTDIR\libuv.lib"
Delete "$INSTDIR\LICENSE"
Delete "$INSTDIR\README.md"
Delete "$INSTDIR\include\uv.h"
Delete "$INSTDIR\include\uv-errno.h"
Delete "$INSTDIR\include\uv-threadpool.h"
Delete "$INSTDIR\include\uv-version.h"
Delete "$INSTDIR\include\uv-win.h"
Delete "$INSTDIR\include\tree.h"
Delete "$INSTDIR\Uninstall.exe"
RMDir "$INSTDIR"
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\libuv-${ARCH}-${VERSION}"
SectionEnd

View File

@ -0,0 +1,11 @@
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}

4
outside/libuv-v1.7.5/m4/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
# Ignore libtoolize-generated files.
*.m4
!as_case.m4
!libuv-check-flags.m4

View File

@ -0,0 +1,21 @@
# 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])])

View File

@ -0,0 +1,319 @@
dnl Macros to check the presence of generic (non-typed) symbols.
dnl Copyright (c) 2006-2008 Diego Pettenà <flameeyes gmail com>
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
])

22
outside/libuv-v1.7.5/samples/.gitignore vendored Normal file
View File

@ -0,0 +1,22 @@
# 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

View File

@ -0,0 +1,21 @@
# 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/

View File

@ -0,0 +1,53 @@
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.

View File

@ -0,0 +1,46 @@
# 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.
BUILDTYPE ?= Debug
BUILDDIR ?= build
GYP ?= gyp
V ?=
SOURCES := client.c defs.h getopt.c main.c s5.c s5.h server.c util.c
.PHONY: all clean
all: $(BUILDDIR)/$(BUILDTYPE)/s5-proxy
clean:
$(RM) $(BUILDDIR)
$(BUILDDIR)/$(BUILDTYPE)/s5-proxy: $(BUILDDIR)/Makefile $(SOURCES)
$(MAKE) -C $(BUILDDIR) V=$(V)
$(BUILDDIR)/Makefile: ../../common.gypi build.gyp
$(GYP) \
-Duv_library=static_library \
-Goutput_dir=. \
-I../../common.gypi \
-f make \
--depth=. \
--generator-output=$(BUILDDIR) \
build.gyp

View File

@ -0,0 +1,46 @@
# 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']
}]
]
}
]
}

View File

@ -0,0 +1,737 @@
/* 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 <errno.h>
#include <stdlib.h>
#include <string.h>
/* 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);
}

View File

@ -0,0 +1,139 @@
/* 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 <assert.h>
#include <netinet/in.h> /* sockaddr_in, sockaddr_in6 */
#include <stddef.h> /* size_t, ssize_t */
#include <stdint.h>
#include <sys/socket.h> /* 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_ */

View File

@ -0,0 +1,131 @@
/* $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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
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 */
}

View File

@ -0,0 +1,99 @@
/* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h> /* 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 <address> [-h] [-p <port>]\n"
"\n"
"Options:\n"
"\n"
" -b <hostname|address> Bind to this address or hostname.\n"
" Default: \"127.0.0.1\"\n"
" -h Show this help message.\n"
" -p <port> Bind to this port number. Default: 1080\n"
"",
progname);
exit(1);
}

View File

@ -0,0 +1,271 @@
/* 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 <errno.h>
#include <stdint.h>
#include <stdlib.h> /* abort() */
#include <string.h> /* 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.";
}

View File

@ -0,0 +1,94 @@
/* 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 <stddef.h>
#include <stdint.h>
#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_ */

View File

@ -0,0 +1,241 @@
/* 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 <netinet/in.h> /* INET6_ADDRSTRLEN */
#include <stdlib.h>
#include <string.h>
#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;
}

View File

@ -0,0 +1,72 @@
/* 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 <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
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);
}

View File

@ -0,0 +1,255 @@
/* 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 <assert.h>
#include <stdlib.h>
#include <string.h>
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 = uv__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:
uv__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) {
uv__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 */

View File

@ -0,0 +1,245 @@
/* Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
*
* 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 <stddef.h> /* 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_ */

Some files were not shown because too many files have changed in this diff Show More