// Copyright 2009 Ryan Dahl
#ifndef SRC_NET_H_
#define SRC_NET_H_
#include
#include
#include
#include
namespace node {
class Server;
class Connection : public EventEmitter {
public:
static void Initialize(v8::Handle target);
protected:
/* v8 interface */
static v8::Persistent constructor_template;
static v8::Handle New(const v8::Arguments& args);
static v8::Handle Connect(const v8::Arguments& args);
static v8::Handle Send(const v8::Arguments& args);
static v8::Handle SendUtf8(const v8::Arguments& args);
static v8::Handle Close(const v8::Arguments& args);
static v8::Handle ForceClose(const v8::Arguments& args);
static v8::Handle SetEncoding(const v8::Arguments& args);
static v8::Handle ReadPause(const v8::Arguments& args);
static v8::Handle ReadResume(const v8::Arguments& args);
static v8::Handle SetTimeout(const v8::Arguments& args);
static v8::Handle SetNoDelay(const v8::Arguments& args);
static v8::Handle ReadyStateGetter(v8::Local _,
const v8::AccessorInfo& info);
static v8::Handle FDGetter(v8::Local _,
const v8::AccessorInfo& info);
Connection() : EventEmitter() {
encoding_ = BINARY;
host_ = NULL;
port_ = NULL;
Init();
}
virtual ~Connection();
int Connect(struct sockaddr *address) {
return evcom_stream_connect(&stream_, address);
}
void Send(const char *buf, size_t len) {
evcom_stream_write(&stream_, buf, len);
}
void Close() {
evcom_stream_close(&stream_);
}
void ForceClose() {
evcom_stream_force_close(&stream_);
}
void ReadPause() {
evcom_stream_read_pause(&stream_);
}
void ReadResume() {
evcom_stream_read_resume(&stream_);
}
void SetTimeout(float timeout) {
evcom_stream_reset_timeout(&stream_, timeout);
}
void SetNoDelay(bool no_delay) {
evcom_stream_set_no_delay(&stream_, no_delay);
}
virtual void OnConnect();
virtual void OnReceive(const void *buf, size_t len);
virtual void OnEOF();
virtual void OnClose();
virtual void OnTimeout();
virtual void OnDrain();
v8::Local GetProtocol();
enum evcom_stream_state ReadyState() {
return evcom_stream_state(&stream_);
}
enum encoding encoding_;
bool resolving_;
private:
/* liboi callbacks */
static void on_connect(evcom_stream *s) {
Connection *connection = static_cast(s->data);
connection->OnConnect();
}
static void on_read(evcom_stream *s, const void *buf, size_t len) {
Connection *connection = static_cast(s->data);
assert(connection->attached_);
if (len == 0)
connection->OnEOF();
else
connection->OnReceive(buf, len);
}
static void on_close(evcom_stream *s) {
Connection *connection = static_cast(s->data);
evcom_stream_detach(s);
assert(connection->stream_.recvfd < 0);
assert(connection->stream_.sendfd < 0);
connection->OnClose();
assert(connection->attached_);
connection->Detach();
}
static void on_timeout(evcom_stream *s) {
Connection *connection = static_cast(s->data);
connection->OnTimeout();
}
static void on_drain(evcom_stream *s) {
Connection *connection = static_cast(s->data);
connection->OnDrain();
}
void Init(); // constructor helper.
static int Resolve(eio_req *req);
static int AfterResolve(eio_req *req);
char *host_;
char *port_;
evcom_stream stream_;
friend class Server;
};
class Server : public EventEmitter {
public:
static void Initialize(v8::Handle target);
protected:
static v8::Persistent constructor_template;
static v8::Handle New(const v8::Arguments& args);
static v8::Handle Listen(const v8::Arguments& args);
static v8::Handle Close(const v8::Arguments& args);
Server() : EventEmitter() {
evcom_server_init(&server_);
server_.on_connection = Server::on_connection;
server_.on_close = Server::on_close;
server_.data = this;
}
virtual ~Server() {
assert(server_.fd >= 0);
}
int Listen(struct sockaddr *address, int backlog) {
int r = evcom_server_listen(&server_, address, backlog);
if (r != 0) return r;
evcom_server_attach(EV_DEFAULT_ &server_);
Attach();
return 0;
}
void Close() {
evcom_server_close(&server_);
}
virtual v8::Handle GetConnectionTemplate();
virtual Connection* UnwrapConnection(v8::Local connection);
private:
Connection* OnConnection(struct sockaddr *addr);
static evcom_stream* on_connection(evcom_server *s, struct sockaddr *addr) {
Server *server = static_cast(s->data);
Connection *connection = server->OnConnection(addr);
return &connection->stream_;
}
void OnClose(int errorno);
static void on_close(evcom_server *s) {
Server *server = static_cast(s->data);
evcom_server_detach(s);
server->OnClose(s->errorno);
server->Detach();
}
evcom_server server_;
};
} // namespace node
#endif // SRC_NET_H_