mirror of https://github.com/lukechilds/node.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
247 lines
5.2 KiB
247 lines
5.2 KiB
#include <v8.h>
|
|
|
|
extern "C" {
|
|
#include <oi.h>
|
|
#include <ebb_request_parser.h>
|
|
}
|
|
|
|
#include <assert.h>
|
|
#include <string>
|
|
#include <map>
|
|
|
|
using namespace v8;
|
|
using namespace std;
|
|
|
|
#define PORT "1981"
|
|
#define MAX_URL 500
|
|
|
|
static oi_server server;
|
|
static struct ev_loop *loop;
|
|
|
|
class Connection {
|
|
public:
|
|
Connection(void);
|
|
ebb_request_parser parser;
|
|
oi_socket socket;
|
|
};
|
|
|
|
class Request {
|
|
public:
|
|
Request(Connection &);
|
|
string path;
|
|
Connection &connection_;
|
|
ebb_request parser_info;
|
|
};
|
|
|
|
Request::Request
|
|
( Connection &connection
|
|
)
|
|
: connection_(connection)
|
|
{
|
|
ebb_request_init(&parser_info);
|
|
}
|
|
|
|
Connection::Connection
|
|
( void
|
|
)
|
|
{
|
|
oi_socket_init (&socket, 30.0);
|
|
ebb_request_parser_init (&parser);
|
|
}
|
|
|
|
void on_path
|
|
( ebb_request *req
|
|
, const char *buf
|
|
, size_t len
|
|
)
|
|
{
|
|
Request *request = static_cast<Request*> (req->data);
|
|
request->path.append(buf, len);
|
|
}
|
|
|
|
void on_request_complete
|
|
( ebb_request *req
|
|
)
|
|
{
|
|
Request *request = static_cast<Request*> (req->data);
|
|
|
|
// dispatch to javascript
|
|
}
|
|
|
|
ebb_request * on_request
|
|
( void *data
|
|
)
|
|
{
|
|
Connection *connection = static_cast<Connection*> (data);
|
|
|
|
Request *request = new Request(*connection);
|
|
|
|
request->parser_info.on_path = on_path;
|
|
request->parser_info.on_query_string = NULL;
|
|
request->parser_info.on_uri = NULL;
|
|
request->parser_info.on_fragment = NULL;
|
|
request->parser_info.on_header_field = NULL;
|
|
request->parser_info.on_header_value = NULL;
|
|
request->parser_info.on_headers_complete = NULL;
|
|
request->parser_info.on_body = NULL;
|
|
request->parser_info.on_complete = on_request_complete;
|
|
request->parser_info.data = request;
|
|
|
|
return &request->parser_info;
|
|
}
|
|
|
|
static void on_read
|
|
( oi_socket *socket
|
|
, const void *buf
|
|
, size_t count
|
|
)
|
|
{
|
|
Connection *connection = static_cast<Connection*> (socket->data);
|
|
ebb_request_parser_execute ( &connection->parser
|
|
, static_cast<const char*> (buf) // FIXME change ebb to use void*
|
|
, count
|
|
);
|
|
/* TODO check for errors */
|
|
}
|
|
|
|
static void on_close
|
|
( oi_socket *socket
|
|
)
|
|
{
|
|
Connection *connection = static_cast<Connection*> (socket->data);
|
|
/* TODO free requests */
|
|
free(connection);
|
|
}
|
|
|
|
static void on_drain
|
|
( oi_socket *socket
|
|
)
|
|
{
|
|
Connection *connection = static_cast<Connection*> (socket->data);
|
|
//oi_socket_close(&connection->socket);
|
|
}
|
|
|
|
static oi_socket* new_connection
|
|
( oi_server *server
|
|
, struct sockaddr *addr
|
|
, socklen_t len
|
|
)
|
|
{
|
|
Connection *connection = new Connection();
|
|
|
|
/* initialize the components of Connection */
|
|
oi_socket_init(&connection->socket, 30.0);
|
|
connection->socket.on_read = on_read;
|
|
connection->socket.on_error = NULL;
|
|
connection->socket.on_close = on_close;
|
|
connection->socket.on_timeout = NULL;
|
|
connection->socket.on_drain = on_drain;
|
|
connection->socket.data = connection;
|
|
|
|
ebb_request_parser_init(&connection->parser);
|
|
connection->parser.new_request = on_request;
|
|
connection->parser.data = connection;
|
|
|
|
return &connection->socket;
|
|
}
|
|
|
|
|
|
// Reads a file into a v8 string.
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
int main
|
|
( int argc
|
|
, char *argv[]
|
|
)
|
|
{
|
|
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;
|
|
}
|
|
/*
|
|
HttpRequestProcessor processor(source);
|
|
map<string, string> output;
|
|
if (!processor.Initialize(&options, &output)) {
|
|
fprintf(stderr, "Error initializing processor.\n");
|
|
return 1;
|
|
}
|
|
*/
|
|
|
|
/////////////////////////////////////
|
|
|
|
|
|
loop = ev_default_loop(0);
|
|
|
|
oi_server_init(&server, 1024);
|
|
server.on_connection = new_connection;
|
|
|
|
// get addrinfo for localhost, PORT
|
|
struct addrinfo *servinfo;
|
|
struct addrinfo hints;
|
|
memset(&hints, 0, sizeof hints);
|
|
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);
|
|
|
|
r = oi_server_listen(&server, servinfo);
|
|
assert(r == 0);
|
|
|
|
oi_server_attach(&server, loop);
|
|
|
|
printf("Running at http://localhost:%s/\n", PORT);
|
|
|
|
ev_loop(loop, 0);
|
|
return 0;
|
|
}
|
|
|