Permalink
Browse files

tcp: initial

  • Loading branch information...
1 parent c9f034d commit 29ca6ac7c8dd7341bdb499dd05e6d5b401e3cce4 @indutny committed Nov 4, 2012
Showing with 170 additions and 1 deletion.
  1. +2 −0 candor.io.gyp
  2. +1 −1 deps/candor
  3. +30 −0 lib/tcp.can
  4. +2 −0 src/bindings.h
  5. +95 −0 src/bindings/tcp.cc
  6. +37 −0 src/bindings/tcp.h
  7. +3 −0 src/runtime.cc
View
@@ -2,6 +2,7 @@
'variables': {
'library_files': [
'lib/fs.can',
+ 'lib/tcp.can',
'lib/module.can',
'lib/can.can',
]
@@ -31,6 +32,7 @@
'src/bindings.cc',
'src/bindings/fs.cc',
'src/bindings/buffer.cc',
+ 'src/bindings/tcp.cc',
'<@(library_files)',
'<(SHARED_INTERMEDIATE_DIR)/can_natives.h',
View
@@ -0,0 +1,30 @@
+// TCP Module
+
+tcp = global._bindings.tcp
+
+exports = {}
+
+Server = exports.Server = {}
+Server.init = (self, listener) {
+ global.log(self, listener)
+ self._handle = tcp.new()
+ self._listener = listener
+
+ return self
+}
+
+Server.listen = (self, port, host) {
+ tcp.bind(self._handle, port, host || "0.0.0.0")
+ tcp.listen(self._handle, 10, (socket) {
+ self._listener(socket)
+ })
+
+ return self
+}
+
+exports.createServer = (listener) {
+ s = clone Server
+ return s:init(listener)
+}
+
+return exports
View
@@ -3,6 +3,7 @@
#include "bindings/fs.h"
#include "bindings/buffer.h"
+#include "bindings/tcp.h"
#include <candor.h>
namespace can {
@@ -15,6 +16,7 @@ struct can_binding_s {
static const struct can_binding_s can_bindings[] = {
{ "fs", FS::Init },
{ "buffer", Buffer::Init },
+ { "tcp", TCP::Init },
{ NULL, NULL }
};
View
@@ -0,0 +1,95 @@
+#include "tcp.h"
+#include <string.h> //memcpy
+
+namespace can {
+
+using namespace candor;
+
+const int TCP::magic = 0;
+
+
+bool TCP::HasInstance(Value* value) {
+ return CWrapper::HasClass(value, &magic);
+}
+
+
+Value* TCP::New(uint32_t argc, Value** argv) {
+ TCP* t = new TCP();
+
+ int r = uv_tcp_init(uv_default_loop(), &t->handle_);
+ if (r) return Nil::New();
+
+ t->handle_.data = t;
+
+ return t->Wrap();
+}
+
+
+Value* TCP::Bind(uint32_t argc, Value** argv) {
+ if (argc < 3 || !TCP::HasInstance(argv[0]) ||
+ !argv[1]->Is<Number>() || !argv[2]->Is<String>()) {
+ return Nil::New();
+ }
+
+ int port = argv[1]->As<Number>()->IntegralValue();
+ TCP* t = CWrapper::Unwrap<TCP>(argv[0]);
+ String* ip = argv[2]->As<String>();
+
+ char ip_address[64];
+ size_t len = ip->Length();
+ if (len > sizeof(ip_address) - 1) len = sizeof(ip_address) - 1;
+
+ memcpy(ip_address, ip->Value(), len);
+ ip_address[len] = 0;
+ struct sockaddr_in address = uv_ip4_addr(ip_address, port);
+ int r = uv_tcp_bind(&t->handle_, address);
+
+ return Number::NewIntegral(r);
+}
+
+
+void TCP::OnConnection(uv_stream_t* server, int status) {
+ Value* argv[2] = { Nil::New(), Nil::New() };
+ if (status) {
+ argv[0] = Number::NewIntegral(status);
+ } else {
+ Value* res = TCP::New(NULL, NULL);
+ TCP* t = CWrapper::Unwrap<TCP>(res);
+
+ int r = uv_accept(server, reinterpret_cast<uv_stream_t*>(&t->handle_));
+ if (r) {
+ argv[0] = Number::NewIntegral(r);
+ } else {
+ argv[1] = res;
+ }
+ }
+
+ TCP* s = reinterpret_cast<TCP*>(server->data);
+ if (!s->connection_cb_.IsEmpty()) s->connection_cb_->Call(2, argv);
+}
+
+
+Value* TCP::Listen(uint32_t argc, Value** argv) {
+ if (argc < 3 || !TCP::HasInstance(argv[0]) ||
+ !argv[1]->Is<Number>() || !argv[2]->Is<Function>()) {
+ return Nil::New();
+ }
+
+ TCP* t = CWrapper::Unwrap<TCP>(argv[0]);
+ int backlog = argv[1]->As<Number>()->IntegralValue();
+ int r = uv_listen(reinterpret_cast<uv_stream_t*>(&t->handle_),
+ backlog,
+ OnConnection);
+ t->connection_cb_.Wrap(argv[2]->As<Function>());
+
+ return Number::NewIntegral(r);
+}
+
+
+void TCP::Init(Object* target) {
+ target->Set("new", Function::New(TCP::New));
+ target->Set("bind", Function::New(TCP::Bind));
+ target->Set("listen", Function::New(TCP::Listen));
+}
+
+} // namespace can
View
@@ -0,0 +1,37 @@
+#ifndef _SRC_BINDINGS_NET_H_
+#define _SRC_BINDINGS_NET_H_
+
+#include <candor.h>
+#include <uv.h>
+#include <sys/types.h> // size_t
+#include <stdlib.h> // NULL
+
+namespace can {
+
+class TCP : public candor::CWrapper {
+ public:
+ TCP() : candor::CWrapper(&magic) {
+ }
+
+ static void Init(candor::Object* target);
+
+ static bool HasInstance(candor::Value* value);
+
+ // Magic word
+ static const int magic;
+
+ protected:
+ static void OnConnection(uv_stream_t* server, int status);
+
+ static candor::Value* New(uint32_t argc, candor::Value** argv);
+ static candor::Value* Bind(uint32_t argc, candor::Value** argv);
+ static candor::Value* Listen(uint32_t argc, candor::Value** argv);
+
+ uv_tcp_t handle_;
+
+ candor::Handle<candor::Function> connection_cb_;
+};
+
+} // namespace can
+
+#endif // _SRC_BINDINGS_NET_H_
View
@@ -1,5 +1,6 @@
#include "runtime.h"
#include "bindings/buffer.h" // Buffer
+#include "bindings/tcp.h" // TCP
#include <stdlib.h> // NULL
#include <stdio.h> // fprintf
@@ -21,6 +22,8 @@ void PrettyPrint(Value* value) {
case Value::kCData:
if (Buffer::HasInstance(value)) {
fprintf(stdout, "\033[1;31m" "buffer" "\033[0m");
+ } else if (TCP::HasInstance(value)) {
+ fprintf(stdout, "\033[1;31m" "tcp" "\033[0m");
} else {
fprintf(stdout, "\033[1;31m" "cdata" "\033[0m");
}

0 comments on commit 29ca6ac

Please sign in to comment.