forked from nodejs/node
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
begin work on the TCP.connect interface
- Loading branch information
Showing
7 changed files
with
268 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,16 @@ | ||
WHEREAS, The usage of threads has complicated computer programming; and | ||
|
||
git submodule init | ||
git submodule update | ||
make | ||
WHEREAS, V8 javascript comes free of I/O and threads; and | ||
|
||
WHEREAS, Most operating systems do not provide asynchonous file system | ||
access. | ||
|
||
Now, therefore: | ||
|
||
This set server and client libraries were made to build simple but fast | ||
servers. They are provided free of charge under a permissive simple license. | ||
|
||
Submitted by | ||
Ryah Dahl, Programmer | ||
Tim Becker, Programmer | ||
March 1, 2009 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,26 @@ | ||
function encode(data) { | ||
var chunk = data.toString(); | ||
return chunk.length.toString(16) + "\r\n" + chunk + "\r\n"; | ||
} | ||
function encode(data) { | ||
var chunk = data.toString(); | ||
return chunk.length.toString(16) + "\r\n" + chunk + "\r\n"; | ||
} | ||
|
||
function Process(request) { | ||
|
||
log( "path: " + request.path ); | ||
log( "query string: " + request.query_string ); | ||
|
||
function Process(request) { | ||
// onBody sends null on the last chunk. | ||
request.onBody = function (chunk) { | ||
if(chunk) { | ||
this.respond(encode(chunk)); | ||
} else { | ||
this.respond(encode("\n")); | ||
this.respond("0\r\n\r\n"); | ||
this.respond(null); // signals end-of-request | ||
} | ||
// onBody sends null on the last chunk. | ||
request.onBody = function (chunk) { | ||
if(chunk) { | ||
this.respond(encode(chunk)); | ||
} else { | ||
this.respond(encode("\n")); | ||
this.respond("0\r\n\r\n"); | ||
this.respond(null); // signals end-of-request | ||
} | ||
request.respond("HTTP/1.0 200 OK\r\n"); | ||
request.respond("Content-Type: text-plain\r\n"); | ||
request.respond("Transfer-Encoding: chunked\r\n"); | ||
request.respond("\r\n"); | ||
} | ||
request.respond("HTTP/1.0 200 OK\r\n"); | ||
request.respond("Content-Type: text/plain\r\n"); | ||
request.respond("Transfer-Encoding: chunked\r\n"); | ||
request.respond("\r\n"); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
#include "tcp.h" | ||
|
||
#include <oi_socket.h> | ||
#include <oi_async.h> | ||
|
||
#include <sys/types.h> | ||
#include <sys/socket.h> | ||
#include <netdb.h> | ||
|
||
|
||
|
||
/* | ||
Target API | ||
TCP.connect({ | ||
host: "google.com", | ||
port: 80, | ||
connect: function () { | ||
this.write("GET /search?q=hello HTTP/1.0\r\n\r\n"); | ||
}, | ||
read: function (data) { | ||
request.respond("<table> <td>" + data + "</td> </table>"); | ||
}, | ||
drain: function () { | ||
}, | ||
error: function () { | ||
} | ||
}); | ||
*/ | ||
|
||
static oi_async thread_pool; | ||
|
||
static struct addrinfo tcp_hints = | ||
/* ai_flags */ { AI_PASSIVE | ||
/* ai_family */ , AF_UNSPEC | ||
/* ai_socktype */ , SOCK_STREAM | ||
/* ai_protocol */ , 0 | ||
/* ai_addrlen */ , 0 | ||
/* ai_addr */ , 0 | ||
/* ai_canonname */ , 0 | ||
/* ai_next */ , 0 | ||
}; | ||
|
||
static struct ev_loop *loop; | ||
|
||
class TCPClient { | ||
public: | ||
oi_task resolve_task; | ||
oi_socket socket; | ||
struct addrinfo *address; | ||
Persistent<Object> options; | ||
}; | ||
|
||
static void on_connect | ||
( oi_socket *socket | ||
) | ||
{ | ||
TCPClient *client = static_cast<TCPClient*> (socket->data); | ||
|
||
HandleScope scope; | ||
|
||
Handle<Value> connect_value = client->options->Get( String::NewSymbol("connect") ); | ||
if (!connect_value->IsFunction()) | ||
return; // error! | ||
Handle<Function> connect_cb = Handle<Function>::Cast(connect_value); | ||
|
||
TryCatch try_catch; | ||
Handle<Value> r = connect_cb->Call(client->options, 0, NULL); | ||
if (r.IsEmpty()) { | ||
String::Utf8Value error(try_catch.Exception()); | ||
printf("connect error: %s\n", *error); | ||
} | ||
} | ||
|
||
static void resolve_done | ||
( oi_task *resolve_task | ||
, int result | ||
) | ||
{ | ||
TCPClient *client = static_cast<TCPClient*> (resolve_task->data); | ||
|
||
if(result != 0) { | ||
printf("error. TODO make call options error callback\n"); | ||
client->options.Dispose(); | ||
delete client; | ||
return; | ||
} | ||
|
||
// Got the address succesfully. Let's connect now. | ||
|
||
oi_socket_init(&client->socket, 30.0); // TODO adjustable timeout | ||
|
||
client->socket.on_connect = on_connect; | ||
client->socket.on_read = NULL; | ||
client->socket.on_drain = NULL; | ||
client->socket.on_error = NULL; | ||
client->socket.on_close = NULL; | ||
client->socket.on_timeout = NULL; | ||
client->socket.data = client; | ||
|
||
oi_socket_connect (&client->socket, client->address); | ||
oi_socket_attach (&client->socket, loop); | ||
|
||
|
||
freeaddrinfo(client->address); | ||
client->address = NULL; | ||
} | ||
|
||
static Handle<Value> Connect | ||
( const Arguments& args | ||
) | ||
{ | ||
if (args.Length() < 1) | ||
return Undefined(); | ||
|
||
HandleScope scope; | ||
|
||
Handle<Value> arg = args[0]; | ||
Handle<Object> options = arg->ToObject(); | ||
|
||
/* Make sure the user has provided at least host and port */ | ||
|
||
Handle<Value> host_value = options->Get( String::NewSymbol("host") ); | ||
|
||
if(host_value->IsUndefined()) | ||
return False(); | ||
|
||
Handle<Value> port_value = options->Get( String::NewSymbol("port") ); | ||
|
||
if(port_value->IsUndefined()) | ||
return False(); | ||
|
||
Handle<String> host = host_value->ToString(); | ||
Handle<String> port = port_value->ToString(); | ||
|
||
char host_s[host->Length()+1]; // + 1 for \0 | ||
char port_s[port->Length()+1]; | ||
|
||
host->WriteAscii(host_s, 0, host->Length()); | ||
port->WriteAscii(port_s, 0, port->Length()); | ||
|
||
printf("resolving host: %s, port: %s\n", host_s, port_s); | ||
|
||
TCPClient *client = new TCPClient; | ||
|
||
oi_task_init_getaddrinfo ( &client->resolve_task | ||
, resolve_done | ||
, host_s | ||
, port_s | ||
, &tcp_hints | ||
, &client->address | ||
); | ||
client->options = Persistent<Object>::New(options); | ||
|
||
oi_async_submit (&thread_pool, &client->resolve_task); | ||
} | ||
|
||
Handle<Object> tcp_initialize | ||
( struct ev_loop *_loop | ||
) | ||
{ | ||
loop = _loop; | ||
|
||
oi_async_init(&thread_pool); | ||
oi_async_attach(loop, &thread_pool); | ||
|
||
HandleScope scope; | ||
|
||
Local<Object> t = Object::New(); | ||
|
||
t->Set(String::New("connect"), FunctionTemplate::New(Connect)->GetFunction()); | ||
|
||
return scope.Close(t); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#ifndef tcp_h | ||
#define tcp_h | ||
|
||
#include <v8.h> | ||
#include <ev.h> | ||
|
||
using namespace v8; | ||
|
||
Handle<Object> tcp_initialize (struct ev_loop *); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
|
||
TCP.connect ({ | ||
host: "google.com", | ||
port: 80, | ||
connected: function () { | ||
log("connected to google.com"); | ||
} | ||
}); | ||
|