Browse Source

Remove http_old tcp_old

v0.7.4-release
Ryan Dahl 15 years ago
parent
commit
c72967d335
  1. 75
      deps/evcom/Makefile
  2. 1589
      deps/evcom/evcom.c
  3. 260
      deps/evcom/evcom.h
  4. 37
      deps/evcom/recv_states.dot
  5. 65
      deps/evcom/send_states.dot
  6. 100
      deps/evcom/test/echo.c
  7. 892
      deps/evcom/test/test.c
  8. 98
      deps/evcom/test/timeout.rb
  9. 641
      lib/http_old.js
  10. 26
      lib/tcp_old.js
  11. 30
      src/node.cc
  12. 1
      src/node.h
  13. 4
      src/node_cares.cc
  14. 392
      src/node_http.cc
  15. 68
      src/node_http.h
  16. 1122
      src/node_net.cc
  17. 284
      src/node_net.h
  18. 2
      src/node_net2.cc
  19. 25
      wscript

75
deps/evcom/Makefile

@ -1,75 +0,0 @@
# Define EVDIR=/foo/bar if your libev header and library files are in
# /foo/bar/include and /foo/bar/lib directories.
EVDIR=$(HOME)/local/libev
# Define GNUTLSDIR=/foo/bar if your gnutls header and library files are in
# /foo/bar/include and /foo/bar/lib directories.
#
# Comment out the following line to disable TLS
GNUTLSDIR=/usr
# CFLAGS and LDFLAGS are for the users to override from the command line.
CFLAGS = -g -I. -Wall -Werror -Wextra #-DNDEBUG=1
LDFLAGS =
CC = gcc
AR = ar
RANLIB = ranlib
ifdef EVDIR
CFLAGS += -I$(EVDIR)/include
LDFLAGS += -L$(EVDIR)/lib
endif
LDFLAGS += -lev
ifdef GNUTLSDIR
CFLAGS += -I$(GNUTLSDIR)/include -DEVCOM_HAVE_GNUTLS=1
LDFLAGS += -L$(GNUTLSDIR)/lib
LDFLAGS += -lgnutls
endif
DEP = evcom.h
SRC = evcom.c
OBJ = ${SRC:.c=.o}
NAME=libevcom
OUTPUT_A=$(NAME).a
all: $(OUTPUT_A) test/test test/echo
$(OUTPUT_A): $(OBJ)
$(AR) cru $(OUTPUT_A) $(OBJ)
$(RANLIB) $(OUTPUT_A)
.c.o:
$(CC) -c ${CFLAGS} $<
${OBJ}: ${DEP}
FAIL=ruby -e 'puts "\033[1;31m FAIL\033[m"'
PASS=ruby -e 'puts "\033[1;32m PASS\033[m"'
test: test/test test/echo test/timeout.rb
@echo test.c
@test/test > /dev/null && $(PASS) || $(FAIL)
@echo timeout.rb
@test/timeout.rb
test/test: test/test.c $(OUTPUT_A)
$(CC) $(LDFLAGS) $(CFLAGS) -o $@ test/test.c $(OUTPUT_A)
test/echo: test/echo.c $(OUTPUT_A)
$(CC) $(LDFLAGS) $(CFLAGS) -o $@ test/echo.c $(OUTPUT_A)
send_states.png: send_states.dot
dot -Tpng -o send_states.png send_states.dot
recv_states.png: recv_states.dot
dot -Tpng -o recv_states.png recv_states.dot
clean:
rm -rf test/test test/echo
rm -f $(OUTPUT_A) *.o
.PHONY: all clean test

1589
deps/evcom/evcom.c

File diff suppressed because it is too large

260
deps/evcom/evcom.h

@ -1,260 +0,0 @@
/* Copyright (c) 2008,2009 Ryan Dahl
*
* evcom_queue comes from Nginx, ngx_queue.h
* Copyright (C) 2002-2009 Igor Sysoev
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <netdb.h>
#include <ev.h>
#include <stddef.h> /* offsetof() */
#ifndef evcom_h
#define evcom_h
#ifdef __cplusplus
extern "C" {
#endif
#ifndef EVCOM_HAVE_GNUTLS
# define EVCOM_HAVE_GNUTLS 0
#endif
#if EVCOM_HAVE_GNUTLS
# include <gnutls/gnutls.h>
#endif
/* The maximum evcom_stream will try to read in one callback */
#ifndef EVCOM_CHUNKSIZE
# define EVCOM_CHUNKSIZE (8*1024)
#endif
/* flags for stream and server */
#define EVCOM_ATTACHED 0x0001
#define EVCOM_LISTENING 0x0002
#define EVCOM_CONNECTED 0x0004
#define EVCOM_SECURE 0x0008
#define EVCOM_DUPLEX 0x0010
#define EVCOM_GOT_CLOSE 0x0020
#define EVCOM_PAUSED 0x0040
#define EVCOM_READABLE 0x0080
#define EVCOM_WRITABLE 0x0100
#define EVCOM_TOO_MANY_CONN 0x0200
enum evcom_stream_state { EVCOM_INITIALIZED
, EVCOM_CONNECTING
, EVCOM_CONNECTED_RW /* read write */
, EVCOM_CONNECTED_RO /* read only */
, EVCOM_CONNECTED_WO /* write only */
, EVCOM_CLOSING
, EVCOM_CLOSED
};
typedef struct evcom_queue {
struct evcom_queue *prev;
struct evcom_queue *next;
} evcom_queue;
typedef struct evcom_buf {
/* public */
char *base;
size_t len;
void (*release) (struct evcom_buf *); /* called when oi is done with the object */
void *data;
/* private */
size_t written;
evcom_queue queue;
} evcom_buf;
#if EV_MULTIPLICITY
# define EVCOM_LOOP struct ev_loop *loop;
#else
# define EVCOM_LOOP
#endif
#define EVCOM_DESCRIPTOR(type) \
/* private */ unsigned int flags; \
/* private */ int (*action) (struct evcom_descriptor*); \
/* read-only */ int errorno; \
/* read-only */ int fd; \
/* read-only */ EVCOM_LOOP \
/* public */ void *data; \
/* public */ void (*on_close) (struct type*);
/* abstract base class */
typedef struct evcom_descriptor {
EVCOM_DESCRIPTOR(evcom_descriptor)
} evcom_descriptor;
typedef struct evcom_reader {
EVCOM_DESCRIPTOR(evcom_reader)
ev_io read_watcher; /* private */
void (*on_read) (struct evcom_reader*, const void* buf, size_t len); /* public */
} evcom_reader;
typedef struct evcom_writer {
EVCOM_DESCRIPTOR(evcom_writer)
ev_io write_watcher; /* private */
evcom_queue out; /* private */
} evcom_writer;
typedef struct evcom_stream {
/* PRIVATE */
EVCOM_LOOP
int errorno;
unsigned int flags;
evcom_queue out;
ev_io read_watcher;
ev_io write_watcher;
int (*send_action) (struct evcom_stream*);
int (*recv_action) (struct evcom_stream*);
ev_timer timeout_watcher;
#if EVCOM_HAVE_GNUTLS
gnutls_session_t session;
#endif
/* READ-ONLY */
int recvfd;
int sendfd;
struct evcom_server *server;
#if EVCOM_HAVE_GNUTLS
int gnutls_errorno;
#endif
/* PUBLIC */
void (*on_connect) (struct evcom_stream *);
void (*on_timeout) (struct evcom_stream *);
void (*on_read) (struct evcom_stream *, const void* buf, size_t len);
void (*on_drain) (struct evcom_stream *);
void (*on_close) (struct evcom_stream *);
void *data;
} evcom_stream;
typedef struct evcom_server {
EVCOM_DESCRIPTOR(evcom_server)
/* PRIVATE */
ev_io watcher;
/* PUBLIC */
struct evcom_stream*
(*on_connection)(struct evcom_server *, struct sockaddr *remote_addr);
} evcom_server;
/* Highly recommended to ignore SIGPIPE! */
void evcom_ignore_sigpipe (void);
void evcom_reader_init (evcom_reader*);
void evcom_reader_set (evcom_reader*, int fd);
void evcom_reader_attach (EV_P_ evcom_reader*);
void evcom_reader_detach (evcom_reader*);
void evcom_reader_close (evcom_reader*);
void evcom_writer_init (evcom_writer*);
void evcom_writer_set (evcom_writer*, int fd);
void evcom_writer_attach (EV_P_ evcom_writer*);
void evcom_writer_detach (evcom_writer*);
void evcom_writer_write (evcom_writer*, const char *str, size_t len);
void evcom_writer_close (evcom_writer*);
void evcom_server_init (evcom_server *);
int evcom_server_listen (evcom_server *, struct sockaddr *address, int backlog);
void evcom_server_attach (EV_P_ evcom_server *);
void evcom_server_detach (evcom_server *);
void evcom_server_close (evcom_server *);
void evcom_stream_init (evcom_stream *);
int evcom_stream_pair (evcom_stream *a, evcom_stream *b);
int evcom_stream_connect (evcom_stream *, struct sockaddr *address);
void evcom_stream_assign_fds (evcom_stream *, int recvfd, int sendfd);
void evcom_stream_attach (EV_P_ evcom_stream *);
void evcom_stream_detach (evcom_stream *);
void evcom_stream_read_resume (evcom_stream *);
void evcom_stream_read_pause (evcom_stream *);
void evcom_stream_reset_timeout (evcom_stream *, float timeout);
void evcom_stream_set_no_delay (evcom_stream *, int no_delay);
ssize_t evcom_stream_write (evcom_stream *, const char *str, size_t len);
/* Once the write buffer is drained, evcom_stream_close will shutdown the
* writing end of the stream and will close the read end once the server
* replies with an EOF.
*/
void evcom_stream_close (evcom_stream *);
/* Will not wait for the write queue to complete. Closes both directions */
void evcom_stream_force_close (evcom_stream *);
#if EVCOM_HAVE_GNUTLS
/* Tells the stream to use transport layer security (SSL). evcom_stream does
* not want to make any decisions about security requirements, so the
* majoirty of GnuTLS configuration is left to the user. Only the transport
* layer of GnuTLS is controlled by evcom_stream. That is, do not use
* gnutls_transport_* functions. Do use the rest of GnuTLS's API.
*/
void evcom_stream_set_secure_session (evcom_stream *, gnutls_session_t);
#endif
enum evcom_stream_state evcom_stream_state (evcom_stream *stream);
evcom_buf* evcom_buf_new (const char* base, size_t len);
evcom_buf* evcom_buf_new2 (size_t len);
EV_INLINE void
evcom_queue_init (evcom_queue *q)
{
q->prev = q;
q->next = q;
}
EV_INLINE void
evcom_queue_insert_head (evcom_queue *h, evcom_queue *x)
{
(x)->next = (h)->next;
(x)->next->prev = x;
(x)->prev = h;
(h)->next = x;
}
EV_INLINE void
evcom_queue_remove (evcom_queue *x)
{
(x)->next->prev = (x)->prev;
(x)->prev->next = (x)->next;
#ifndef NDEBUG
(x)->prev = NULL;
(x)->next = NULL;
#endif
}
#define evcom_queue_empty(h) (h == (h)->prev)
#define evcom_queue_head(h) (h)->next
#define evcom_queue_last(h) (h)->prev
#define evcom_queue_data(q, type, link) \
(type *) ((unsigned char *) q - offsetof(type, link))
#ifdef __cplusplus
}
#endif
#endif /* evcom_h */

37
deps/evcom/recv_states.dot

@ -1,37 +0,0 @@
strict digraph recv_states {
start [peripheries=2];
end [peripheries=2];
handshake;
recv_data;
wait_for_resume;
wait_for_close;
close_one;
close_both;
node [label="", shape="box", height=0.1, width=0.1];
close;
start -> handshake [label="tls"];
start -> recv_data;
handshake -> close [label="error"];
handshake -> recv_data;
recv_data -> handshake [label="rehandshake"];
recv_data -> wait_for_resume [label="pause"];
recv_data -> wait_for_close [label="eof"];
recv_data -> close [label="error"];
wait_for_resume -> recv_data;
wait_for_close -> close;
close -> close_one [label="duplex"];
close -> close_both;
close_one -> end;
close_both -> end;
}

65
deps/evcom/send_states.dot

@ -1,65 +0,0 @@
strict digraph send_states {
start [peripheries=2];
end [peripheries=2];
connection_established;
handshake;
send_data;
shutdown;
gnutls_bye;
close_one;
close_both;
wait_for_connect;
wait_for_buf;
wait_for_eof;
node [label="", shape="box", height=0.1, width=0.1];
close;
drain;
hangup;
hangup_unsecure;
start -> wait_for_connect [label="duplex"];
start -> connection_established;
wait_for_connect -> connection_established;
wait_for_connect -> close [label="error"];
connection_established -> handshake [label="tls"];
connection_established -> send_data;
handshake -> close [label="error"];
handshake -> send_data;
send_data -> close [label="error"];
send_data -> drain [label="drain"];
drain -> wait_for_buf;
drain -> hangup [label="got_close"];
wait_for_buf -> send_data;
wait_for_buf -> drain [label="empty_buf"];
hangup -> gnutls_bye [label="tls"];
hangup -> hangup_unsecure;
gnutls_bye -> wait_for_eof;
gnutls_bye -> close [label="error"];
hangup_unsecure -> shutdown [label="duplex"];
hangup_unsecure -> close_one;
shutdown -> wait_for_eof;
shutdown -> close [label="error"];
wait_for_eof -> close_one;
close_one -> wait_for_eof [label="readable"];
close -> close_both;
close -> close_one [label="duplex"];
close_both -> end;
close_one -> end;
}

100
deps/evcom/test/echo.c

@ -1,100 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <ev.h>
#include <evcom.h>
#if EVCOM_HAVE_GNUTLS
# include <gnutls/gnutls.h>
#endif
#define HOST "127.0.0.1"
#define SOCKFILE "/tmp/oi.sock"
#define PORT 5000
static int nconnections;
static void
on_peer_close (evcom_stream *stream)
{
assert(stream->errorno == 0);
//printf("server connection closed\n");
free(stream);
}
static void
on_peer_timeout (evcom_stream *stream)
{
assert(stream);
fprintf(stderr, "peer connection timeout\n");
assert(0);
}
// timeout must match the timeout in timeout.rb
#define TIMEOUT 5.0
static void
on_peer_read (evcom_stream *stream, const void *base, size_t len)
{
if(len == 0) return;
evcom_stream_write(stream, base, len);
}
static evcom_stream*
on_server_connection (evcom_server *server, struct sockaddr *addr)
{
assert(server);
assert(addr);
evcom_stream *stream = malloc(sizeof(evcom_stream));
evcom_stream_init(stream);
stream->on_read = on_peer_read;
stream->on_close = on_peer_close;
stream->on_timeout = on_peer_timeout;
evcom_stream_reset_timeout(stream, TIMEOUT);
nconnections++;
//printf("on server connection\n");
return stream;
}
int
main (void)
{
int r;
evcom_server server;
//printf("sizeof(evcom_server): %d\n", sizeof(evcom_server));
//printf("sizeof(evcom_stream): %d\n", sizeof(evcom_stream));
evcom_server_init(&server);
server.on_connection = on_server_connection;
struct sockaddr_in address;
memset(&address, 0, sizeof(struct sockaddr_in));
address.sin_family = AF_INET;
address.sin_port = htons(PORT);
address.sin_addr.s_addr = INADDR_ANY;
r = evcom_server_listen(&server, (struct sockaddr*)&address, 10);
assert(r == 0);
evcom_server_attach(EV_DEFAULT_ &server);
ev_loop(EV_DEFAULT_ 0);
return 0;
}

892
deps/evcom/test/test.c

@ -1,892 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <ev.h>
#include <evcom.h>
#if EVCOM_HAVE_GNUTLS
# include <gnutls/gnutls.h>
#endif
#undef MAX
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#undef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MARK_PROGRESS(c,cur,max) \
if (cur % (MAX(max,50)/50) == 0) write(STDERR_FILENO, c, 1)
#define SOCKFILE "/tmp/oi.sock"
#define PORT 5000
static evcom_server server;
static int nconnections;
static int use_tls;
static int got_server_close;
static void
common_on_server_close (evcom_server *s)
{
printf("server on_close\n");
assert(s == &server);
assert(s->errorno == 0);
got_server_close = 1;
evcom_server_detach(s);
}
static void
common_on_peer_close (evcom_stream *stream)
{
assert(EVCOM_CLOSED == evcom_stream_state(stream));
assert(stream->errorno == 0);
printf("server connection closed\n");
#if EVCOM_HAVE_GNUTLS
assert(stream->gnutls_errorno == 0);
if (use_tls) gnutls_deinit(stream->session);
#endif
evcom_stream_detach(stream);
free(stream);
}
static void
common_on_client_timeout (evcom_stream *stream)
{
assert(stream);
printf("client connection timeout\n");
}
static void
common_on_peer_timeout (evcom_stream *stream)
{
assert(stream);
fprintf(stderr, "peer connection timeout\n");
assert(0);
}
#if EVCOM_HAVE_GNUTLS
#define DH_BITS 768
static gnutls_anon_server_credentials_t server_credentials;
const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 };
static gnutls_dh_params_t dh_params;
void anon_tls_server (evcom_stream *stream)
{
gnutls_session_t session;
stream->data = session;
int r = gnutls_init(&session, GNUTLS_SERVER);
assert(r == 0);
gnutls_set_default_priority(session);
gnutls_kx_set_priority (session, kx_prio);
gnutls_credentials_set(session, GNUTLS_CRD_ANON, server_credentials);
gnutls_dh_set_prime_bits(session, DH_BITS);
evcom_stream_set_secure_session(stream, session);
}
void anon_tls_client (evcom_stream *stream)
{
gnutls_session_t client_session;
gnutls_anon_client_credentials_t client_credentials;
gnutls_anon_allocate_client_credentials (&client_credentials);
gnutls_init(&client_session, GNUTLS_CLIENT);
gnutls_set_default_priority(client_session);
gnutls_kx_set_priority(client_session, kx_prio);
/* Need to enable anonymous KX specifically. */
gnutls_credentials_set(client_session, GNUTLS_CRD_ANON, client_credentials);
evcom_stream_set_secure_session(stream, client_session);
assert(stream->flags & EVCOM_SECURE);
}
#endif // EVCOM_HAVE_GNUTLS
#define PING "PING"
#define PONG "PONG"
#define EXCHANGES 500
#define PINGPONG_TIMEOUT 5.0
static int successful_ping_count;
static void
pingpong_on_peer_read (evcom_stream *stream, const void *base, size_t len)
{
if (len == 0) {
evcom_stream_close(stream);
return;
}
char buf[2000];
strncpy(buf, base, len);
buf[len] = 0;
printf("server got message: %s\n", buf);
evcom_stream_write(stream, PONG, sizeof PONG);
}
static void
pingpong_on_client_close (evcom_stream *stream)
{
assert(EVCOM_CLOSED == evcom_stream_state(stream));
assert(stream);
printf("client connection closed\n");
evcom_server_close(&server);
evcom_stream_detach(stream);
}
static evcom_stream*
pingpong_on_server_connection (evcom_server *_server, struct sockaddr *addr)
{
assert(_server == &server);
assert(addr);
evcom_stream *stream = malloc(sizeof(evcom_stream));
evcom_stream_init(stream);
stream->on_read = pingpong_on_peer_read;
stream->on_close = common_on_peer_close;
stream->on_timeout = common_on_peer_timeout;
evcom_stream_reset_timeout(stream, PINGPONG_TIMEOUT);
assert(EVCOM_INITIALIZED == evcom_stream_state(stream));
nconnections++;
#if EVCOM_HAVE_GNUTLS
if (use_tls) anon_tls_server(stream);
#endif
printf("on server connection\n");
return stream;
}
static void
pingpong_on_client_connect (evcom_stream *stream)
{
printf("client connected. sending ping\n");
evcom_stream_write(stream, PING, sizeof PING);
assert(EVCOM_CONNECTED_RW == evcom_stream_state(stream));
}
static void
pingpong_on_client_read (evcom_stream *stream, const void *base, size_t len)
{
if(len == 0) {
evcom_stream_close(stream);
return;
}
assert(len = strlen(PONG));
char buf[len+1];
strncpy(buf, base, len);
buf[len] = 0;
printf("client got message: %s\n", buf);
assert(strcmp(buf, PONG) == 0);
if (++successful_ping_count > EXCHANGES) {
evcom_stream_close(stream);
return;
}
MARK_PROGRESS(".", successful_ping_count, EXCHANGES);
evcom_stream_write(stream, PING, sizeof PING);
}
int
pingpong (struct sockaddr *address)
{
int r;
evcom_stream client;
successful_ping_count = 0;
nconnections = 0;
got_server_close = 0;
evcom_server_init(&server);
server.on_connection = pingpong_on_server_connection;
server.on_close = common_on_server_close;
r = evcom_server_listen(&server, address, 10);
assert(r == 0);
evcom_server_attach(EV_DEFAULT_ &server);
evcom_stream_init(&client);
client.on_read = pingpong_on_client_read;
client.on_connect = pingpong_on_client_connect;
client.on_close = pingpong_on_client_close;
client.on_timeout = common_on_client_timeout;
evcom_stream_reset_timeout(&client, PINGPONG_TIMEOUT);
assert(EVCOM_INITIALIZED == evcom_stream_state(&client));
#if EVCOM_HAVE_GNUTLS
if (use_tls) anon_tls_client(&client);
#endif
r = evcom_stream_connect(&client, address);
assert(r == 0 && "problem connecting");
evcom_stream_attach(EV_DEFAULT_ &client);
ev_loop(EV_DEFAULT_ 0);
printf("successful_ping_count = %d\n", successful_ping_count);
assert(successful_ping_count == EXCHANGES + 1);
assert(nconnections == 1);
assert(got_server_close);
return 0;
}
#define NCONN 50
#define CONNINT_TIMEOUT 10.0
static void
send_bye_and_close(evcom_stream *stream, const void *base, size_t len)
{
assert(base);
assert(len == 0);
evcom_stream_write(stream, "BYE", 3);
printf("server wrote bye\n");
evcom_stream_close(stream);
}
static evcom_stream*
connint_on_connection(evcom_server *_server, struct sockaddr *addr)
{
assert(_server == &server);
assert(addr);
evcom_stream *stream = malloc(sizeof(evcom_stream));
evcom_stream_init(stream);
stream->on_read = send_bye_and_close;
stream->on_close = common_on_peer_close;
stream->on_timeout = common_on_peer_timeout;
evcom_stream_reset_timeout(stream, CONNINT_TIMEOUT);
#if EVCOM_HAVE_GNUTLS
if (use_tls) anon_tls_server(stream);
#endif
printf("on server connection\n");
return stream;
}
static void
connint_on_client_connect (evcom_stream *stream)
{
printf("on client connection\n");
evcom_stream_close(stream);
}
static void
connint_on_client_close (evcom_stream *stream)
{
evcom_stream_close(stream); // already closed, but it shouldn't crash if we try to do it again
printf("client connection closed\n");
MARK_PROGRESS(".", nconnections, NCONN);
if(++nconnections == NCONN) {
evcom_server_close(&server);
printf("closing server\n");
}
evcom_stream_detach(stream);
}
static void
connint_on_client_read (evcom_stream *stream, const void *base, size_t len)
{
if (len == 0) {
evcom_stream_close(stream);
return;
}
char buf[200000];
strncpy(buf, base, len);
buf[len] = 0;
printf("client got message: %s\n", buf);
assert(strcmp(buf, "BYE") == 0);
evcom_stream_close(stream);
}
int
connint (struct sockaddr *address)
{
int r;
nconnections = 0;
got_server_close = 0;
evcom_server_init(&server);
server.on_connection = connint_on_connection;
server.on_close = common_on_server_close;
evcom_server_listen(&server, address, 1000);
evcom_server_attach(EV_DEFAULT_ &server);
evcom_stream clients[NCONN];
int i;
for (i = 0; i < NCONN; i++) {
evcom_stream *client = &clients[i];
evcom_stream_init(client);
client->on_read = connint_on_client_read;
client->on_connect = connint_on_client_connect;
client->on_close = connint_on_client_close;
client->on_timeout = common_on_client_timeout;
evcom_stream_reset_timeout(client, CONNINT_TIMEOUT);
#if EVCOM_HAVE_GNUTLS
if (use_tls) anon_tls_client(client);
#endif
r = evcom_stream_connect(client, address);
assert(r == 0 && "problem connecting");
evcom_stream_attach(EV_DEFAULT_ client);
}
ev_loop(EV_DEFAULT_ 0);
assert(nconnections == NCONN);
assert(got_server_close);
return 0;
}
static evcom_reader reader;
static evcom_writer writer;
static int reader_got_close = 0;
static int reader_got_eof = 0;
static int reader_got_hello = 0;
static int reader_cnt = 0;
static int writer_got_close = 0;
#define PIPE_MSG "hello world"
#define PIPE_CNT 5000
static void
reader_read (evcom_reader *r, const void *str, size_t len)
{
assert(r == &reader);
if (len == 0) {
reader_got_eof = 1;
return;
}
assert(len == strlen(PIPE_MSG));
if (strncmp(str, PIPE_MSG, strlen(PIPE_MSG)) == 0) {
reader_got_hello = 1;
}
if (++reader_cnt < PIPE_CNT) {
MARK_PROGRESS(".", reader_cnt, PIPE_CNT);
evcom_writer_write(&writer, PIPE_MSG, strlen(PIPE_MSG));
} else {
evcom_writer_close(&writer);
}
}
static void
reader_close (evcom_reader *r)
{
assert(r == &reader);
reader_got_close = 1;
evcom_reader_detach(r);
}
static void
writer_close (evcom_writer *w)
{
assert(w == &writer);
writer_got_close = 1;
evcom_writer_detach(w);
}
int
pipe_stream (void)
{
reader_cnt = 0;
reader_got_close = 0;
reader_got_hello = 0;
reader_got_eof = 0;
writer_got_close = 0;
int pipefd[2];
int r = pipe(pipefd);
if (r < 0) {
perror("pipe()");
return -1;
}
evcom_reader_init(&reader);
reader.on_read = reader_read;
reader.on_close = reader_close;
evcom_reader_set(&reader, pipefd[0]);
evcom_reader_attach(EV_DEFAULT_ &reader);
evcom_writer_init(&writer);
writer.on_close = writer_close;
evcom_writer_set(&writer, pipefd[1]);
evcom_writer_attach(EV_DEFAULT_ &writer);
evcom_writer_write(&writer, PIPE_MSG, strlen(PIPE_MSG));
ev_loop(EV_DEFAULT_ 0);
assert(reader_got_close);
assert(reader_got_hello);
assert(reader_got_eof);
assert(writer_got_close);
assert(reader_cnt == PIPE_CNT);
return 0;
}
#define PAIR_PINGPONG_TIMEOUT 5000.0
#define PAIR_PINGPONG_EXCHANGES 50
static int a_got_close;
static int a_got_connect;
static int b_got_close;
static int b_got_connect;
static int pair_pingpong_cnt;
static evcom_stream a, b;
void a_connect (evcom_stream *stream)
{
assert(stream == &a);
a_got_connect = 1;
}
void a_close (evcom_stream *stream)
{
evcom_stream_detach(stream);
assert(stream == &a);
a_got_close = 1;
assert(stream->errorno == 0);
#if EVCOM_HAVE_GNUTLS
if (stream->gnutls_errorno) {
fprintf(stderr, "\nGNUTLS ERROR: %s\n", gnutls_strerror(stream->gnutls_errorno));
}
assert(stream->gnutls_errorno == 0);
if (use_tls) gnutls_deinit(stream->session);
#endif
}
void a_read (evcom_stream *stream, const void *buf, size_t len)
{
assert(stream == &a);
if (len == 0) return;
assert(len == strlen(PONG));
assert(strncmp(buf, PONG, strlen(PONG)) == 0);
if (++pair_pingpong_cnt < PAIR_PINGPONG_EXCHANGES) {
evcom_stream_write(&a, PING, strlen(PING));
} else if (pair_pingpong_cnt == PAIR_PINGPONG_EXCHANGES) {
evcom_stream_close(stream);
}
MARK_PROGRESS(".", pair_pingpong_cnt, PAIR_PINGPONG_EXCHANGES);
}
void b_connect (evcom_stream *stream)
{
assert(stream == &b);
b_got_connect = 1;
}
void b_close (evcom_stream *stream)
{
evcom_stream_detach(stream);
assert(stream == &b);
b_got_close = 1;
assert(stream->errorno == 0);
#if EVCOM_HAVE_GNUTLS
if (stream->gnutls_errorno) {
fprintf(stderr, "\nGNUTLS ERROR: %s\n", gnutls_strerror(stream->gnutls_errorno));
}
assert(stream->gnutls_errorno == 0);
if (use_tls) gnutls_deinit(stream->session);
#endif
}
void b_read (evcom_stream *stream, const void *buf, size_t len)
{
assert(stream == &b);
if (len == 0) {
evcom_stream_close(stream);
return;
}
assert(len == strlen(PING));
assert(strncmp(buf, PING, strlen(PING)) == 0);
evcom_stream_write(&b, PONG, strlen(PONG));
}
int
pair_pingpong (int use_pipe)
{
a_got_close = 0;
a_got_connect = 0;
b_got_close = 0;
b_got_connect = 0;
pair_pingpong_cnt = 0;
evcom_stream_init(&a);
a.on_close = a_close;
a.on_connect = a_connect;
a.on_read = a_read;
evcom_stream_reset_timeout(&a, PAIR_PINGPONG_TIMEOUT);
#if EVCOM_HAVE_GNUTLS
if (use_tls) anon_tls_client(&a);
#endif
evcom_stream_init(&b);
b.on_close = b_close;
b.on_connect = b_connect;
b.on_read = b_read;
evcom_stream_reset_timeout(&b, PAIR_PINGPONG_TIMEOUT);
#if EVCOM_HAVE_GNUTLS
if (use_tls) anon_tls_server(&b);
#endif
if (use_pipe) {
int pipeA[2], pipeB[2];
assert(0 == pipe(pipeA));
assert(0 == pipe(pipeB));
evcom_stream_assign_fds(&a, pipeA[0], pipeB[1]);
evcom_stream_assign_fds(&b, pipeB[0], pipeA[1]);
} else {
int r = evcom_stream_pair(&a, &b);
assert(r == 0);
}
evcom_stream_attach(EV_DEFAULT_ &a);
evcom_stream_attach(EV_DEFAULT_ &b);
evcom_stream_write(&a, PING, strlen(PING));
ev_loop(EV_DEFAULT_ 0);
assert(a_got_close);
assert(a_got_connect);
assert(b_got_close);
assert(b_got_connect);
assert(pair_pingpong_cnt == PAIR_PINGPONG_EXCHANGES);
return 0;
}
static void
free_stream (evcom_stream *stream)
{
assert(stream->errorno == 0);
free(stream);
}
#define ZERO_TIMEOUT 50.0
static size_t zero_to_write = 0;
static size_t zero_written = 0;
static size_t zero_read = 0;
static size_t zero_client_closed = 0;
static void
error_out (evcom_stream *stream)
{
assert(stream);
fprintf(stderr, "peer connection timeout\n");
assert(0);
}
static void
echo (evcom_stream *stream, const void *base, size_t len)
{
if(len == 0) {
fprintf(stderr, "close");
evcom_stream_close(stream);
} else {
evcom_stream_write(stream, base, len);
}
}
static evcom_stream*
make_echo_connection (evcom_server *server, struct sockaddr *addr)
{
assert(server);
assert(addr);
evcom_stream *stream = malloc(sizeof(evcom_stream));
evcom_stream_init(stream);
stream->on_read = echo;
stream->on_close = free_stream;
stream->on_timeout = error_out;
evcom_stream_reset_timeout(stream, ZERO_TIMEOUT);
#if EVCOM_HAVE_GNUTLS
if (use_tls) anon_tls_server(stream);
#endif
return stream;
}
static void
zero_start (evcom_stream *stream)
{
evcom_stream_write(stream, "0", 1);
zero_written++;
}
static void
zero_close (evcom_stream *stream)
{
assert(stream);
zero_client_closed = 1;
}
static void
zero_recv (evcom_stream *stream, const void *buf, size_t len)
{
MARK_PROGRESS("-", zero_read, zero_to_write);
zero_read += len;
size_t i;
for (i = 0; i < len; i++) {
assert(((char*)buf)[i] == '0');
}
for (i = 0; i < MIN(zero_to_write - zero_written, 90000); i++) {
evcom_stream_write(stream, "0", 1);
zero_written++;
MARK_PROGRESS(".", zero_written, zero_to_write);
if (zero_written == zero_to_write) {
fprintf(stderr, "CLOSE");
evcom_stream_close(stream);
}
}
if (len == 0) {
fprintf(stderr, "finish");
evcom_server_close(&server);
}
}
int
zero_stream (struct sockaddr *address, size_t to_write)
{
int r;
assert(to_write >= 1024); // should be kind of big at least.
zero_to_write = to_write;
got_server_close = 0;
zero_written = 0;
zero_read = 0;
zero_client_closed = 0;
evcom_server_init(&server);
server.on_connection = make_echo_connection;
server.on_close = common_on_server_close;
evcom_server_listen(&server, address, 1000);
evcom_server_attach(EV_DEFAULT_ &server);
evcom_stream client;
evcom_stream_init(&client);
client.on_read = zero_recv;
client.on_connect = zero_start;
client.on_close = zero_close;
client.on_timeout = error_out;
evcom_stream_reset_timeout(&client, ZERO_TIMEOUT);
#if EVCOM_HAVE_GNUTLS
if (use_tls) anon_tls_client(&client);
#endif
r = evcom_stream_connect(&client, address);
assert(r == 0 && "problem connecting");
evcom_stream_attach(EV_DEFAULT_ &client);
ev_loop(EV_DEFAULT_ 0);
assert(got_server_close);
assert(zero_written == zero_to_write);
assert(zero_read == zero_to_write);
assert(zero_client_closed) ;
return 0;
}
struct sockaddr *
create_unix_address (void)
{
struct stat tstat;
if (lstat(SOCKFILE, &tstat) == 0) {
assert(S_ISSOCK(tstat.st_mode));
unlink(SOCKFILE);
}
struct sockaddr_un *address = calloc(1, sizeof(struct sockaddr_un));
address->sun_family = AF_UNIX;
strcpy(address->sun_path, SOCKFILE);
return (struct sockaddr*)address;
}
void
free_unix_address (struct sockaddr *address)
{
struct stat tstat;
if (lstat(SOCKFILE, &tstat) == 0) {
assert(S_ISSOCK(tstat.st_mode));
unlink(SOCKFILE);
}
free(address);
}
int
main (void)
{
fprintf(stderr, "sizeof(evcom_server): %d\n", (int)sizeof(evcom_server));
fprintf(stderr, "sizeof(evcom_stream): %d\n", (int)sizeof(evcom_stream));
fprintf(stderr, "sizeof(evcom_reader): %d\n", (int)sizeof(evcom_reader));
fprintf(stderr, "sizeof(evcom_writer): %d\n", (int)sizeof(evcom_writer));
evcom_ignore_sigpipe();
#if EVCOM_HAVE_GNUTLS
gnutls_global_init();
gnutls_dh_params_init (&dh_params);
fsync((int)stderr);
gnutls_dh_params_generate2 (dh_params, DH_BITS);
gnutls_anon_allocate_server_credentials (&server_credentials);
gnutls_anon_set_server_dh_params (server_credentials, dh_params);
#endif
struct sockaddr_in tcp_address;
memset(&tcp_address, 0, sizeof(struct sockaddr_in));
tcp_address.sin_family = AF_INET;
tcp_address.sin_port = htons(PORT);
tcp_address.sin_addr.s_addr = INADDR_ANY;
use_tls = 0;
fprintf(stderr, "pair_pingpong use_pipe=1: ");
assert(pair_pingpong(1) == 0);
fprintf(stderr, "\n");
fprintf(stderr, "pair_pingpong use_pipe=0: ");
assert(pair_pingpong(0) == 0);
fprintf(stderr, "\n");
fprintf(stderr, "zero_stream tcp: ");
assert(zero_stream((struct sockaddr*)&tcp_address, 5*1024*1024) == 0);
fprintf(stderr, "\n");
fprintf(stderr, "pipe_stream: ");
assert(pipe_stream() == 0);
fprintf(stderr, "\n");
fprintf(stderr, "pingpong tcp: ");
assert(pingpong((struct sockaddr*)&tcp_address) == 0);
fprintf(stderr, "\n");
fprintf(stderr, "connint tcp: ");
assert(connint((struct sockaddr*)&tcp_address) == 0);
fprintf(stderr, "\n");
#if EVCOM_HAVE_GNUTLS
use_tls = 1;
fprintf(stderr, "zero_stream ssl: ");
assert(zero_stream((struct sockaddr*)&tcp_address, 50*1024) == 0);
fprintf(stderr, "\n");
fprintf(stderr, "pair_pingpong ssl use_pipe=1: ");
assert(pair_pingpong(1) == 0);
fprintf(stderr, "\n");
fprintf(stderr, "pair_pingpong ssl use_pipe=0: ");
assert(pair_pingpong(0) == 0);
fprintf(stderr, "\n");
fprintf(stderr, "pingpong ssl: ");
assert(pingpong((struct sockaddr*)&tcp_address) == 0);
fprintf(stderr, "\n");
fprintf(stderr, "connint ssl: ");
assert(connint((struct sockaddr*)&tcp_address) == 0);
fprintf(stderr, "\n");
#endif
struct sockaddr *unix_address;
use_tls = 0;
fprintf(stderr, "pingpong unix: ");
unix_address = create_unix_address();
assert(pingpong(unix_address) == 0);
free_unix_address(unix_address);
fprintf(stderr, "\n");
fprintf(stderr, "connint unix: ");
unix_address = create_unix_address();
assert(connint(unix_address) == 0);
free_unix_address(unix_address);
fprintf(stderr, "\n");
#if EVCOM_HAVE_GNUTLS
use_tls = 1;
fprintf(stderr, "pingpong unix ssl: ");
unix_address = create_unix_address();
assert(pingpong(unix_address) == 0);
free_unix_address(unix_address);
fprintf(stderr, "\n");
fprintf(stderr, "connint unix ssl: ");
unix_address = create_unix_address();
assert(connint(unix_address) == 0);
free_unix_address(unix_address);
fprintf(stderr, "\n");
#endif
return 0;
}

98
deps/evcom/test/timeout.rb

@ -1,98 +0,0 @@
#!/usr/bin/env ruby
require 'socket'
def test(description)
pid = fork do
exec(File.dirname(__FILE__) + "/echo")
end
puts "#{description}: "
begin
sleep 0.5 # give time for the server to start
yield(pid)
rescue
puts "\033[1;31mFAIL\033[m"
raise $!
ensure
`kill -9 #{pid}`
end
puts "\033[1;32mPASS\033[m"
end
test("make sure echo server works") do
socket = TCPSocket.open("localhost", 5000)
w = socket.write("hello");
raise "error" unless w == 5
got = socket.recv(5);
raise "error" unless got == "hello"
socket.close
end
test("doing nothing should not timeout the server") do |pid|
10.times do
print "."
STDOUT.flush
if Process.waitpid(pid, Process::WNOHANG)
raise "server died when it shouldn't have"
end
sleep 1
end
puts ""
end
test("connecting and doing nothing to should timeout in 5 seconds") do |pid|
socket = TCPSocket.open("localhost", 5000)
i = 0
10.times do
print "."
STDOUT.flush
break if Process.waitpid(pid, Process::WNOHANG)
sleep 1
i+=1
end
puts ""
raise "died too soon (after #{i} seconds)" if i < 5
raise "died too late (after #{i} seconds)" if i > 6
end
test("connecting and writing once to should timeout in 5 seconds") do |pid|
socket = TCPSocket.open("localhost", 5000)
w = socket.write("hello");
raise "error" unless w == 5
i = 0
10.times do
print "."
STDOUT.flush
break if Process.waitpid(pid, Process::WNOHANG)
sleep 1
i+=1
end
puts ""
raise "died too soon (after #{i} seconds)" if i < 5
raise "died too late (after #{i} seconds)" if i > 6
end
test("connecting waiting 3, writing once to should timeout in 8 seconds") do |pid|
socket = TCPSocket.open("localhost", 5000)
sleep 3
w = socket.write("hello");
raise "error" unless w == 5
i = 0
10.times do
print "."
STDOUT.flush
break if Process.waitpid(pid, Process::WNOHANG)
sleep 1
i+=1
end
puts ""
raise "died too soon (after #{i} seconds)" if i < 5
raise "died too late (after #{i} seconds)" if i > 6
end

641
lib/http_old.js

@ -1,641 +0,0 @@
var sys = require('sys');
var events = require('events');
// FIXME: The TCP binding isn't actually used here, but it needs to be
// loaded before the http binding.
process.binding('tcp');
var http = process.binding('http');
var CRLF = "\r\n";
var STATUS_CODES = exports.STATUS_CODES = {
100 : 'Continue',
101 : 'Switching Protocols',
200 : 'OK',
201 : 'Created',
202 : 'Accepted',
203 : 'Non-Authoritative Information',
204 : 'No Content',
205 : 'Reset Content',
206 : 'Partial Content',
300 : 'Multiple Choices',
301 : 'Moved Permanently',
302 : 'Moved Temporarily',
303 : 'See Other',
304 : 'Not Modified',
305 : 'Use Proxy',
400 : 'Bad Request',
401 : 'Unauthorized',
402 : 'Payment Required',
403 : 'Forbidden',
404 : 'Not Found',
405 : 'Method Not Allowed',
406 : 'Not Acceptable',
407 : 'Proxy Authentication Required',
408 : 'Request Time-out',
409 : 'Conflict',
410 : 'Gone',
411 : 'Length Required',
412 : 'Precondition Failed',
413 : 'Request Entity Too Large',
414 : 'Request-URI Too Large',
415 : 'Unsupported Media Type',
500 : 'Internal Server Error',
501 : 'Not Implemented',
502 : 'Bad Gateway',
503 : 'Service Unavailable',
504 : 'Gateway Time-out',
505 : 'HTTP Version not supported'
};
var connection_expression = /Connection/i;
var transfer_encoding_expression = /Transfer-Encoding/i;
var close_expression = /close/i;
var chunk_expression = /chunk/i;
var content_length_expression = /Content-Length/i;
/* Abstract base class for ServerRequest and ClientResponse. */
function IncomingMessage (connection) {
events.EventEmitter.call(this);
this.connection = connection;
this.httpVersion = null;
this.headers = {};
// request (server) only
this.url = "";
this.method = null;
// response (client) only
this.statusCode = null;
this.client = this.connection;
}
sys.inherits(IncomingMessage, events.EventEmitter);
exports.IncomingMessage = IncomingMessage;
IncomingMessage.prototype._parseQueryString = function () {
throw new Error("_parseQueryString is deprecated. Use require(\"querystring\") to parse query strings.\n");
};
IncomingMessage.prototype.setBodyEncoding = function (enc) {
// TODO: Find a cleaner way of doing this.
this.connection.setEncoding(enc);
};
IncomingMessage.prototype.pause = function () {
this.connection.pause();
};
IncomingMessage.prototype.resume = function () {
this.connection.resume();
};
IncomingMessage.prototype._addHeaderLine = function (field, value) {
if (field in this.headers) {
// TODO Certain headers like 'Content-Type' should not be concatinated.
// See https://www.google.com/reader/view/?tab=my#overview-page
this.headers[field] += ", " + value;
} else {
this.headers[field] = value;
}
};
function OutgoingMessage (connection) {
events.EventEmitter.call(this, connection);
this.connection = connection;
this.output = [];
this.outputEncodings = [];
this.closeOnFinish = false;
this.chunked_encoding = false;
this.should_keep_alive = true;
this.use_chunked_encoding_by_default = true;
this.flushing = false;
this.headWritten = false;
this.finished = false;
}
sys.inherits(OutgoingMessage, events.EventEmitter);
exports.OutgoingMessage = OutgoingMessage;
OutgoingMessage.prototype._send = function (data, encoding) {
var length = this.output.length;
if (length === 0) {
this.output.push(data);
encoding = encoding || "ascii";
this.outputEncodings.push(encoding);
return;
}
var lastEncoding = this.outputEncodings[length-1];
var lastData = this.output[length-1];
if ((lastEncoding === encoding) ||
(!encoding && data.constructor === lastData.constructor)) {
if (lastData.constructor === String) {
this.output[length-1] = lastData + data;
} else {
this.output[length-1] = lastData.concat(data);
}
return;
}
this.output.push(data);
encoding = encoding || "ascii";
this.outputEncodings.push(encoding);
};
OutgoingMessage.prototype.sendHeaderLines = function (first_line, headers) {
var sent_connection_header = false;
var sent_content_length_header = false;
var sent_transfer_encoding_header = false;
// first_line in the case of request is: "GET /index.html HTTP/1.1\r\n"
// in the case of response it is: "HTTP/1.1 200 OK\r\n"
var message_header = first_line;
var field, value;
for (var i in headers) {
if (headers[i] instanceof Array) {
field = headers[i][0];
value = headers[i][1];
} else {
if (!headers.hasOwnProperty(i)) continue;
field = i;
value = headers[i];
}
message_header += field + ": " + value + CRLF;
if (connection_expression.test(field)) {
sent_connection_header = true;
if (close_expression.test(value)) this.closeOnFinish = true;
} else if (transfer_encoding_expression.test(field)) {
sent_transfer_encoding_header = true;
if (chunk_expression.test(value)) this.chunked_encoding = true;
} else if (content_length_expression.test(field)) {
sent_content_length_header = true;
}
}
// keep-alive logic
if (sent_connection_header == false) {
if (this.should_keep_alive &&
(sent_content_length_header || this.use_chunked_encoding_by_default)) {
message_header += "Connection: keep-alive\r\n";
} else {
this.closeOnFinish = true;
message_header += "Connection: close\r\n";
}
}
if (sent_content_length_header == false && sent_transfer_encoding_header == false) {
if (this.use_chunked_encoding_by_default) {
message_header += "Transfer-Encoding: chunked\r\n";
this.chunked_encoding = true;
}
else {
this.closeOnFinish = true;
}
}
message_header += CRLF;
this._send(message_header);
// wait until the first body chunk, or close(), is sent to flush.
};
OutgoingMessage.prototype.sendBody = function () {
throw new Error("sendBody() has been renamed to write(). " +
"The 'body' event has been renamed to 'data' and " +
"the 'complete' event has been renamed to 'end'.");
};
OutgoingMessage.prototype.write = function (chunk, encoding) {
if ( (this instanceof ServerResponse) && !this.headWritten) {
throw new Error("writeHead() must be called before write()")
}
encoding = encoding || "ascii";
if (this.chunked_encoding) {
this._send(process._byteLength(chunk, encoding).toString(16));
this._send(CRLF);
this._send(chunk, encoding);
this._send(CRLF);
} else {
this._send(chunk, encoding);
}
if (this.flushing) {
this.flush();
} else {
this.flushing = true;
}
};
OutgoingMessage.prototype.flush = function () {
this.emit("flush");
};
OutgoingMessage.prototype.finish = function () {
throw new Error("finish() has been renamed to close().");
};
OutgoingMessage.prototype.close = function () {
if (this.chunked_encoding) this._send("0\r\n\r\n"); // last chunk
this.finished = true;
this.flush();
};
function ServerResponse (req) {
OutgoingMessage.call(this, req.connection);
if (req.httpVersionMajor < 1 || req.httpVersionMinor < 1) {
this.use_chunked_encoding_by_default = false;
this.should_keep_alive = false;
}
}
sys.inherits(ServerResponse, OutgoingMessage);
exports.ServerResponse = ServerResponse;
ServerResponse.prototype.writeHead = function (statusCode) {
var reasonPhrase, headers, headerIndex;
if (typeof arguments[1] == 'string') {
reasonPhrase = arguments[1];
headerIndex = 2;
} else {
reasonPhrase = STATUS_CODES[statusCode] || "unknown";
headerIndex = 1;
}
if (typeof arguments[headerIndex] == 'object') {
headers = arguments[headerIndex];
} else {
headers = {};
}
var status_line = "HTTP/1.1 " + statusCode.toString() + " "
+ reasonPhrase + CRLF;
this.sendHeaderLines(status_line, headers);
this.headWritten = true;
};
// TODO eventually remove sendHeader(), writeHeader()
ServerResponse.prototype.sendHeader = ServerResponse.prototype.writeHead;
ServerResponse.prototype.writeHeader = ServerResponse.prototype.writeHead;
function ClientRequest (connection, method, url, headers) {
OutgoingMessage.call(this, connection);
this.should_keep_alive = false;
if (method === "GET" || method === "HEAD") {
this.use_chunked_encoding_by_default = false;
} else {
this.use_chunked_encoding_by_default = true;
}
this.closeOnFinish = true;
this.sendHeaderLines(method + " " + url + " HTTP/1.1\r\n", headers);
}
sys.inherits(ClientRequest, OutgoingMessage);
exports.ClientRequest = ClientRequest;
ClientRequest.prototype.finish = function () {
throw new Error( "finish() has been renamed to close() and no longer takes "
+ "a response handler as an argument. Manually add a 'response' listener "
+ "to the request object."
);
};
ClientRequest.prototype.close = function () {
if (arguments.length > 0) {
throw new Error( "ClientRequest.prototype.close does not take any arguments. "
+ "Add a response listener manually to the request object."
);
}
OutgoingMessage.prototype.close.call(this);
};
function createIncomingMessageStream (connection, incoming_listener) {
var incoming, field, value;
connection.addListener("messageBegin", function () {
incoming = new IncomingMessage(connection);
field = null;
value = null;
});
// Only servers will get URL events.
connection.addListener("url", function (data) {
incoming.url += data;
});
connection.addListener("headerField", function (data) {
if (value) {
incoming._addHeaderLine(field, value);
field = null;
value = null;
}
if (field) {
field += data;
} else {
field = data;
}
});
connection.addListener("headerValue", function (data) {
if (value) {
value += data;
} else {
value = data;
}
});
connection.addListener("headerComplete", function (info) {
if (field && value) {
incoming._addHeaderLine(field, value);
}
incoming.httpVersion = info.httpVersion;
incoming.httpVersionMajor = info.versionMajor;
incoming.httpVersionMinor = info.versionMinor;
if (info.method) {
// server only
incoming.method = info.method;
} else {
// client only
incoming.statusCode = info.statusCode;
}
incoming_listener(incoming, info.should_keep_alive);
});
connection.addListener("body", function (chunk) {
incoming.emit('data', chunk);
});
connection.addListener("messageComplete", function () {
incoming.emit('end');
});
}
/* Returns true if the message queue is finished and the connection
* should be closed. */
function flushMessageQueue (connection, queue) {
while (queue[0]) {
var message = queue[0];
while (message.output.length > 0) {
if (connection.readyState !== "open" && connection.readyState !== "writeOnly") {
return true;
}
var data = message.output.shift();
var encoding = message.outputEncodings.shift();
connection.write(data, encoding);
}
if (!message.finished) break;
message.emit("sent");
queue.shift();
if (message.closeOnFinish) return true;
}
return false;
}
exports.createServer = function (requestListener, options) {
var server = new http.Server();
//server.setOptions(options);
server.addListener("request", requestListener);
server.addListener("connection", connectionListener);
return server;
};
function connectionListener (connection) {
// An array of responses for each connection. In pipelined connections
// we need to keep track of the order they were sent.
var responses = [];
connection.resetParser();
// is this really needed?
connection.addListener("end", function () {
if (responses.length == 0) {
connection.close();
} else {
responses[responses.length-1].closeOnFinish = true;
}
});
createIncomingMessageStream(connection, function (incoming, should_keep_alive) {
var req = incoming;
var res = new ServerResponse(req);
res.should_keep_alive = should_keep_alive;
res.addListener("flush", function () {
if (flushMessageQueue(connection, responses)) {
connection.close();
}
});
responses.push(res);
connection.server.emit("request", req, res);
});
}
exports.createClient = function (port, host) {
var client = new http.Client();
var secure_credentials={ secure : false };
var requests = [];
var currentRequest;
client.tcpSetSecure = client.setSecure;
client.setSecure = function(format_type, ca_certs, crl_list, private_key, certificate) {
secure_credentials.secure = true;
secure_credentials.format_type = format_type;
secure_credentials.ca_certs = ca_certs;
secure_credentials.crl_list = crl_list;
secure_credentials.private_key = private_key;
secure_credentials.certificate = certificate;
}
client._reconnect = function () {
if (client.readyState != "opening") {
//sys.debug("HTTP CLIENT: reconnecting readyState = " + client.readyState);
client.connect(port, host);
if (secure_credentials.secure) {
client.tcpSetSecure(secure_credentials.format_type,
secure_credentials.ca_certs,
secure_credentials.crl_list,
secure_credentials.private_key,
secure_credentials.certificate);
}
}
};
client._pushRequest = function (req) {
req.addListener("flush", function () {
if (client.readyState == "closed") {
//sys.debug("HTTP CLIENT request flush. reconnect. readyState = " + client.readyState);
client._reconnect();
return;
}
//sys.debug("client flush readyState = " + client.readyState);
if (req == currentRequest) flushMessageQueue(client, [req]);
});
requests.push(req);
};
client.addListener("connect", function () {
client.resetParser();
currentRequest = requests.shift();
currentRequest.flush();
});
client.addListener("end", function () {
//sys.debug("client got end closing. readyState = " + client.readyState);
client.close();
});
client.addListener("close", function (had_error) {
if (had_error) {
client.emit("error");
return;
}
//sys.debug("HTTP CLIENT onClose. readyState = " + client.readyState);
// If there are more requests to handle, reconnect.
if (requests.length > 0) {
client._reconnect();
}
});
createIncomingMessageStream(client, function (res) {
//sys.debug("incoming response!");
res.addListener('end', function ( ) {
//sys.debug("request complete disconnecting. readyState = " + client.readyState);
client.close();
});
currentRequest.emit("response", res);
});
return client;
};
http.Client.prototype.get = function () {
throw new Error("client.get(...) is now client.request('GET', ...)");
};
http.Client.prototype.head = function () {
throw new Error("client.head(...) is now client.request('HEAD', ...)");
};
http.Client.prototype.post = function () {
throw new Error("client.post(...) is now client.request('POST', ...)");
};
http.Client.prototype.del = function () {
throw new Error("client.del(...) is now client.request('DELETE', ...)");
};
http.Client.prototype.put = function () {
throw new Error("client.put(...) is now client.request('PUT', ...)");
};
http.Client.prototype.request = function (method, url, headers) {
if (typeof(url) != "string") { // assume method was omitted, shift arguments
headers = url;
url = method;
method = null;
}
var req = new ClientRequest(this, method || "GET", url, headers);
this._pushRequest(req);
return req;
};
exports.cat = function (url, encoding_, headers_) {
var encoding = 'utf8',
headers = {},
callback = null;
// parse the arguments for the various options... very ugly
if (typeof(arguments[1]) == 'string') {
encoding = arguments[1];
if (typeof(arguments[2]) == 'object') {
headers = arguments[2];
if (typeof(arguments[3]) == 'function') callback = arguments[3];
} else {
if (typeof(arguments[2]) == 'function') callback = arguments[2];
}
} else {
// didn't specify encoding
if (typeof(arguments[1]) == 'object') {
headers = arguments[1];
callback = arguments[2];
} else {
callback = arguments[1];
}
}
var url = require("url").parse(url);
var hasHost = false;
for (var i in headers) {
if (i.toLowerCase() === "host") {
hasHost = true;
break;
}
}
if (!hasHost) headers["Host"] = url.hostname;
var content = "";
var client = exports.createClient(url.port || 80, url.hostname);
var req = client.request((url.pathname || "/")+(url.search || "")+(url.hash || ""), headers);
req.addListener('response', function (res) {
if (res.statusCode < 200 || res.statusCode >= 300) {
if (callback) callback(res.statusCode);
client.close();
return;
}
res.setBodyEncoding(encoding);
res.addListener('data', function (chunk) { content += chunk; });
res.addListener('end', function () {
if (callback) callback(null, content);
});
});
client.addListener("error", function (err) {
// todo an error should actually be passed here...
if (callback) callback(new Error('Connection error'));
});
req.close();
};

26
lib/tcp_old.js

@ -1,26 +0,0 @@
var tcp = process.binding('tcp');
var TLS_STATUS_CODES = {
1 : 'JS_GNUTLS_CERT_VALIDATED',
0 : 'JS_GNUTLS_CERT_UNDEFINED',
}
TLS_STATUS_CODES[-100] = 'JS_GNUTLS_CERT_SIGNER_NOT_FOUND';
TLS_STATUS_CODES[-101] = 'JS_GNUTLS_CERT_SIGNER_NOT_CA';
TLS_STATUS_CODES[-102] = 'JS_GNUTLS_CERT_INVALID';
TLS_STATUS_CODES[-103] = 'JS_GNUTLS_CERT_NOT_ACTIVATED';
TLS_STATUS_CODES[-104] = 'JS_GNUTLS_CERT_EXPIRED';
TLS_STATUS_CODES[-105] = 'JS_GNUTLS_CERT_REVOKED';
TLS_STATUS_CODES[-106] = 'JS_GNUTLS_CERT_DOES_NOT_MATCH_HOSTNAME';
exports.createServer = function (on_connection, options) {
var server = new tcp.Server();
server.addListener("connection", on_connection);
//server.setOptions(options);
return server;
};
exports.createConnection = function (port, host) {
var connection = new tcp.Connection();
connection.connect(port, host);
return connection;
};

30
src/node.cc

@ -19,13 +19,11 @@
#include <node_net2.h>
#include <node_events.h>
#include <node_cares.h>
#include <node_net.h>
#include <node_file.h>
#if 0
// not in use
# include <node_idle_watcher.h>
#endif
#include <node_http.h>
#include <node_http_parser.h>
#include <node_signal_watcher.h>
#include <node_stat_watcher.h>
@ -1516,29 +1514,6 @@ static Handle<Value> Binding(const Arguments& args) {
binding_cache->Set(module, exports);
}
} else if (!strcmp(*module_v, "http")) {
if (binding_cache->Has(module)) {
exports = binding_cache->Get(module)->ToObject();
} else {
// Warning: When calling requireBinding('http') from javascript then
// be sure that you call requireBinding('tcp') before it.
assert(binding_cache->Has(String::New("tcp")));
exports = Object::New();
HTTPServer::Initialize(exports);
HTTPConnection::Initialize(exports);
binding_cache->Set(module, exports);
}
} else if (!strcmp(*module_v, "tcp")) {
if (binding_cache->Has(module)) {
exports = binding_cache->Get(module)->ToObject();
} else {
exports = Object::New();
Server::Initialize(exports);
Connection::Initialize(exports);
binding_cache->Set(module, exports);
}
} else if (!strcmp(*module_v, "cares")) {
if (binding_cache->Has(module)) {
exports = binding_cache->Get(module)->ToObject();
@ -1643,7 +1618,6 @@ static Handle<Value> Binding(const Arguments& args) {
exports->Set(String::New("freelist"), String::New(native_freelist));
exports->Set(String::New("fs"), String::New(native_fs));
exports->Set(String::New("http"), String::New(native_http));
exports->Set(String::New("http_old"), String::New(native_http_old));
exports->Set(String::New("crypto"), String::New(native_crypto));
exports->Set(String::New("ini"), String::New(native_ini));
exports->Set(String::New("mjsunit"), String::New(native_mjsunit));
@ -1653,7 +1627,6 @@ static Handle<Value> Binding(const Arguments& args) {
exports->Set(String::New("repl"), String::New(native_repl));
exports->Set(String::New("sys"), String::New(native_sys));
exports->Set(String::New("tcp"), String::New(native_tcp));
exports->Set(String::New("tcp_old"), String::New(native_tcp_old));
exports->Set(String::New("uri"), String::New(native_uri));
exports->Set(String::New("url"), String::New(native_url));
exports->Set(String::New("utils"), String::New(native_utils));
@ -1896,9 +1869,6 @@ int main(int argc, char *argv[]) {
return 1;
}
// Ignore the SIGPIPE
evcom_ignore_sigpipe();
// Initialize the default ev loop.
#ifdef __sun
// TODO(Ryan) I'm experiencing abnormally high load using Solaris's

1
src/node.h

@ -5,7 +5,6 @@
#include <ev.h>
#include <eio.h>
#include <v8.h>
#include <evcom.h>
#include <sys/types.h> /* struct stat */
#include <sys/stat.h>

4
src/node_cares.cc

@ -4,6 +4,10 @@
#include <v8.h>
#include <ares.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/nameser.h>
#include <arpa/inet.h>

392
src/node_http.cc

@ -1,392 +0,0 @@
#include <node_http.h>
#include <assert.h>
#include <stdio.h>
#include <strings.h>
using namespace v8;
using namespace node;
Persistent<FunctionTemplate> HTTPConnection::client_constructor_template;
Persistent<FunctionTemplate> HTTPConnection::server_constructor_template;
static Persistent<String> method_symbol;
static Persistent<String> status_code_symbol;
static Persistent<String> http_version_symbol;
static Persistent<String> version_major_symbol;
static Persistent<String> version_minor_symbol;
static Persistent<String> should_keep_alive_symbol;
static Persistent<String> message_begin_symbol;
static Persistent<String> message_complete_symbol;
static Persistent<String> url_symbol;
static Persistent<String> query_string_symbol;
static Persistent<String> path_symbol;
static Persistent<String> fragment_symbol;
static Persistent<String> header_field_symbol;
static Persistent<String> header_value_symbol;
static Persistent<String> header_complete_symbol;
static Persistent<String> body_symbol;
static Persistent<String> end_symbol;
static Persistent<String> delete_sym;
static Persistent<String> get_sym;
static Persistent<String> head_sym;
static Persistent<String> post_sym;
static Persistent<String> put_sym;
static Persistent<String> connect_sym;
static Persistent<String> options_sym;
static Persistent<String> trace_sym;
static Persistent<String> copy_sym;
static Persistent<String> lock_sym;
static Persistent<String> mkcol_sym;
static Persistent<String> move_sym;
static Persistent<String> propfind_sym;
static Persistent<String> proppatch_sym;
static Persistent<String> unlock_sym;
static Persistent<String> unknown_method_sym;
static struct http_parser_settings settings;
void
HTTPConnection::Initialize (Handle<Object> target)
{
HandleScope scope;
Local<FunctionTemplate> t = FunctionTemplate::New(NewClient);
client_constructor_template = Persistent<FunctionTemplate>::New(t);
client_constructor_template->Inherit(Connection::constructor_template);
client_constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
client_constructor_template->SetClassName(String::NewSymbol("Client"));
NODE_SET_PROTOTYPE_METHOD(client_constructor_template, "resetParser", ResetParser);
target->Set(String::NewSymbol("Client"), client_constructor_template->GetFunction());
t = FunctionTemplate::New(NewServer);
server_constructor_template = Persistent<FunctionTemplate>::New(t);
server_constructor_template->Inherit(Connection::constructor_template);
server_constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
NODE_SET_PROTOTYPE_METHOD(server_constructor_template, "resetParser", ResetParser);
server_constructor_template->SetClassName(String::NewSymbol("ServerSideConnection"));
end_symbol = NODE_PSYMBOL("end");
settings.on_message_begin = on_message_begin;
settings.on_path = on_path;
settings.on_query_string = on_query_string;
settings.on_url = on_url;
settings.on_fragment = on_fragment;
settings.on_header_field = on_header_field;
settings.on_header_value = on_header_value;
settings.on_headers_complete = on_headers_complete;
settings.on_body = on_body;
settings.on_message_complete = on_message_complete;
}
Handle<Value>
HTTPConnection::NewClient (const Arguments& args)
{
HandleScope scope;
HTTPConnection *connection = new HTTPConnection(HTTP_RESPONSE);
connection->Wrap(args.This());
return args.This();
}
Handle<Value>
HTTPConnection::NewServer (const Arguments& args)
{
HandleScope scope;
HTTPConnection *connection = new HTTPConnection(HTTP_REQUEST);
connection->Wrap(args.This());
return args.This();
}
Handle<Value> HTTPConnection::ResetParser(const Arguments& args) {
HandleScope scope;
HTTPConnection *connection = ObjectWrap::Unwrap<HTTPConnection>(args.Holder());
connection->ResetParser();
return Undefined();
}
void
HTTPConnection::OnReceive (const void *buf, size_t len)
{
HandleScope scope;
assert(refs_);
size_t nparsed;
nparsed = http_parser_execute(&parser_, settings, static_cast<const char*>(buf), len);
if (nparsed != len) {
ForceClose();
}
}
void
HTTPConnection::OnEOF ()
{
HandleScope scope;
assert(refs_);
size_t nparsed;
nparsed = http_parser_execute(&parser_, settings, NULL, 0);
Emit(end_symbol, 0, NULL);
}
int
HTTPConnection::on_message_begin (http_parser *parser)
{
if (message_begin_symbol.IsEmpty()) {
method_symbol = NODE_PSYMBOL("method");
status_code_symbol = NODE_PSYMBOL("statusCode");
http_version_symbol = NODE_PSYMBOL("httpVersion");
version_major_symbol = NODE_PSYMBOL("versionMajor");
version_minor_symbol = NODE_PSYMBOL("versionMinor");
should_keep_alive_symbol = NODE_PSYMBOL("should_keep_alive");
message_begin_symbol = NODE_PSYMBOL("messageBegin");
message_complete_symbol = NODE_PSYMBOL("messageComplete");
url_symbol = NODE_PSYMBOL("url");
query_string_symbol = NODE_PSYMBOL("queryString");
path_symbol = NODE_PSYMBOL("path");
fragment_symbol = NODE_PSYMBOL("fragment");
header_field_symbol = NODE_PSYMBOL("headerField");
header_value_symbol = NODE_PSYMBOL("headerValue");
header_complete_symbol = NODE_PSYMBOL("headerComplete");
body_symbol = NODE_PSYMBOL("body");
delete_sym = NODE_PSYMBOL("DELETE");
get_sym = NODE_PSYMBOL("GET");
head_sym = NODE_PSYMBOL("HEAD");
post_sym = NODE_PSYMBOL("POST");
put_sym = NODE_PSYMBOL("PUT");
connect_sym = NODE_PSYMBOL("CONNECT");
options_sym = NODE_PSYMBOL("OPTIONS");
trace_sym = NODE_PSYMBOL("TRACE");
copy_sym = NODE_PSYMBOL("COPY");
lock_sym = NODE_PSYMBOL("LOCK");
mkcol_sym = NODE_PSYMBOL("MKCOL");
move_sym = NODE_PSYMBOL("MOVE");
propfind_sym = NODE_PSYMBOL("PROPFIND");
proppatch_sym = NODE_PSYMBOL("PROPPATCH");
unlock_sym = NODE_PSYMBOL("UNLOCK");
unknown_method_sym = NODE_PSYMBOL("UNKNOWN_METHOD");
}
HTTPConnection *connection = static_cast<HTTPConnection*> (parser->data);
assert(connection->refs_);
connection->Emit(message_begin_symbol, 0, NULL);
return 0;
}
int
HTTPConnection::on_message_complete (http_parser *parser)
{
HTTPConnection *connection = static_cast<HTTPConnection*> (parser->data);
assert(connection->refs_);
connection->Emit(message_complete_symbol, 0, NULL);
return 0;
}
int
HTTPConnection::on_url (http_parser *parser, const char *buf, size_t len)
{
HTTPConnection *connection = static_cast<HTTPConnection*>(parser->data);
assert(connection->refs_);
Local<Value> argv[1] = { String::New(buf, len) };
connection->Emit(url_symbol, 1, argv);
return 0;
}
int
HTTPConnection::on_query_string (http_parser *parser, const char *buf, size_t len)
{
HTTPConnection *connection = static_cast<HTTPConnection*>(parser->data);
assert(connection->refs_);
Local<Value> argv[1] = { String::New(buf, len) };
connection->Emit(query_string_symbol, 1, argv);
return 0;
}
int
HTTPConnection::on_path (http_parser *parser, const char *buf, size_t len)
{
HTTPConnection *connection = static_cast<HTTPConnection*>(parser->data);
assert(connection->refs_);
Local<Value> argv[1] = { String::New(buf, len) };
connection->Emit(path_symbol, 1, argv);
return 0;
}
int
HTTPConnection::on_fragment (http_parser *parser, const char *buf, size_t len)
{
HTTPConnection *connection = static_cast<HTTPConnection*>(parser->data);
assert(connection->refs_);
Local<Value> argv[1] = { String::New(buf, len) };
connection->Emit(fragment_symbol, 1, argv);
return 0;
}
const static char normalizer[] =
"\0------------------------------"
"-----------------0123456789-----"
"--abcdefghijklmnopqrstuvwxyz----"
"--abcdefghijklmnopqrstuvwxyz----"
"--------------------------------"
"--------------------------------"
"--------------------------------"
"--------------------------------";
int
HTTPConnection::on_header_field (http_parser *parser, const char *buf, size_t len)
{
HTTPConnection *connection = static_cast<HTTPConnection*>(parser->data);
assert(connection->refs_);
// NORMALIZE
size_t i;
char *nonconstbuf = (char*)buf; // FIXME
for (i = 0; i < len; i++) { nonconstbuf[i] = normalizer[buf[i]]; }
Local<Value> argv[1] = { String::New(buf, len) };
connection->Emit(header_field_symbol, 1, argv);
return 0;
}
int
HTTPConnection::on_header_value (http_parser *parser, const char *buf, size_t len)
{
HTTPConnection *connection = static_cast<HTTPConnection*>(parser->data);
assert(connection->refs_);
Local<Value> argv[1] = { String::New(buf, len) };
connection->Emit(header_value_symbol, 1, argv);
return 0;
}
static inline Persistent<String>
method_to_str(enum http_method m) {
switch (m) {
case HTTP_DELETE: return delete_sym;
case HTTP_GET: return get_sym;
case HTTP_HEAD: return head_sym;
case HTTP_POST: return post_sym;
case HTTP_PUT: return put_sym;
case HTTP_CONNECT: return connect_sym;
case HTTP_OPTIONS: return options_sym;
case HTTP_TRACE: return trace_sym;
case HTTP_COPY: return copy_sym;
case HTTP_LOCK: return lock_sym;
case HTTP_MKCOL: return mkcol_sym;
case HTTP_MOVE: return move_sym;
case HTTP_PROPFIND: return propfind_sym;
case HTTP_PROPPATCH: return proppatch_sym;
case HTTP_UNLOCK: return unlock_sym;
default: return unknown_method_sym;
}
}
int
HTTPConnection::on_headers_complete (http_parser *parser)
{
HTTPConnection *connection = static_cast<HTTPConnection*> (parser->data);
assert(connection->refs_);
Local<Object> message_info = Object::New();
// METHOD
if (connection->type_ == HTTP_REQUEST) {
message_info->Set(method_symbol, method_to_str(connection->parser_.method));
}
// STATUS
if (connection->type_ == HTTP_RESPONSE) {
message_info->Set(status_code_symbol,
Integer::New(connection->parser_.status_code));
}
// VERSION
char version[10];
snprintf( version
, 10
, "%d.%d"
, connection->parser_.http_major
, connection->parser_.http_minor
);
message_info->Set(http_version_symbol, String::New(version));
message_info->Set(version_major_symbol,
Integer::New(connection->parser_.http_major));
message_info->Set(version_minor_symbol,
Integer::New(connection->parser_.http_minor));
message_info->Set(should_keep_alive_symbol,
http_should_keep_alive(&connection->parser_) ? True() : False());
Local<Value> argv[1] = { message_info };
connection->Emit(header_complete_symbol, 1, argv);
return 0;
}
int
HTTPConnection::on_body (http_parser *parser, const char *buf, size_t len)
{
assert(len != 0);
HTTPConnection *connection = static_cast<HTTPConnection*> (parser->data);
assert(connection->refs_);
// TODO each message should have their encoding.
// don't look at the conneciton for encoding
Local<Value> data = Encode(buf, len, connection->encoding_);
connection->Emit(body_symbol, 1, &data);
return 0;
}
Persistent<FunctionTemplate> HTTPServer::constructor_template;
void
HTTPServer::Initialize (Handle<Object> target)
{
HandleScope scope;
Local<FunctionTemplate> t = FunctionTemplate::New(New);
constructor_template = Persistent<FunctionTemplate>::New(t);
constructor_template->Inherit(Server::constructor_template);
constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
constructor_template->SetClassName(String::NewSymbol("Server"));
target->Set(String::NewSymbol("Server"), constructor_template->GetFunction());
}
Handle<Value>
HTTPServer::New (const Arguments& args)
{
HandleScope scope;
HTTPServer *server = new HTTPServer();
server->Wrap(args.This());
return args.This();
}
Handle<FunctionTemplate>
HTTPServer::GetConnectionTemplate (void)
{
return HTTPConnection::server_constructor_template;
}
Connection*
HTTPServer::UnwrapConnection (Local<Object> connection)
{
HandleScope scope;
return ObjectWrap::Unwrap<HTTPConnection>(connection);
}

68
src/node_http.h

@ -1,68 +0,0 @@
#ifndef node_http_h
#define node_http_h
#include <node_net.h>
#include <v8.h>
#include <http_parser.h>
namespace node {
class HTTPConnection : public Connection {
public:
static void Initialize (v8::Handle<v8::Object> target);
static v8::Persistent<v8::FunctionTemplate> client_constructor_template;
static v8::Persistent<v8::FunctionTemplate> server_constructor_template;
protected:
static v8::Handle<v8::Value> NewClient (const v8::Arguments& args);
static v8::Handle<v8::Value> NewServer (const v8::Arguments& args);
static v8::Handle<v8::Value> ResetParser(const v8::Arguments& args);
HTTPConnection (enum http_parser_type t)
: Connection()
{
type_ = t;
ResetParser();
}
void ResetParser() {
http_parser_init (&parser_, type_);
parser_.data = this;
}
void OnReceive (const void *buf, size_t len);
void OnEOF ();
static int on_message_begin (http_parser *parser);
static int on_url (http_parser *parser, const char *at, size_t length);
static int on_query_string (http_parser *parser, const char *at, size_t length);
static int on_path (http_parser *parser, const char *at, size_t length);
static int on_fragment (http_parser *parser, const char *at, size_t length);
static int on_header_field (http_parser *parser, const char *buf, size_t len);
static int on_header_value (http_parser *parser, const char *buf, size_t len);
static int on_headers_complete (http_parser *parser);
static int on_body (http_parser *parser, const char *buf, size_t len);
static int on_message_complete (http_parser *parser);
enum http_parser_type type_;
http_parser parser_;
friend class HTTPServer;
};
class HTTPServer : public Server {
public:
static void Initialize (v8::Handle<v8::Object> target);
static v8::Persistent<v8::FunctionTemplate> constructor_template;
protected:
static v8::Handle<v8::Value> New (const v8::Arguments& args);
HTTPServer (void) : Server() {}
v8::Handle<v8::FunctionTemplate> GetConnectionTemplate (void);
Connection* UnwrapConnection (v8::Local<v8::Object> connection);
};
} // namespace node
#endif

1122
src/node_net.cc

File diff suppressed because it is too large

284
src/node_net.h

@ -1,284 +0,0 @@
// Copyright 2009 Ryan Dahl <ry@tinyclouds.org>
#ifndef SRC_NET_H_
#define SRC_NET_H_
#include <node.h>
#include <node_events.h>
#include <v8.h>
#include <evcom.h>
#if EVCOM_HAVE_GNUTLS
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#endif
namespace node {
class Server;
class Connection : public EventEmitter {
public:
static void Initialize(v8::Handle<v8::Object> target);
protected:
/* v8 interface */
static v8::Persistent<v8::FunctionTemplate> constructor_template;
static v8::Handle<v8::Value> New(const v8::Arguments& args);
static v8::Handle<v8::Value> Connect(const v8::Arguments& args);
static v8::Handle<v8::Value> Send(const v8::Arguments& args);
static v8::Handle<v8::Value> Write(const v8::Arguments& args);
static v8::Handle<v8::Value> SendUtf8(const v8::Arguments& args);
static v8::Handle<v8::Value> Close(const v8::Arguments& args);
static v8::Handle<v8::Value> ForceClose(const v8::Arguments& args);
static v8::Handle<v8::Value> SetEncoding(const v8::Arguments& args);
static v8::Handle<v8::Value> Pause(const v8::Arguments& args);
static v8::Handle<v8::Value> Resume(const v8::Arguments& args);
static v8::Handle<v8::Value> SetTimeout(const v8::Arguments& args);
static v8::Handle<v8::Value> SetNoDelay(const v8::Arguments& args);
static v8::Handle<v8::Value> ReadyStateGetter(v8::Local<v8::String> _,
const v8::AccessorInfo& info);
static v8::Handle<v8::Value> FDGetter(v8::Local<v8::String> _,
const v8::AccessorInfo& info);
#if EVCOM_HAVE_GNUTLS
static v8::Handle<v8::Value> SetSecure(const v8::Arguments& args);
static v8::Handle<v8::Value> VerifyPeer(const v8::Arguments& args);
static v8::Handle<v8::Value> 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);
}
ssize_t Write(const char *buf, size_t len) {
return evcom_stream_write(&stream_, buf, len);
}
void Close() {
evcom_stream_close(&stream_);
}
void ForceClose() {
evcom_stream_force_close(&stream_);
}
void Pause() {
evcom_stream_read_pause(&stream_);
}
void Resume() {
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<v8::Object> 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<Connection*>(s->data);
connection->OnConnect();
}
static void on_read(evcom_stream *s, const void *buf, size_t len) {
Connection *connection = static_cast<Connection*>(s->data);
assert(connection->refs_);
if (len == 0)
connection->OnEOF();
else
connection->OnReceive(buf, len);
}
static void on_close(evcom_stream *s) {
Connection *connection = static_cast<Connection*>(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->refs_);
connection->Unref();
}
static void on_timeout(evcom_stream *s) {
Connection *connection = static_cast<Connection*>(s->data);
connection->OnTimeout();
}
static void on_drain(evcom_stream *s) {
Connection *connection = static_cast<Connection*>(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<v8::Object> target);
protected:
static v8::Persistent<v8::FunctionTemplate> constructor_template;
static v8::Handle<v8::Value> New(const v8::Arguments& args);
static v8::Handle<v8::Value> Listen(const v8::Arguments& args);
static v8::Handle<v8::Value> Close(const v8::Arguments& args);
#if EVCOM_HAVE_GNUTLS
static v8::Handle<v8::Value> 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_);
Ref();
return 0;
}
void Close() {
evcom_server_close(&server_);
}
virtual v8::Handle<v8::FunctionTemplate> GetConnectionTemplate();
virtual Connection* UnwrapConnection(v8::Local<v8::Object> connection);
private:
Connection* OnConnection(struct sockaddr *addr);
static evcom_stream* on_connection(evcom_server *s, struct sockaddr *addr) {
Server *server = static_cast<Server*>(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<Server*>(s->data);
evcom_server_detach(s);
server->OnClose(s->errorno);
server->Unref();
}
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

2
src/node_net2.cc

@ -14,6 +14,8 @@
#include <fcntl.h>
#include <arpa/inet.h> /* inet_pton */
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>

25
wscript

@ -295,22 +295,6 @@ def build(bld):
bld.add_subdirs('deps/libeio')
### evcom
evcom = bld.new_task_gen("cc")
evcom.source = "deps/evcom/evcom.c"
if not bld.env["USE_SYSTEM"]:
evcom.includes = "deps/evcom/ deps/libev/"
else:
evcom.includes = "deps/evcom/"
evcom.name = "evcom"
evcom.target = "evcom"
evcom.uselib = "GPGERROR GNUTLS"
evcom.install_path = None
if bld.env["USE_DEBUG"]:
evcom.clone("debug")
bld.install_files('${PREFIX}/include/node/', 'deps/evcom/evcom.h')
### http_parser
http_parser = bld.new_task_gen("cc")
http_parser.source = "deps/http_parser/http_parser.c"
@ -397,8 +381,6 @@ def build(bld):
src/node_cares.cc
src/node_events.cc
src/node_file.cc
src/node_http.cc
src/node_net.cc
src/node_signal_watcher.cc
src/node_stat_watcher.cc
src/node_stdio.cc
@ -415,7 +397,6 @@ def build(bld):
deps/libev
deps/c-ares
deps/libeio
deps/evcom
deps/http_parser
deps/coupling
"""
@ -423,18 +404,17 @@ def build(bld):
node.includes += ' deps/c-ares/' + bld.env['DEST_OS'] + '-' + bld.env['DEST_CPU']
node.add_objects = 'cares ev eio evcom http_parser coupling'
node.add_objects = 'cares ev eio http_parser coupling'
node.uselib_local = ''
node.uselib = 'RT OPENSSL GNUTLS GPGERROR UDNS V8 EXECINFO DL KVM SOCKET NSL'
else:
node.includes = """
src/
deps/libeio
deps/evcom
deps/http_parser
deps/coupling
"""
node.add_objects = 'eio evcom http_parser coupling'
node.add_objects = 'eio http_parser coupling'
node.uselib_local = 'eio'
node.uselib = 'RT EV OPENSSL GNUTLS GPGERROR UDNS V8 EXECINFO DL KVM SOCKET NSL'
@ -478,7 +458,6 @@ def build(bld):
src/node.h
src/node_object_wrap.h
src/node_events.h
src/node_net.h
""")
# Only install the man page if it exists.

Loading…
Cancel
Save