// Copyright 2009 Ryan Dahl #ifndef SRC_NET_H_ #define SRC_NET_H_ #include #include #include #include #if EVCOM_HAVE_GNUTLS #include #include #endif 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); #if EVCOM_HAVE_GNUTLS static v8::Handle SetSecure(const v8::Arguments& args); static v8::Handle VerifyPeer(const v8::Arguments& args); static v8::Handle GetPeerCertificate(const v8::Arguments& args); #endif 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_; bool secure_; #if EVCOM_HAVE_GNUTLS gnutls_certificate_credentials_t credentials; #endif 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); #if EVCOM_HAVE_GNUTLS if (connection->secure_) { if (connection->stream_.session) { gnutls_deinit(connection->stream_.session); connection->stream_.session = NULL; } if (!connection->stream_.server && connection->credentials) { gnutls_certificate_free_credentials(connection->credentials); connection->credentials = NULL; } } #endif 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); #if EVCOM_HAVE_GNUTLS static v8::Handle SetSecure(const v8::Arguments& args); #endif Server() : EventEmitter() { evcom_server_init(&server_); server_.on_connection = Server::on_connection; server_.on_close = Server::on_close; server_.data = this; secure_ = false; } 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_; #if EVCOM_HAVE_GNUTLS gnutls_certificate_credentials_t credentials; #endif bool secure_; }; } // namespace node #endif // SRC_NET_H_ #if EVCOM_HAVE_GNUTLS void init_tls_session(evcom_stream* stream_, gnutls_certificate_credentials_t credentials, gnutls_connection_end_t session_type); int verify_certificate_chain(gnutls_session_t session, const char *hostname, const gnutls_datum_t * cert_chain, int cert_chain_length, gnutls_x509_crl_t *crl_list, int crl_list_size, gnutls_x509_crt_t *ca_list, int ca_list_size); int verify_cert2(gnutls_x509_crt_t crt, gnutls_x509_crt_t issuer, gnutls_x509_crl_t * crl_list, int crl_list_size); int verify_last_cert(gnutls_x509_crt_t crt, gnutls_x509_crt_t * ca_list, int ca_list_size, gnutls_x509_crl_t * crl_list, int crl_list_size); #define JS_GNUTLS_CERT_VALIDATED 1 #define JS_GNUTLS_CERT_UNDEFINED 0 #define JS_GNUTLS_CERT_SIGNER_NOT_FOUND -100 #define JS_GNUTLS_CERT_SIGNER_NOT_CA -101 #define JS_GNUTLS_CERT_INVALID -102 #define JS_GNUTLS_CERT_NOT_ACTIVATED -103 #define JS_GNUTLS_CERT_EXPIRED -104 #define JS_GNUTLS_CERT_REVOKED -105 #define JS_GNUTLS_CERT_DOES_NOT_MATCH_HOSTNAME -106 #endif