Skip to content

Commit

Permalink
Implement full tcp echo server
Browse files Browse the repository at this point in the history
  • Loading branch information
creationix committed Mar 8, 2012
1 parent 828cd02 commit c3160d4
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 16 deletions.
6 changes: 3 additions & 3 deletions src/helpers.h
Expand Up @@ -9,9 +9,9 @@
return JS_FALSE; \
}

#define LUV_REF(cx, obj) \
#define LUV_REF(context, object) \
(luv_ref_t*)malloc(sizeof(luv_ref_t)); \
ref->cx = cx; \
ref->obj = obj;
ref->cx = context; \
ref->obj = object;

#endif
1 change: 1 addition & 0 deletions src/luv_handle.c
Expand Up @@ -21,6 +21,7 @@ void luv_on_close(uv_handle_t* handle) {
/* TODO: report properly */
printf("Error in onClose callback\n");
}
free(handle);
}

static JSBool luv_close(JSContext *cx, unsigned argc, jsval *vp) {
Expand Down
76 changes: 66 additions & 10 deletions src/luv_stream.c
@@ -1,4 +1,5 @@
#include "uv.h"
#include "assert.h"
#include "luv_stream.h"

static JSClass Stream_class = {
Expand All @@ -15,11 +16,6 @@ static JSBool Stream_constructor(JSContext *cx, unsigned argc, jsval *vp) {
}


static JSBool luv_write(JSContext *cx, unsigned argc, jsval *vp) {
printf("TODO: Implement luv_write\n");
return JS_TRUE;
}

static void luv_on_connection(uv_stream_t* server, int status) {
luv_ref_t* ref;
ref = (luv_ref_t*)server->data;
Expand Down Expand Up @@ -74,7 +70,6 @@ static uv_buf_t luv_on_alloc(uv_handle_t* handle, size_t suggested_size) {
}

static void luv_on_read(uv_stream_t* stream, ssize_t nread, uv_buf_t buf) {
printf("luv_on_read\n");
luv_ref_t* ref;
ref = (luv_ref_t*)stream->data;

Expand All @@ -89,7 +84,10 @@ static void luv_on_read(uv_stream_t* stream, ssize_t nread, uv_buf_t buf) {
} else {
uv_err_t err = uv_last_error(uv_default_loop());
if (err.code == UV_EOF) {
printf("EOF\n");
if (!luv_call_callback(ref->cx, ref->obj, "onEnd", 0, NULL)) {
/* TODO: report properly */
printf("Error in onError callback\n");
}
} else {
/*
TODO: Implement close
Expand All @@ -111,14 +109,71 @@ static JSBool luv_read_start(JSContext* cx, unsigned argc, jsval* vp) {
uv_stream_t* stream;
stream = (uv_stream_t*)JS_GetPrivate(this);

UV_CALL(uv_read_start, stream, luv_on_alloc, luv_on_read);

JS_SET_RVAL(cx, vp, JSVAL_VOID);
return JS_TRUE;
}

static JSBool luv_read_stop(JSContext* cx, unsigned argc, jsval* vp) {
JSObject* this = JS_THIS_OBJECT(cx, vp);
uv_stream_t* stream;
stream = (uv_stream_t*)JS_GetPrivate(this);

UV_CALL(uv_read_stop, stream);

JS_SET_RVAL(cx, vp, JSVAL_VOID);
return JS_TRUE;
}

static void luv_on_write(uv_write_t* req, int status) {
luv_ref_t* ref;

/* Get the context, instance, and handle */
ref = (luv_ref_t*)req->handle->data;
JSContext* cx = ref->cx;
JSObject* this = ref->obj;

/* Get the callback */
ref = (luv_ref_t*)req->data;
assert(ref->cx == cx);
JSObject* callback = ref->obj;
free(ref);

if (JS_ObjectIsFunction(cx, callback)) {
jsval result;
if (!JS_CallFunctionValue(cx, this, OBJECT_TO_JSVAL(callback), 0, NULL, &result)) {
/* TODO: report properly */
printf("Error in onWrite callback\n");
}
}

/* TODO: free the chunk */
/* JS_free(cx, chunk); */
}

static JSBool luv_write(JSContext* cx, unsigned argc, jsval* vp) {
JSObject* this = JS_THIS_OBJECT(cx, vp);
uv_stream_t* stream;
stream = (uv_stream_t*)JS_GetPrivate(this);

JSString* str;
JSObject* callback;
if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "o", &callback)) {
if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "So", &str, &callback)) {
return JS_FALSE;
}
/* Put the string in a new uv_buf_t */
uv_buf_t* buf = (uv_buf_t*)malloc(sizeof(uv_buf_t));
size_t len = JS_GetStringEncodingLength(cx, str);
buf->base = (char*)malloc(len);
buf->len = JS_EncodeStringToBuffer(str, buf->base, len);

if (!luv_store_callback(cx, this, "onData", callback)) return JS_FALSE;
/* Store a reference to the callback in the write request */
luv_ref_t* ref = LUV_REF(cx, callback);
uv_write_t* req = (uv_write_t*)malloc(sizeof(uv_write_t));
req->data = ref;

UV_CALL(uv_read_start, stream, luv_on_alloc, luv_on_read);
UV_CALL(uv_write, req, stream, buf, 1, luv_on_write);

JS_SET_RVAL(cx, vp, JSVAL_VOID);
return JS_TRUE;
Expand All @@ -129,6 +184,7 @@ static JSFunctionSpec Stream_methods[] = {
JS_FS("listen", luv_listen, 0, JSPROP_ENUMERATE),
JS_FS("accept", luv_accept, 0, JSPROP_ENUMERATE),
JS_FS("readStart", luv_read_start, 0, JSPROP_ENUMERATE),
JS_FS("readStop", luv_read_stop, 0, JSPROP_ENUMERATE),
JS_FS_END
};

Expand Down
14 changes: 11 additions & 3 deletions test-tcp.js
Expand Up @@ -7,9 +7,17 @@ server.bind("0.0.0.0", 1337);
server.listen(128, function () {
var client = new Tcp();
server.accept(client);
client.readStart(function (chunk) {
p("onRead", chunk);
});
client.readStart();
client.onData = function (chunk) {
p("onData", chunk);
client.write(chunk, function () {
p("onWrite", chunk);
});
};
client.onEnd = function () {
p("onEnd");
client.close();
};
p("Connection!", client);
});

Expand Down

0 comments on commit c3160d4

Please sign in to comment.