about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--README.md28
-rw-r--r--common.gypi82
-rwxr-xr-xgyp_uv_link97
-rw-r--r--include/uv_link.h61
-rw-r--r--src/common.h7
-rw-r--r--src/uv_link.c10
-rw-r--r--src/uv_link_source.c160
-rw-r--r--test/deps/.gitkeep0
-rw-r--r--uv_link_t.gyp22
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",
+    ],
+  }],
+}