diff options
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | README.md | 28 | ||||
-rw-r--r-- | common.gypi | 82 | ||||
-rwxr-xr-x | gyp_uv_link | 97 | ||||
-rw-r--r-- | include/uv_link.h | 61 | ||||
-rw-r--r-- | src/common.h | 7 | ||||
-rw-r--r-- | src/uv_link.c | 10 | ||||
-rw-r--r-- | src/uv_link_source.c | 160 | ||||
-rw-r--r-- | test/deps/.gitkeep | 0 | ||||
-rw-r--r-- | uv_link_t.gyp | 22 |
10 files changed, 470 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e5fe69e --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +test/deps/libuv +tools/gyp +out/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..d9c3ffb --- /dev/null +++ b/README.md @@ -0,0 +1,28 @@ +# uv_link_t + +WIP + +## LICENSE + +This software is licensed under the MIT License. + +Copyright Fedor Indutny, 2016. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the +following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/common.gypi b/common.gypi new file mode 100644 index 0000000..3a9c481 --- /dev/null +++ b/common.gypi @@ -0,0 +1,82 @@ +{ + "variables": { + "visibility%": "hidden", # V8"s visibility setting + "target_arch%": "ia32", # set v8"s target architecture + "host_arch%": "ia32", # set v8"s host architecture + "library%": "static_library", # allow override to "shared_library" for DLL/.so builds + "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 + "gcc_version%": "unknown", + "clang%": 1, + "openssl_fips%": "false", + "bud_asan%": "false", + "conditions": [ + ["GENERATOR == 'ninja'", { + "OBJ_DIR": "<(PRODUCT_DIR)/obj", + }, { + "OBJ_DIR": "<(PRODUCT_DIR)/obj.target", + }], + ], + }, + + "target_defaults": { + "default_configuration": "Release", + "configurations": { + "Debug": { + "defines": [ "DEBUG", "_DEBUG" ], + "cflags": [ "-g", "-O0", "-fwrapv", "-Wno-parentheses-equality" ], + "xcode_settings": { + "GCC_OPTIMIZATION_LEVEL": "0" + }, + }, + "Release": { + "defines": [ "NDEBUG" ], + "cflags": [ "-g" ], + } + }, + + "xcode_settings": { + "GCC_VERSION": "com.apple.compilers.llvm.clang.1_0", + "GCC_WARN_ABOUT_MISSING_NEWLINE": "YES", # -Wnewline-eof + "PREBINDING": "NO", # No -Wl,-prebind + "OTHER_CFLAGS": [ + "-fstrict-aliasing", + "-g", + ], + "WARNING_CFLAGS": [ + "-Wall", + "-Wendif-labels", + "-W", + "-Wno-unused-parameter", + "-Wundeclared-selector", + "-Wno-parentheses-equality", + ], + }, + "conditions": [ + ["target_arch=='ia32'", { + "xcode_settings": {"ARCHS": ["i386"]}, + }], + ["target_arch=='x64'", { + "xcode_settings": {"ARCHS": ["x86_64"]}, + }], + [ "OS in 'linux freebsd openbsd solaris'", { + "target_conditions": [ + ["_type=='static_library'", { + "standalone_static_library": 1, # disable thin archive which needs binutils >= 2.19 + }], + ], + "conditions": [ + [ "target_arch=='ia32'", { + "cflags": [ "-m32" ], + "ldflags": [ "-m32" ], + }], + [ "target_arch=='x64'", { + "cflags": [ "-m64" ], + "ldflags": [ "-m64" ], + }], + ], + }], + ] + }, +} diff --git a/gyp_uv_link b/gyp_uv_link new file mode 100755 index 0000000..e174485 --- /dev/null +++ b/gyp_uv_link @@ -0,0 +1,97 @@ +#!/usr/bin/env python + +import glob +import platform +import os +import subprocess +import sys + +CC = os.environ.get('CC', 'cc') +script_dir = os.path.dirname(__file__) +root = os.path.normpath(script_dir) +output_dir = os.path.join(os.path.abspath(root), 'out') + +sys.path.insert(0, os.path.join(root, 'tools', 'gyp', 'pylib')) +try: + import gyp +except ImportError: + print('You need to install gyp in tools/gyp first, run:') + print(' svn co http://gyp.googlecode.com/svn/trunk tools/gyp'); + print('or') + print(' git clone https://chromium.googlesource.com/external/gyp.git ' + + 'tools/gyp') + 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 compiler_version(): + proc = subprocess.Popen(CC.split() + ['--version'], stdout=subprocess.PIPE) + is_clang = 'clang' in proc.communicate()[0].split('\n')[0] + proc = subprocess.Popen(CC.split() + ['-dumpversion'], stdout=subprocess.PIPE) + version = proc.communicate()[0].split('.') + version = map(int, version[:2]) + version = tuple(version) + return (version, is_clang) + + +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(root, 'uv_link_t.gyp')) + common_fn = os.path.join(root, 'common.gypi') + options_fn = os.path.join(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(root), 'uv_link_t.gyp')) + common_fn = os.path.join(os.path.abspath(root), 'common.gypi') + options_fn = os.path.join(os.path.abspath(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=' + 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 'ninja' not in args: + args.extend(['-Goutput_dir=' + output_dir]) + args.extend(['--generator-output', output_dir]) + (major, minor), is_clang = compiler_version() + args.append('-Dgcc_version=%d' % (10 * major + minor)) + args.append('-Dclang=%d' % int(is_clang)) + + 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()) + + gyp_args = list(args) + print gyp_args + run_gyp(gyp_args) diff --git a/include/uv_link.h b/include/uv_link.h new file mode 100644 index 0000000..2d2b744 --- /dev/null +++ b/include/uv_link.h @@ -0,0 +1,61 @@ +#ifndef INCLUDE_UV_LINK_H_ +#define INCLUDE_UV_LINK_H_ + +#include <uv.h> + +typedef struct uv_link_s uv_link_t; +typedef struct uv_link_source_s uv_link_source_t; + +typedef void (*uv_link_close_cb)(uv_link_t* link); +typedef void (*uv_link_alloc_cb)(uv_link_t* link, + size_t suggested_size, + uv_buf_t* buf); +typedef void (*uv_link_read_cb)(uv_link_t* link, + ssize_t nread, + const uv_buf_t* buf); +typedef void (*uv_link_write_cb)(uv_link_t* link, int status); +typedef void (*uv_link_shutdown_cb)(uv_link_t* link, int status); + +struct uv_link_s { + uv_link_t* parent; + uv_link_t* child; + + uv_link_alloc_cb alloc_cb; + uv_link_read_cb read_cb; + + /* Sort of virtual table */ + int (*read_start)(uv_link_t* link); + int (*read_stop)(uv_link_t* link); + + int (*write)(uv_link_t* link, + const uv_buf_t bufs[], + unsigned int nbufs, + uv_stream_t* send_handle, + uv_link_write_cb cb); + int (*try_write)(uv_link_t* link, + const uv_buf_t bufs[], + unsigned int nbufs); + + int (*shutdown)(uv_link_t* link, uv_link_shutdown_cb cb); +}; + +struct uv_link_source_s { + uv_link_t link; + + uv_stream_t* stream; +}; + +UV_EXTERN int uv_link_init(uv_loop_t* loop, uv_link_t* link); +UV_EXTERN int uv_link_close(uv_link_t* link, uv_link_close_cb close_cb); + +UV_EXTERN int uv_link_chain(uv_link_t* from, uv_link_t* to); + +/* Source */ + +/* NOTE: uses `stream->data` field */ +UV_EXTERN int uv_link_source_init(uv_loop_t* loop, + uv_link_source_t* source, + uv_stream_t* stream); +UV_EXTERN int uv_link_source_destroy(uv_link_source_t* source); + +#endif /* INCLUDE_UV_LINK_H_ */ diff --git a/src/common.h b/src/common.h new file mode 100644 index 0000000..8c5725d --- /dev/null +++ b/src/common.h @@ -0,0 +1,7 @@ +#ifndef SRC_COMMON_H_ +#define SRC_COMMON_H_ + +#define container_of(ptr, type, member) \ + ((type *) ((char *) (ptr) - offsetof(type, member))) + +#endif /* SRC_COMMON_H_ */ diff --git a/src/uv_link.c b/src/uv_link.c new file mode 100644 index 0000000..e4199cf --- /dev/null +++ b/src/uv_link.c @@ -0,0 +1,10 @@ +#include <string.h> + +#include "uv_link.h" + +#include "common.h" + +int uv_link_init(uv_loop_t* loop, uv_link_t* link) { + memset(link, 0, sizeof(*link)); + return 0; +} diff --git a/src/uv_link_source.c b/src/uv_link_source.c new file mode 100644 index 0000000..181a060 --- /dev/null +++ b/src/uv_link_source.c @@ -0,0 +1,160 @@ +#include <stdlib.h> + +#include "uv_link.h" + +#include "common.h" + +typedef struct uv_link_source_write_s uv_link_source_write_t; +typedef struct uv_link_source_shutdown_s uv_link_source_shutdown_t; + +struct uv_link_source_write_s { + uv_write_t req; + uv_link_t* link; + uv_link_write_cb write_cb; +}; + +struct uv_link_source_shutdown_s { + uv_shutdown_t req; + uv_link_t* link; + uv_link_shutdown_cb shutdown_cb; +}; + + +static void uv_link_source_wrap_alloc_cb(uv_handle_t* handle, + size_t suggested_size, + uv_buf_t* buf) { + uv_link_source_t* source; + + source = handle->data; + + source->link.alloc_cb(&source->link, suggested_size, buf); +} + + +static void uv_link_source_wrap_read_cb(uv_stream_t* stream, + ssize_t nread, + const uv_buf_t* buf) { + uv_link_source_t* source; + + source = stream->data; + + source->link.read_cb(&source->link, nread, buf); +} + + +static int uv_link_source_read_start(uv_link_t* link) { + uv_link_source_t* source; + + source = container_of(link, uv_link_source_t, link); + + return uv_read_start(source->stream, + uv_link_source_wrap_alloc_cb, + uv_link_source_wrap_read_cb); +} + + +static int uv_link_source_read_stop(uv_link_t* link) { + uv_link_source_t* source; + + source = container_of(link, uv_link_source_t, link); + + return uv_read_stop(source->stream); +} + + +static void uv_link_source_wrap_write_cb(uv_write_t* req, int status) { + uv_link_source_write_t* lreq; + + lreq = container_of(req, uv_link_source_write_t, req); + lreq->write_cb(lreq->link, status); + free(lreq); +} + + +static int uv_link_source_write(uv_link_t* link, + const uv_buf_t bufs[], + unsigned int nbufs, + uv_stream_t* send_handle, + uv_link_write_cb cb) { + uv_link_source_t* source; + uv_link_source_write_t* req; + + source = container_of(link, uv_link_source_t, link); + req = malloc(sizeof(*req)); + if (req == NULL) + return UV_ENOMEM; + + req->link = link; + req->write_cb = cb; + + return uv_write2(&req->req, source->stream, bufs, nbufs, send_handle, + uv_link_source_wrap_write_cb); +} + + +static int uv_link_source_try_write(uv_link_t* link, + const uv_buf_t bufs[], + unsigned int nbufs) { + uv_link_source_t* source; + + source = container_of(link, uv_link_source_t, link); + + return uv_try_write(source->stream, bufs, nbufs); +} + + +static void uv_link_source_wrap_shutdown_cb(uv_shutdown_t* req, int status) { + uv_link_source_shutdown_t* lreq; + + lreq = container_of(req, uv_link_source_shutdown_t, req); + lreq->shutdown_cb(lreq->link, status); + free(lreq); +} + + +static int uv_link_shutdown(uv_link_t* link, uv_link_shutdown_cb cb) { + uv_link_source_t* source; + uv_link_source_shutdown_t* req; + + source = container_of(link, uv_link_source_t, link); + + req = malloc(sizeof(*req)); + if (req == NULL) + return UV_ENOMEM; + + req->link = link; + req->shutdown_cb = cb; + + return uv_shutdown(&req->req, source->stream, + uv_link_source_wrap_shutdown_cb); +} + + +int uv_link_source_init(uv_loop_t* loop, + uv_link_source_t* source, + uv_stream_t* stream) { + int err; + uv_link_t* l; + + err = uv_link_init(loop, &source->link); + if (err != 0) + return err; + + source->stream = stream; + source->stream->data = source; + + l = &source->link; + l->read_start = uv_link_source_read_start; + l->read_stop = uv_link_source_read_stop; + l->write = uv_link_source_write; + l->try_write = uv_link_source_try_write; + l->shutdown = uv_link_shutdown; + + return 0; +} + + +int uv_link_source_destroy(uv_link_source_t* source) { + source->stream = NULL; + return 0; +} diff --git a/test/deps/.gitkeep b/test/deps/.gitkeep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/deps/.gitkeep diff --git a/uv_link_t.gyp b/uv_link_t.gyp new file mode 100644 index 0000000..6b00b43 --- /dev/null +++ b/uv_link_t.gyp @@ -0,0 +1,22 @@ +{ + "targets": [{ + "target_name": "uv_link_t", + "type": "<(library)", + + "direct_dependent_settings": { + "include_dirs": [ "include" ], + }, + "include_dirs": [ + # libuv + "<(uv_dir)/include", + + "include", + "src", + ], + + "sources": [ + "src/uv_link.c", + "src/uv_link_source.c", + ], + }], +} |