diff --git a/node_tcp.cc b/node_tcp.cc index 4142bba3ab..1b253ae96f 100644 --- a/node_tcp.cc +++ b/node_tcp.cc @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -31,6 +32,8 @@ public: void Disconnect(); void OnOpen(); + void OnRead(const void *buf, size_t count); + void OnClose(); private: oi_socket socket; @@ -39,14 +42,27 @@ private: }; -static void on_connect - ( oi_socket *socket - ) +static void +on_connect (oi_socket *socket) { TCPClient *client = static_cast (socket->data); client->OnOpen(); } +static void +on_close (oi_socket *socket) +{ + TCPClient *client = static_cast (socket->data); + client->OnClose(); +} + +static void +on_read (oi_socket *socket, const void *buf, size_t count) +{ + TCPClient *client = static_cast (socket->data); + client->OnRead(buf, count); +} + static struct addrinfo tcp_hints = /* ai_flags */ { AI_PASSIVE /* ai_family */ , AF_UNSPEC @@ -120,11 +136,11 @@ TCPClient::TCPClient(Handle _js_client) { oi_socket_init(&socket, 30.0); // TODO adjustable timeout socket.on_connect = on_connect; - socket.on_read = NULL; + socket.on_read = on_read; socket.on_drain = NULL; socket.on_error = NULL; - socket.on_close = NULL; - socket.on_timeout = NULL; + socket.on_close = on_close; + socket.on_timeout = on_close; socket.data = this; HandleScope scope; @@ -193,10 +209,12 @@ TCPClient::Disconnect() oi_socket_close(&socket); } -void TCPClient::OnOpen() +void +TCPClient::OnOpen() { HandleScope scope; + assert(READY_STATE_CONNECTING == js_client->Get(readyState_str)->IntegerValue()); js_client->Set(readyState_str, readyState_OPEN); Handle onopen_value = js_client->Get( String::NewSymbol("onopen") ); @@ -212,6 +230,56 @@ void TCPClient::OnOpen() node_fatal_exception(try_catch); } +void +TCPClient::OnRead(const void *buf, size_t count) +{ + HandleScope scope; + + assert(READY_STATE_OPEN == js_client->Get(readyState_str)->IntegerValue()); + + Handle onread_value = js_client->Get( String::NewSymbol("onread") ); + if (!onread_value->IsFunction()) return; + Handle onread = Handle::Cast(onread_value); + + const int argc = 1; + Handle argv[argc]; + + if(count) { + Handle chunk = String::New((const char*)buf, count); // TODO binary data? + argv[0] = chunk; + } else { + // TODO eof? delete write method? + argv[0] = Null(); + } + + TryCatch try_catch; + + Handle r = onread->Call(js_client, argc, argv); + + if(try_catch.HasCaught()) + node_fatal_exception(try_catch); +} + +void +TCPClient::OnClose() +{ + HandleScope scope; + + assert(READY_STATE_OPEN == js_client->Get(readyState_str)->IntegerValue()); + js_client->Set(readyState_str, readyState_CLOSED); + + Handle onclose_value = js_client->Get( String::NewSymbol("onclose") ); + if (!onclose_value->IsFunction()) return; + Handle onclose = Handle::Cast(onclose_value); + + TryCatch try_catch; + + Handle r = onclose->Call(js_client, 0, NULL); + + if(try_catch.HasCaught()) + node_fatal_exception(try_catch); +} + void Init_tcp (Handle target) {