Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

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.
  • Loading branch information...
ry committed Mar 3, 2009
1 parent 1afe6d2 commit 19478ed4b14263c489e872156ca55ff16a07ebe0
Showing with 355 additions and 208 deletions.
  1. +14 −11 Makefile
  2. +30 −0 http_api.js
  3. +154 −0 node.cc
  4. +128 −181 server.cc → node_http.cc
  5. +11 −0 node_http.h
  6. +7 −5 tcp.cc → node_tcp.cc
  7. +11 −0 node_tcp.h
  8. +0 −11 tcp.h
@@ -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
@@ -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
@@ -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;
}

0 comments on commit 19478ed

Please sign in to comment.
You can’t perform that action at this time.