mirror of
https://github.com/nodejs/node.git
synced 2025-12-28 16:07:39 +00:00
Major refactoring: program name now "node"
Trying to make a more moduler design. Two libraries currently "TCP" and "HTTP" each have their own file. Other major feature added here is multiple web servers! excitement.
This commit is contained in:
parent
1afe6d26db
commit
19478ed4b1
25
Makefile
25
Makefile
@ -1,6 +1,6 @@
|
||||
EVDIR=$(HOME)/local/libev
|
||||
V8INC = $(HOME)/src/v8/include
|
||||
V8LIB = $(HOME)/src/v8/libv8.a
|
||||
V8LIB = $(HOME)/src/v8/libv8_g.a
|
||||
|
||||
CFLAGS = -g -I$(V8INC) -Ideps/oi -DHAVE_GNUTLS=0 -Ideps/ebb
|
||||
LDFLAGS = -lev -pthread # -lefence
|
||||
@ -10,20 +10,17 @@ ifdef EVDIR
|
||||
LDFLAGS += -L$(EVDIR)/lib
|
||||
endif
|
||||
|
||||
server: server.o tcp.o oi_socket.o oi_async.o ebb_request_parser.o oi_buf.o
|
||||
g++ -o server $^ $(LDFLAGS) $(V8LIB)
|
||||
node: node.o node_tcp.o node_http.o oi_socket.o oi_async.o oi_buf.o ebb_request_parser.o
|
||||
g++ -o node $^ $(LDFLAGS) $(V8LIB)
|
||||
|
||||
server.o: server.cc
|
||||
node.o: node.cc
|
||||
g++ $(CFLAGS) -c $<
|
||||
|
||||
tcp.o: tcp.cc
|
||||
g++ $(CFLAGS) -c $<
|
||||
|
||||
ebb_request_parser.o: ebb_request_parser.c deps/ebb/ebb_request_parser.h
|
||||
node_tcp.o: node_tcp.cc
|
||||
g++ $(CFLAGS) -c $<
|
||||
|
||||
ebb_request_parser.c: deps/ebb/ebb_request_parser.rl
|
||||
ragel -s -G2 $< -o $@
|
||||
node_http.o: node_http.cc
|
||||
g++ $(CFLAGS) -c $<
|
||||
|
||||
oi_socket.o: deps/oi/oi_socket.c deps/oi/oi_socket.h
|
||||
gcc $(CFLAGS) -c $<
|
||||
@ -33,10 +30,16 @@ oi_async.o: deps/oi/oi_async.c deps/oi/oi_async.h
|
||||
|
||||
oi_buf.o: deps/oi/oi_buf.c deps/oi/oi_buf.h
|
||||
gcc $(CFLAGS) -c $<
|
||||
|
||||
ebb_request_parser.o: ebb_request_parser.c deps/ebb/ebb_request_parser.h
|
||||
g++ $(CFLAGS) -c $<
|
||||
|
||||
ebb_request_parser.c: deps/ebb/ebb_request_parser.rl
|
||||
ragel -s -G2 $< -o $@
|
||||
|
||||
clean:
|
||||
rm -f ebb_request_parser.c
|
||||
rm -f *.o
|
||||
rm -f server
|
||||
rm -f node
|
||||
|
||||
.PHONY: clean test
|
||||
|
||||
30
http_api.js
Normal file
30
http_api.js
Normal file
@ -0,0 +1,30 @@
|
||||
function encode(data) {
|
||||
var chunk = data.toString();
|
||||
return chunk.length.toString(16) + "\r\n" + chunk + "\r\n";
|
||||
}
|
||||
|
||||
var server = new HTTP.Server("localhost", 8000);
|
||||
|
||||
server.onRequest = function (request) {
|
||||
log( "path: " + request.path );
|
||||
log( "query string: " + request.query_string );
|
||||
|
||||
// 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");
|
||||
|
||||
};
|
||||
/*
|
||||
server.close();
|
||||
*/
|
||||
154
node.cc
Normal file
154
node.cc
Normal file
@ -0,0 +1,154 @@
|
||||
#include <oi.h>
|
||||
|
||||
#include "node_tcp.h"
|
||||
#include "node_http.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
#include <v8.h>
|
||||
|
||||
using namespace v8;
|
||||
using namespace std;
|
||||
|
||||
static struct ev_loop *loop;
|
||||
|
||||
static Persistent<Context> context;
|
||||
static Persistent<Function> process_;
|
||||
|
||||
// Reads a file into a v8 string.
|
||||
static Handle<String> ReadFile
|
||||
( const string& name
|
||||
)
|
||||
{
|
||||
FILE* file = fopen(name.c_str(), "rb");
|
||||
if (file == NULL) return Handle<String>();
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
int size = ftell(file);
|
||||
rewind(file);
|
||||
|
||||
char* chars = new char[size + 1];
|
||||
chars[size] = '\0';
|
||||
for (int i = 0; i < size;) {
|
||||
int read = fread(&chars[i], 1, size - i, file);
|
||||
i += read;
|
||||
}
|
||||
fclose(file);
|
||||
Handle<String> result = String::New(chars, size);
|
||||
delete[] chars;
|
||||
return result;
|
||||
}
|
||||
|
||||
static void ParseOptions
|
||||
( int argc
|
||||
, char* argv[]
|
||||
, map<string, string>& options
|
||||
, string* file
|
||||
)
|
||||
{
|
||||
for (int i = 1; i < argc; i++) {
|
||||
string arg = argv[i];
|
||||
int index = arg.find('=', 0);
|
||||
if (index == string::npos) {
|
||||
*file = arg;
|
||||
} else {
|
||||
string key = arg.substr(0, index);
|
||||
string value = arg.substr(index+1);
|
||||
options[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool compile
|
||||
( Handle<String> script
|
||||
)
|
||||
{
|
||||
HandleScope handle_scope;
|
||||
|
||||
// We're just about to compile the script; set up an error handler to
|
||||
// catch any exceptions the script might throw.
|
||||
TryCatch try_catch;
|
||||
|
||||
// Compile the script and check for errors.
|
||||
Handle<Script> compiled_script = Script::Compile(script);
|
||||
if (compiled_script.IsEmpty()) {
|
||||
|
||||
Handle<Message> message = try_catch.Message();
|
||||
|
||||
String::Utf8Value error(try_catch.Exception());
|
||||
|
||||
printf("error: %s line %d\n", *error, message->GetLineNumber());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Run the script!
|
||||
Handle<Value> result = compiled_script->Run();
|
||||
if (result.IsEmpty()) {
|
||||
// The TryCatch above is still in effect and will have caught the error.
|
||||
String::Utf8Value error(try_catch.Exception());
|
||||
printf("error: %s\n", *error);
|
||||
// Running the script failed; bail out.
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static Handle<Value> LogCallback
|
||||
( const Arguments& args
|
||||
)
|
||||
{
|
||||
if (args.Length() < 1) return v8::Undefined();
|
||||
HandleScope scope;
|
||||
Handle<Value> arg = args[0];
|
||||
String::Utf8Value value(arg);
|
||||
|
||||
printf("Logged: %s\n", *value);
|
||||
fflush(stdout);
|
||||
|
||||
return v8::Undefined();
|
||||
}
|
||||
|
||||
int main
|
||||
( int argc
|
||||
, char *argv[]
|
||||
)
|
||||
{
|
||||
loop = ev_default_loop(0);
|
||||
|
||||
map<string, string> options;
|
||||
string file;
|
||||
ParseOptions(argc, argv, options, &file);
|
||||
if (file.empty()) {
|
||||
fprintf(stderr, "No script was specified.\n");
|
||||
return 1;
|
||||
}
|
||||
HandleScope scope;
|
||||
Handle<String> source = ReadFile(file);
|
||||
if (source.IsEmpty()) {
|
||||
fprintf(stderr, "Error reading '%s'.\n", file.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
context = Context::New(NULL, ObjectTemplate::New());
|
||||
Context::Scope context_scope(context);
|
||||
|
||||
Local<Object> g = Context::GetCurrent()->Global();
|
||||
g->Set( String::New("log"), FunctionTemplate::New(LogCallback)->GetFunction());
|
||||
g->Set( String::New("TCP"), node_tcp_initialize(loop));
|
||||
g->Set( String::New("HTTP"), node_http_initialize(loop));
|
||||
|
||||
// Compile and run the script
|
||||
if (!compile(source))
|
||||
return false;
|
||||
|
||||
ev_loop(loop, 0);
|
||||
|
||||
context.Dispose();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1,37 +1,51 @@
|
||||
#include <oi.h>
|
||||
#include "node_http.h"
|
||||
|
||||
#include <oi_socket.h>
|
||||
#include <ebb_request_parser.h>
|
||||
|
||||
#include "tcp.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
#include <v8.h>
|
||||
|
||||
using namespace v8;
|
||||
using namespace std;
|
||||
|
||||
#define PORT "1981"
|
||||
|
||||
static oi_server server;
|
||||
static Persistent<ObjectTemplate> request_template;
|
||||
static struct ev_loop *loop;
|
||||
|
||||
static Persistent<Context> context;
|
||||
static Persistent<Function> process_;
|
||||
static Persistent<ObjectTemplate> request_template_;
|
||||
class Server {
|
||||
public:
|
||||
Server (Handle<Object> _js_server);
|
||||
~Server ();
|
||||
|
||||
int Start(struct addrinfo *servinfo);
|
||||
void Stop();
|
||||
|
||||
Handle<Value> Callback()
|
||||
{
|
||||
HandleScope scope;
|
||||
Handle<Value> value = js_server->Get(String::New("onRequest"));
|
||||
return scope.Close(value);
|
||||
}
|
||||
|
||||
private:
|
||||
oi_server server;
|
||||
Persistent<Object> js_server;
|
||||
};
|
||||
|
||||
class Connection {
|
||||
public:
|
||||
Connection ( void)
|
||||
Connection ()
|
||||
{
|
||||
oi_socket_init (&socket, 30.0);
|
||||
ebb_request_parser_init (&parser);
|
||||
}
|
||||
ebb_request_parser parser;
|
||||
oi_socket socket;
|
||||
Persistent<Function> js_onRequest;
|
||||
|
||||
friend class Server;
|
||||
};
|
||||
|
||||
class HttpRequest {
|
||||
@ -39,6 +53,8 @@ class HttpRequest {
|
||||
HttpRequest (Connection &c);
|
||||
~HttpRequest();
|
||||
|
||||
void MakeBodyCallback (const char *base, size_t length);
|
||||
|
||||
string path;
|
||||
string query_string;
|
||||
string fragment;
|
||||
@ -62,17 +78,14 @@ static HttpRequest* UnwrapRequest
|
||||
return static_cast<HttpRequest*>(ptr);
|
||||
}
|
||||
|
||||
static void make_onBody_callback
|
||||
( HttpRequest *request
|
||||
, const char *base
|
||||
, size_t length
|
||||
)
|
||||
void
|
||||
HttpRequest::MakeBodyCallback (const char *base, size_t length)
|
||||
{
|
||||
HandleScope handle_scope;
|
||||
|
||||
Handle<Object> obj = request->js_object;
|
||||
//
|
||||
// XXX don't always allocate onBody strings
|
||||
Handle<Value> onBody_val = request->js_object->Get(String::NewSymbol("onBody"));
|
||||
//
|
||||
Handle<Value> onBody_val = js_object->Get(String::NewSymbol("onBody"));
|
||||
if (!onBody_val->IsFunction()) return;
|
||||
Handle<Function> onBody = Handle<Function>::Cast(onBody_val);
|
||||
|
||||
@ -81,13 +94,14 @@ static void make_onBody_callback
|
||||
Handle<Value> argv[argc];
|
||||
|
||||
if(length) {
|
||||
// TODO use array for binary data
|
||||
Handle<String> chunk = String::New(base, length);
|
||||
argv[0] = chunk;
|
||||
} else {
|
||||
argv[0] = Null();
|
||||
}
|
||||
|
||||
Handle<Value> result = onBody->Call(request->js_object, argc, argv);
|
||||
Handle<Value> result = onBody->Call(js_object, argc, argv);
|
||||
|
||||
if (result.IsEmpty()) {
|
||||
String::Utf8Value error(try_catch.Exception());
|
||||
@ -250,17 +264,16 @@ static void on_headers_complete
|
||||
|
||||
HandleScope handle_scope;
|
||||
|
||||
if (request_template_.IsEmpty()) {
|
||||
if (request_template.IsEmpty()) {
|
||||
Handle<ObjectTemplate> raw_template = ObjectTemplate::New();
|
||||
raw_template->SetInternalFieldCount(1);
|
||||
raw_template->Set(String::New("respond"), FunctionTemplate::New(RespondCallback));
|
||||
raw_template->Set(String::NewSymbol("respond"), FunctionTemplate::New(RespondCallback));
|
||||
|
||||
request_template_ = Persistent<ObjectTemplate>::New(raw_template);
|
||||
request_template = Persistent<ObjectTemplate>::New(raw_template);
|
||||
}
|
||||
Handle<ObjectTemplate> templ = request_template_;
|
||||
|
||||
// Create an empty http request wrapper.
|
||||
Handle<Object> result = templ->NewInstance();
|
||||
Handle<Object> result = request_template->NewInstance();
|
||||
|
||||
// Wrap the raw C++ pointer in an External so it can be referenced
|
||||
// from within JavaScript.
|
||||
@ -320,9 +333,6 @@ static void on_headers_complete
|
||||
|
||||
request->js_object = Persistent<Object>::New(result);
|
||||
|
||||
// Enter this processor's context so all the remaining operations
|
||||
// take place there
|
||||
Context::Scope context_scope(context);
|
||||
|
||||
// Set up an exception handler before calling the Process function
|
||||
TryCatch try_catch;
|
||||
@ -331,7 +341,7 @@ static void on_headers_complete
|
||||
// and one argument, the request.
|
||||
const int argc = 1;
|
||||
Handle<Value> argv[argc] = { request->js_object };
|
||||
Handle<Value> r = process_->Call(context->Global(), argc, argv);
|
||||
Handle<Value> r = request->connection.js_onRequest->Call(Context::GetCurrent()->Global(), argc, argv);
|
||||
if (r.IsEmpty()) {
|
||||
String::Utf8Value error(try_catch.Exception());
|
||||
printf("error: %s\n", *error);
|
||||
@ -343,23 +353,19 @@ static void on_request_complete
|
||||
)
|
||||
{
|
||||
HttpRequest *request = static_cast<HttpRequest*> (req->data);
|
||||
|
||||
make_onBody_callback(request, NULL, 0); // EOF
|
||||
request->MakeBodyCallback(NULL, 0); // EOF
|
||||
}
|
||||
|
||||
|
||||
static void on_body
|
||||
( ebb_request *req
|
||||
, const char *base
|
||||
, size_t length
|
||||
)
|
||||
{
|
||||
//printf("on body %d\n", length);
|
||||
|
||||
HttpRequest *request = static_cast<HttpRequest*> (req->data);
|
||||
|
||||
if(length)
|
||||
make_onBody_callback(request, base, length);
|
||||
request->MakeBodyCallback(base, length);
|
||||
}
|
||||
|
||||
static ebb_request * on_request
|
||||
@ -419,12 +425,21 @@ static void on_drain
|
||||
//oi_socket_close(&connection->socket);
|
||||
}
|
||||
|
||||
static oi_socket* new_connection
|
||||
( oi_server *server
|
||||
static oi_socket* on_connection
|
||||
( oi_server *_server
|
||||
, struct sockaddr *addr
|
||||
, socklen_t len
|
||||
)
|
||||
{
|
||||
HandleScope scope;
|
||||
|
||||
Server *server = static_cast<Server*> (_server->data);
|
||||
|
||||
Handle<Value> callback_v = server->Callback();
|
||||
|
||||
if(callback_v == Undefined())
|
||||
return NULL;
|
||||
|
||||
Connection *connection = new Connection();
|
||||
connection->socket.on_read = on_read;
|
||||
connection->socket.on_error = NULL;
|
||||
@ -436,159 +451,67 @@ static oi_socket* new_connection
|
||||
connection->parser.new_request = on_request;
|
||||
connection->parser.data = connection;
|
||||
|
||||
Handle<Function> f = Handle<Function>::Cast(callback_v);
|
||||
connection->js_onRequest = Persistent<Function>::New(f);
|
||||
|
||||
return &connection->socket;
|
||||
}
|
||||
|
||||
// Reads a file into a v8 string.
|
||||
static Handle<String> ReadFile
|
||||
( const string& name
|
||||
)
|
||||
{
|
||||
FILE* file = fopen(name.c_str(), "rb");
|
||||
if (file == NULL) return Handle<String>();
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
int size = ftell(file);
|
||||
rewind(file);
|
||||
|
||||
char* chars = new char[size + 1];
|
||||
chars[size] = '\0';
|
||||
for (int i = 0; i < size;) {
|
||||
int read = fread(&chars[i], 1, size - i, file);
|
||||
i += read;
|
||||
}
|
||||
fclose(file);
|
||||
Handle<String> result = String::New(chars, size);
|
||||
delete[] chars;
|
||||
return result;
|
||||
}
|
||||
|
||||
static void ParseOptions
|
||||
( int argc
|
||||
, char* argv[]
|
||||
, map<string, string>& options
|
||||
, string* file
|
||||
static void server_destroy
|
||||
( Persistent<Value> _
|
||||
, void *data
|
||||
)
|
||||
{
|
||||
for (int i = 1; i < argc; i++) {
|
||||
string arg = argv[i];
|
||||
int index = arg.find('=', 0);
|
||||
if (index == string::npos) {
|
||||
*file = arg;
|
||||
} else {
|
||||
string key = arg.substr(0, index);
|
||||
string value = arg.substr(index+1);
|
||||
options[key] = value;
|
||||
}
|
||||
}
|
||||
Server *server = static_cast<Server *> (data);
|
||||
delete server;
|
||||
}
|
||||
|
||||
static bool compile
|
||||
( Handle<String> script
|
||||
)
|
||||
Server::Server (Handle<Object> _js_server)
|
||||
{
|
||||
HandleScope handle_scope;
|
||||
|
||||
// We're just about to compile the script; set up an error handler to
|
||||
// catch any exceptions the script might throw.
|
||||
TryCatch try_catch;
|
||||
|
||||
// Compile the script and check for errors.
|
||||
Handle<Script> compiled_script = Script::Compile(script);
|
||||
if (compiled_script.IsEmpty()) {
|
||||
|
||||
Handle<Message> message = try_catch.Message();
|
||||
|
||||
String::Utf8Value error(try_catch.Exception());
|
||||
|
||||
printf("error: %s line %d\n", *error, message->GetLineNumber());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Run the script!
|
||||
Handle<Value> result = compiled_script->Run();
|
||||
if (result.IsEmpty()) {
|
||||
// The TryCatch above is still in effect and will have caught the error.
|
||||
String::Utf8Value error(try_catch.Exception());
|
||||
printf("error: %s\n", *error);
|
||||
// Running the script failed; bail out.
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static Handle<Value> LogCallback
|
||||
( const Arguments& args
|
||||
)
|
||||
{
|
||||
if (args.Length() < 1) return v8::Undefined();
|
||||
HandleScope scope;
|
||||
Handle<Value> arg = args[0];
|
||||
String::Utf8Value value(arg);
|
||||
|
||||
printf("Logged: %s\n", *value);
|
||||
fflush(stdout);
|
||||
|
||||
return v8::Undefined();
|
||||
}
|
||||
|
||||
int main
|
||||
( int argc
|
||||
, char *argv[]
|
||||
)
|
||||
{
|
||||
loop = ev_default_loop(0);
|
||||
|
||||
|
||||
map<string, string> options;
|
||||
string file;
|
||||
ParseOptions(argc, argv, options, &file);
|
||||
if (file.empty()) {
|
||||
fprintf(stderr, "No script was specified.\n");
|
||||
return 1;
|
||||
}
|
||||
HandleScope scope;
|
||||
Handle<String> source = ReadFile(file);
|
||||
if (source.IsEmpty()) {
|
||||
fprintf(stderr, "Error reading '%s'.\n", file.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
context = Context::New(NULL, ObjectTemplate::New());
|
||||
Context::Scope context_scope(context);
|
||||
|
||||
Local<Object> g = Context::GetCurrent()->Global();
|
||||
g->Set( String::New("log"), FunctionTemplate::New(LogCallback)->GetFunction());
|
||||
g->Set( String::New("TCP"), tcp_initialize(loop));
|
||||
|
||||
// Compile and run the script
|
||||
if (!compile(source))
|
||||
return false;
|
||||
|
||||
// The script compiled and ran correctly. Now we fetch out the
|
||||
// Process function from the global object.
|
||||
Handle<String> process_name = String::New("Process");
|
||||
Handle<Value> process_val = context->Global()->Get(process_name);
|
||||
|
||||
// If there is no Process function, or if it is not a function,
|
||||
// bail out
|
||||
if (!process_val->IsFunction()) return false;
|
||||
|
||||
// It is a function; cast it to a Function
|
||||
Handle<Function> process_fun = Handle<Function>::Cast(process_val);
|
||||
|
||||
// Store the function in a Persistent handle, since we also want
|
||||
// that to remain after this call returns
|
||||
process_ = Persistent<Function>::New(process_fun);
|
||||
|
||||
/////////////////////////////////////
|
||||
/////////////////////////////////////
|
||||
/////////////////////////////////////
|
||||
|
||||
oi_server_init(&server, 1024);
|
||||
server.on_connection = new_connection;
|
||||
server.on_connection = on_connection;
|
||||
server.data = this;
|
||||
HandleScope scope;
|
||||
js_server = Persistent<Object>::New (_js_server);
|
||||
// are we ever going to need this external?
|
||||
js_server->SetInternalField (0, External::New(this));
|
||||
js_server.MakeWeak (this, server_destroy);
|
||||
}
|
||||
|
||||
Server::~Server ()
|
||||
{
|
||||
Stop();
|
||||
js_server.Dispose();
|
||||
js_server.Clear(); // necessary?
|
||||
}
|
||||
|
||||
int
|
||||
Server::Start(struct addrinfo *servinfo)
|
||||
{
|
||||
int r = oi_server_listen(&server, servinfo);
|
||||
if(r == 0)
|
||||
oi_server_attach(&server, loop);
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
Server::Stop()
|
||||
{
|
||||
oi_server_close (&server);
|
||||
oi_server_detach (&server);
|
||||
}
|
||||
|
||||
/* This constructor takes 2 arguments: host, port. */
|
||||
static Handle<Value>
|
||||
server_constructor (const Arguments& args)
|
||||
{
|
||||
if (args.Length() < 2)
|
||||
return Undefined();
|
||||
|
||||
HandleScope scope;
|
||||
|
||||
String::AsciiValue host(args[0]->ToString());
|
||||
String::AsciiValue port(args[1]->ToString());
|
||||
|
||||
// get addrinfo for localhost, PORT
|
||||
struct addrinfo *servinfo;
|
||||
@ -597,20 +520,44 @@ int main
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
int r = getaddrinfo(NULL, PORT, &hints, &servinfo);
|
||||
assert(r == 0);
|
||||
int r = getaddrinfo(NULL, *port, &hints, &servinfo);
|
||||
if (r != 0)
|
||||
return Undefined(); // XXX raise error?
|
||||
|
||||
r = oi_server_listen(&server, servinfo);
|
||||
assert(r == 0);
|
||||
//
|
||||
//
|
||||
//
|
||||
// TODO host is ignored for now assumed localhost
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
oi_server_attach(&server, loop);
|
||||
Server *server = new Server(args.This());
|
||||
if(server == NULL)
|
||||
return Undefined(); // XXX raise error?
|
||||
|
||||
printf("Running at http://localhost:%s/\n", PORT);
|
||||
r = server->Start(servinfo);
|
||||
if (r != 0)
|
||||
return Undefined(); // XXX raise error?
|
||||
|
||||
ev_loop(loop, 0);
|
||||
|
||||
context.Dispose();
|
||||
process_.Dispose();
|
||||
|
||||
return 0;
|
||||
printf("Running at http://localhost:%s/\n", *port);
|
||||
|
||||
return args.This();
|
||||
}
|
||||
|
||||
Handle<Object> node_http_initialize (struct ev_loop *_loop)
|
||||
{
|
||||
HandleScope scope;
|
||||
|
||||
loop = _loop;
|
||||
|
||||
Local<Object> http = Object::New();
|
||||
|
||||
Local<FunctionTemplate> server_t = FunctionTemplate::New(server_constructor);
|
||||
server_t->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
|
||||
http->Set(String::New("Server"), server_t->GetFunction());
|
||||
|
||||
return scope.Close(http);
|
||||
}
|
||||
11
node_http.h
Normal file
11
node_http.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef node_http_h
|
||||
#define node_http_h
|
||||
|
||||
#include <v8.h>
|
||||
#include <ev.h>
|
||||
|
||||
using namespace v8;
|
||||
|
||||
Handle<Object> node_http_initialize (struct ev_loop *);
|
||||
|
||||
#endif
|
||||
@ -1,4 +1,4 @@
|
||||
#include "tcp.h"
|
||||
#include "node_tcp.h"
|
||||
|
||||
#include <oi_socket.h>
|
||||
#include <oi_async.h>
|
||||
@ -88,6 +88,8 @@ static void resolve_done
|
||||
{
|
||||
TCPClient *client = static_cast<TCPClient*> (resolve_task->data);
|
||||
|
||||
printf("hello world\n");
|
||||
|
||||
if(result != 0) {
|
||||
printf("error. TODO make call options error callback\n");
|
||||
client->options.Dispose();
|
||||
@ -95,7 +97,7 @@ static void resolve_done
|
||||
return;
|
||||
}
|
||||
|
||||
// Got the address succesfully. Let's connect now.
|
||||
printf("Got the address succesfully. Let's connect now. \n");
|
||||
|
||||
oi_socket_init(&client->socket, 30.0); // TODO adjustable timeout
|
||||
|
||||
@ -145,8 +147,8 @@ static Handle<Value> Connect
|
||||
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());
|
||||
host->WriteAscii(host_s);
|
||||
port->WriteAscii(port_s);
|
||||
|
||||
printf("resolving host: %s, port: %s\n", host_s, port_s);
|
||||
|
||||
@ -164,7 +166,7 @@ static Handle<Value> Connect
|
||||
oi_async_submit (&thread_pool, &client->resolve_task);
|
||||
}
|
||||
|
||||
Handle<Object> tcp_initialize
|
||||
Handle<Object> node_tcp_initialize
|
||||
( struct ev_loop *_loop
|
||||
)
|
||||
{
|
||||
11
node_tcp.h
Normal file
11
node_tcp.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef node_tcp_h
|
||||
#define node_tcp_h
|
||||
|
||||
#include <v8.h>
|
||||
#include <ev.h>
|
||||
|
||||
using namespace v8;
|
||||
|
||||
Handle<Object> node_tcp_initialize (struct ev_loop *);
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue
Block a user