Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

tcp: initial

  • Loading branch information...
commit 29ca6ac7c8dd7341bdb499dd05e6d5b401e3cce4 1 parent c9f034d
Fedor Indutny authored November 04, 2012
2  candor.io.gyp
@@ -2,6 +2,7 @@
2 2
   'variables': {
3 3
     'library_files': [
4 4
       'lib/fs.can',
  5
+      'lib/tcp.can',
5 6
       'lib/module.can',
6 7
       'lib/can.can',
7 8
     ]
@@ -31,6 +32,7 @@
31 32
       'src/bindings.cc',
32 33
       'src/bindings/fs.cc',
33 34
       'src/bindings/buffer.cc',
  35
+      'src/bindings/tcp.cc',
34 36
 
35 37
       '<@(library_files)',
36 38
       '<(SHARED_INTERMEDIATE_DIR)/can_natives.h',
2  deps/candor
... ...
@@ -1 +1 @@
1  
-Subproject commit 32e4a1e2b4534f30d1592cd30866247b3340f723
  1
+Subproject commit e245d592fe52cd3a1372f031f5410452a2c1050c
30  lib/tcp.can
... ...
@@ -0,0 +1,30 @@
  1
+// TCP Module
  2
+
  3
+tcp = global._bindings.tcp
  4
+
  5
+exports = {}
  6
+
  7
+Server = exports.Server = {}
  8
+Server.init = (self, listener) {
  9
+  global.log(self, listener)
  10
+  self._handle = tcp.new()
  11
+  self._listener = listener
  12
+
  13
+  return self
  14
+}
  15
+
  16
+Server.listen = (self, port, host) {
  17
+  tcp.bind(self._handle, port, host || "0.0.0.0")
  18
+  tcp.listen(self._handle, 10, (socket) {
  19
+    self._listener(socket)
  20
+  })
  21
+
  22
+  return self
  23
+}
  24
+
  25
+exports.createServer = (listener) {
  26
+  s = clone Server
  27
+  return s:init(listener)
  28
+}
  29
+
  30
+return exports
2  src/bindings.h
@@ -3,6 +3,7 @@
3 3
 
4 4
 #include "bindings/fs.h"
5 5
 #include "bindings/buffer.h"
  6
+#include "bindings/tcp.h"
6 7
 #include <candor.h>
7 8
 
8 9
 namespace can {
@@ -15,6 +16,7 @@ struct can_binding_s {
15 16
 static const struct can_binding_s can_bindings[] = {
16 17
   { "fs", FS::Init },
17 18
   { "buffer", Buffer::Init },
  19
+  { "tcp", TCP::Init },
18 20
   { NULL, NULL }
19 21
 };
20 22
 
95  src/bindings/tcp.cc
... ...
@@ -0,0 +1,95 @@
  1
+#include "tcp.h"
  2
+#include <string.h> //memcpy
  3
+
  4
+namespace can {
  5
+
  6
+using namespace candor;
  7
+
  8
+const int TCP::magic = 0;
  9
+
  10
+
  11
+bool TCP::HasInstance(Value* value) {
  12
+  return CWrapper::HasClass(value, &magic);
  13
+}
  14
+
  15
+
  16
+Value* TCP::New(uint32_t argc, Value** argv) {
  17
+  TCP* t = new TCP();
  18
+
  19
+  int r = uv_tcp_init(uv_default_loop(), &t->handle_);
  20
+  if (r) return Nil::New();
  21
+
  22
+  t->handle_.data = t;
  23
+
  24
+  return t->Wrap();
  25
+}
  26
+
  27
+
  28
+Value* TCP::Bind(uint32_t argc, Value** argv) {
  29
+  if (argc < 3 || !TCP::HasInstance(argv[0]) ||
  30
+      !argv[1]->Is<Number>() || !argv[2]->Is<String>()) {
  31
+    return Nil::New();
  32
+  }
  33
+
  34
+  int port = argv[1]->As<Number>()->IntegralValue();
  35
+  TCP* t = CWrapper::Unwrap<TCP>(argv[0]);
  36
+  String* ip = argv[2]->As<String>();
  37
+
  38
+  char ip_address[64];
  39
+  size_t len = ip->Length();
  40
+  if (len > sizeof(ip_address) - 1) len = sizeof(ip_address) - 1;
  41
+
  42
+  memcpy(ip_address, ip->Value(), len);
  43
+  ip_address[len] = 0;
  44
+  struct sockaddr_in address = uv_ip4_addr(ip_address, port);
  45
+  int r = uv_tcp_bind(&t->handle_, address);
  46
+
  47
+  return Number::NewIntegral(r);
  48
+}
  49
+
  50
+
  51
+void TCP::OnConnection(uv_stream_t* server, int status) {
  52
+  Value* argv[2] = { Nil::New(), Nil::New() };
  53
+  if (status) {
  54
+    argv[0] = Number::NewIntegral(status);
  55
+  } else {
  56
+    Value* res = TCP::New(NULL, NULL);
  57
+    TCP* t = CWrapper::Unwrap<TCP>(res);
  58
+
  59
+    int r = uv_accept(server, reinterpret_cast<uv_stream_t*>(&t->handle_));
  60
+    if (r) {
  61
+      argv[0] = Number::NewIntegral(r);
  62
+    } else {
  63
+      argv[1] = res;
  64
+    }
  65
+  }
  66
+
  67
+  TCP* s = reinterpret_cast<TCP*>(server->data);
  68
+  if (!s->connection_cb_.IsEmpty()) s->connection_cb_->Call(2, argv);
  69
+}
  70
+
  71
+
  72
+Value* TCP::Listen(uint32_t argc, Value** argv) {
  73
+  if (argc < 3 || !TCP::HasInstance(argv[0]) ||
  74
+      !argv[1]->Is<Number>() || !argv[2]->Is<Function>()) {
  75
+    return Nil::New();
  76
+  }
  77
+
  78
+  TCP* t = CWrapper::Unwrap<TCP>(argv[0]);
  79
+  int backlog = argv[1]->As<Number>()->IntegralValue();
  80
+  int r = uv_listen(reinterpret_cast<uv_stream_t*>(&t->handle_),
  81
+                    backlog,
  82
+                    OnConnection);
  83
+  t->connection_cb_.Wrap(argv[2]->As<Function>());
  84
+
  85
+  return Number::NewIntegral(r);
  86
+}
  87
+
  88
+
  89
+void TCP::Init(Object* target) {
  90
+  target->Set("new", Function::New(TCP::New));
  91
+  target->Set("bind", Function::New(TCP::Bind));
  92
+  target->Set("listen", Function::New(TCP::Listen));
  93
+}
  94
+
  95
+} // namespace can
37  src/bindings/tcp.h
... ...
@@ -0,0 +1,37 @@
  1
+#ifndef _SRC_BINDINGS_NET_H_
  2
+#define _SRC_BINDINGS_NET_H_
  3
+
  4
+#include <candor.h>
  5
+#include <uv.h>
  6
+#include <sys/types.h> // size_t
  7
+#include <stdlib.h> // NULL
  8
+
  9
+namespace can {
  10
+
  11
+class TCP : public candor::CWrapper {
  12
+ public:
  13
+  TCP() : candor::CWrapper(&magic) {
  14
+  }
  15
+
  16
+  static void Init(candor::Object* target);
  17
+
  18
+  static bool HasInstance(candor::Value* value);
  19
+
  20
+  // Magic word
  21
+  static const int magic;
  22
+
  23
+ protected:
  24
+  static void OnConnection(uv_stream_t* server, int status);
  25
+
  26
+  static candor::Value* New(uint32_t argc, candor::Value** argv);
  27
+  static candor::Value* Bind(uint32_t argc, candor::Value** argv);
  28
+  static candor::Value* Listen(uint32_t argc, candor::Value** argv);
  29
+
  30
+  uv_tcp_t handle_;
  31
+
  32
+  candor::Handle<candor::Function> connection_cb_;
  33
+};
  34
+
  35
+} // namespace can
  36
+
  37
+#endif // _SRC_BINDINGS_NET_H_
3  src/runtime.cc
... ...
@@ -1,5 +1,6 @@
1 1
 #include "runtime.h"
2 2
 #include "bindings/buffer.h" // Buffer
  3
+#include "bindings/tcp.h" // TCP
3 4
 
4 5
 #include <stdlib.h> // NULL
5 6
 #include <stdio.h> // fprintf
@@ -21,6 +22,8 @@ void PrettyPrint(Value* value) {
21 22
    case Value::kCData:
22 23
     if (Buffer::HasInstance(value)) {
23 24
       fprintf(stdout, "\033[1;31m" "buffer" "\033[0m");
  25
+    } else if (TCP::HasInstance(value)) {
  26
+      fprintf(stdout, "\033[1;31m" "tcp" "\033[0m");
24 27
     } else {
25 28
       fprintf(stdout, "\033[1;31m" "cdata" "\033[0m");
26 29
     }

0 notes on commit 29ca6ac

Please sign in to comment.
Something went wrong with that request. Please try again.