Skip to content

Commit

Permalink
Merge branch 'kazuho/expr/proxy-keepalive'
Browse files Browse the repository at this point in the history
  • Loading branch information
kazuho committed Nov 10, 2014
2 parents dbcbeae + d48e12e commit ba44789
Show file tree
Hide file tree
Showing 24 changed files with 1,017 additions and 171 deletions.
5 changes: 1 addition & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ before_script:
- curl -L https://github.com/joyent/libuv/archive/v1.0.0-rc1.tar.gz | tar xzf -
- (cd libuv-1.0.0-rc1 && ./autogen.sh && ./configure --prefix=/usr && make && sudo make install)
- cmake .
- curl -L http://cpanmin.us | perl - --sudo --notest App::cpanminus
- cpanm --sudo --notest Net::EmptyPort
- cpanm --sudo --notest Proc::Wait3
- cpanm --sudo --notest Scope::Guard
- misc/install-perl-modules.pl
- sudo apt-get install -qq apache2-utils
- curl -L http://github.com/tatsuhiro-t/nghttp2/releases/download/v0.6.4/nghttp2-0.6.4.tar.gz | tar xzf -
- (cd nghttp2-0.6.4 && ./configure --prefix=/usr --disable-threads --enable-app && make && sudo make install)
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ SET(LIB_SOURCE_FILES
lib/request.c
lib/rproxy.c
lib/socket.c
lib/socketpool.c
lib/string.c
lib/timeout.c
lib/token.c
Expand Down
102 changes: 70 additions & 32 deletions examples/libh2o/http1client.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,37 +20,91 @@
* IN THE SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include "h2o/socketpool.h"
#include "h2o/string_.h"
#include "h2o/http1client.h"

static int exit_status = -1;
static h2o_timeout_t zero_timeout, io_timeout;
static h2o_socketpool_t *sockpool;
static h2o_mempool_t pool;
static const char *url;
static int cnt_left = 3;

static h2o_http1client_head_cb on_connect(h2o_http1client_t *client, const char *errstr, h2o_buf_t **reqbufs, size_t *reqbufcnt, int *method_is_head);
static h2o_http1client_body_cb on_head(h2o_http1client_t *client, const char *errstr, int minor_version, int status, h2o_buf_t msg, struct phr_header *headers, size_t num_headers);

static void start_request(h2o_http1client_ctx_t *ctx)
{
char *scheme, *host, *path;
uint16_t port;
h2o_buf_t *req;
h2o_http1client_t *client;

/* clear memory pool */
h2o_mempool_clear(&pool);

/* parse URL */
if (h2o_parse_url(&pool, url, &scheme, &host, &port, &path) != 0) {
fprintf(stderr, "unrecognized type of URL: %s\n", url);
exit(1);
}
if (strcmp(scheme, "https") == 0) {
fprintf(stderr, "https is not (yet) supported\n");
exit(1);
}
/* build request */
req = h2o_mempool_alloc(&pool, sizeof(*req));
req->base = h2o_mempool_alloc(&pool, 1024);
req->len = snprintf(req->base, 1024, "GET %s HTTP/1.1\r\nhost: %s:%u\r\n\r\n", path, host, (unsigned)port);
assert(req->len < 1024);

/* initiate the request */
if (1) {
if (sockpool == NULL) {
sockpool = h2o_malloc(sizeof(*sockpool));
h2o_socketpool_init(sockpool, host, port, 10);
h2o_socketpool_set_timeout(sockpool, ctx->loop, 5000 /* in msec */);
}
client = h2o_http1client_connect_with_pool(ctx, &pool, sockpool, on_connect);
} else {
client = h2o_http1client_connect(ctx, &pool, host, port, on_connect);
}
assert(client != NULL);
client->data = req;
}

static int on_body(h2o_http1client_t *client, const char *errstr, h2o_buf_t *bufs, size_t bufcnt)
{
size_t i;

if (errstr != NULL && errstr != h2o_http1client_error_is_eos) {
fprintf(stderr, "%s\n", errstr);
exit_status = 1;
exit(1);
return -1;
}

for (i = 0; i != bufcnt; ++i)
fwrite(bufs[i].base, 1, bufs[i].len, stdout);

if (errstr == h2o_http1client_error_is_eos)
exit_status = 0;
if (errstr == h2o_http1client_error_is_eos) {
if (--cnt_left != 0) {
/* next attempt */
h2o_mempool_clear(&pool);
start_request(client->ctx);
}
}

return 0;
}

static h2o_http1client_body_cb on_head(h2o_http1client_t *client, const char *errstr, int minor_version, int status, h2o_buf_t msg, struct phr_header *headers, size_t num_headers)
h2o_http1client_body_cb on_head(h2o_http1client_t *client, const char *errstr, int minor_version, int status, h2o_buf_t msg, struct phr_header *headers, size_t num_headers)
{
size_t i;

if (errstr != NULL && errstr != h2o_http1client_error_is_eos) {
fprintf(stderr, "%s\n", errstr);
exit_status = 1;
exit(1);
return NULL;
}

Expand All @@ -60,18 +114,19 @@ static h2o_http1client_body_cb on_head(h2o_http1client_t *client, const char *er
printf("\n");

if (errstr == h2o_http1client_error_is_eos) {
exit_status = 0;
fprintf(stderr, "no body\n");
exit(1);
return NULL;
}

return on_body;
}

static h2o_http1client_head_cb on_connect(h2o_http1client_t *client, const char *errstr, h2o_buf_t **reqbufs, size_t *reqbufcnt, int *method_is_head)
h2o_http1client_head_cb on_connect(h2o_http1client_t *client, const char *errstr, h2o_buf_t **reqbufs, size_t *reqbufcnt, int *method_is_head)
{
if (errstr != NULL) {
fprintf(stderr, "%s\n", errstr);
exit_status = 1;
exit(1);
return NULL;
}

Expand All @@ -84,35 +139,20 @@ static h2o_http1client_head_cb on_connect(h2o_http1client_t *client, const char

int main(int argc, char **argv)
{
h2o_timeout_t zero_timeout, io_timeout;
h2o_http1client_ctx_t ctx = {
NULL,
&zero_timeout,
&io_timeout
};
h2o_mempool_t pool;
char *scheme, *host, *path;
uint16_t port;
h2o_buf_t req;
h2o_http1client_t *client;

if (argc != 2) {
fprintf(stderr, "Usage: %s <url>\n", argv[0]);
return 1;
}
url = argv[1];

h2o_mempool_init(&pool);

if (h2o_parse_url(&pool, argv[1], &scheme, &host, &port, &path) != 0) {
fprintf(stderr, "unrecognized type of URL: %s\n", argv[1]);
return 1;
}
if (strcmp(scheme, "https") == 0) {
fprintf(stderr, "https is not (yet) supported\n");
return 1;
}
req.len = asprintf((char**)&req.base, "GET %s HTTP/1.1\r\nhost: %s:%u\r\nconnection: close\r\n\r\n", path, host, (unsigned)port);

/* setup context */
#if H2O_USE_LIBUV
ctx.loop = uv_loop_new();
Expand All @@ -122,18 +162,16 @@ int main(int argc, char **argv)
h2o_timeout_init(ctx.loop, &zero_timeout, 0);
h2o_timeout_init(ctx.loop, &io_timeout, 5000); /* 5 seconds */

/* setup client */
client = h2o_http1client_connect(&ctx, &pool, host, port, on_connect);
assert(client != NULL);
client->data = &req;
/* setup the first request */
start_request(&ctx);

while (exit_status == -1) {
while (cnt_left != 0) {
#if H2O_USE_LIBUV
uv_run(ctx.loop, UV_RUN_DEFAULT);
uv_run(ctx.loop, UV_RUN_ONCE);
#else
h2o_evloop_run(ctx.loop);
#endif
}

return exit_status;
return 0;
}
8 changes: 8 additions & 0 deletions h2o.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@
10D0907019F494CC0043D458 /* test.c in Sources */ = {isa = PBXBuildFile; fileRef = 10D0906E19F494CC0043D458 /* test.c */; };
10D0907119F584260043D458 /* string.c in Sources */ = {isa = PBXBuildFile; fileRef = 10D0905A19F230280043D458 /* string.c */; };
10D0907319F633B00043D458 /* proxy.c in Sources */ = {isa = PBXBuildFile; fileRef = 10D0907219F633B00043D458 /* proxy.c */; };
10EC2A361A0B4D370083514F /* socketpool.h in Headers */ = {isa = PBXBuildFile; fileRef = 10EC2A351A0B4D370083514F /* socketpool.h */; };
10EC2A381A0B4DC70083514F /* socketpool.c in Sources */ = {isa = PBXBuildFile; fileRef = 10EC2A371A0B4DC70083514F /* socketpool.c */; };
10F417CC19C1907B00B6E31A /* libh2o.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1079231519A320A700C52AD6 /* libh2o.a */; };
10F417D619C190F800B6E31A /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 10F417D519C190F800B6E31A /* main.c */; settings = {COMPILER_FLAGS = "-Wno-deprecated-declarations"; }; };
10F417FF19C2D2F800B6E31A /* picotest.c in Sources */ = {isa = PBXBuildFile; fileRef = 10F417FD19C2D2F800B6E31A /* picotest.c */; };
Expand Down Expand Up @@ -232,6 +234,8 @@
10D0906E19F494CC0043D458 /* test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = test.c; sourceTree = "<group>"; };
10D0906F19F494CC0043D458 /* test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = test.h; sourceTree = "<group>"; };
10D0907219F633B00043D458 /* proxy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = proxy.c; sourceTree = "<group>"; };
10EC2A351A0B4D370083514F /* socketpool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = socketpool.h; sourceTree = "<group>"; };
10EC2A371A0B4DC70083514F /* socketpool.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = socketpool.c; sourceTree = "<group>"; };
10F417D319C1907B00B6E31A /* h2o */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = h2o; sourceTree = BUILT_PRODUCTS_DIR; };
10F417D519C190F800B6E31A /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = "<group>"; };
10F417FD19C2D2F800B6E31A /* picotest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = picotest.c; sourceTree = "<group>"; };
Expand Down Expand Up @@ -394,6 +398,7 @@
10D0903919F0A51C0043D458 /* memory.h */,
10D0903F19F0B90A0043D458 /* socket */,
10D0903D19F0A8190043D458 /* socket.h */,
10EC2A351A0B4D370083514F /* socketpool.h */,
10D0905819F22FA10043D458 /* string_.h */,
10D0904019F0B9CD0043D458 /* timeout.h */,
107923A219A3215F00C52AD6 /* token.h */,
Expand Down Expand Up @@ -430,6 +435,7 @@
107923BD19A3217300C52AD6 /* rproxy.c */,
101788B119B561AA0084C6D8 /* socket.c */,
1065E70919BF18A600686E72 /* socket */,
10EC2A371A0B4DC70083514F /* socketpool.c */,
10D0905A19F230280043D458 /* string.c */,
1065E6F819BEBAC600686E72 /* timeout.c */,
107923BF19A3217300C52AD6 /* token.c */,
Expand Down Expand Up @@ -526,6 +532,7 @@
files = (
107923C919A3217300C52AD6 /* hpack_static_table.h in Headers */,
10D0904319F0BA780043D458 /* linklist.h in Headers */,
10EC2A361A0B4D370083514F /* socketpool.h in Headers */,
1079236A19A3210E00C52AD6 /* khash.h in Headers */,
107923A619A3215F00C52AD6 /* http2.h in Headers */,
107923A719A3215F00C52AD6 /* token.h in Headers */,
Expand Down Expand Up @@ -721,6 +728,7 @@
107923CD19A3217300C52AD6 /* memory.c in Sources */,
107923CC19A3217300C52AD6 /* context.c in Sources */,
107923C519A3217300C52AD6 /* http1.c in Sources */,
10EC2A381A0B4DC70083514F /* socketpool.c in Sources */,
1079239619A3210E00C52AD6 /* picohttpparser.c in Sources */,
10D0905B19F230280043D458 /* string.c in Sources */,
1065E6F919BEBAC600686E72 /* timeout.c in Sources */,
Expand Down
12 changes: 11 additions & 1 deletion include/h2o.h
Original file line number Diff line number Diff line change
Expand Up @@ -763,14 +763,24 @@ void h2o_file_register_configurator(h2o_globalconf_t *conf);

/* lib/proxy.c */

typedef struct st_h2o_proxy_config_vars_t {
uint64_t io_timeout;
int use_keepalive;
uint64_t keepalive_timeout;
} h2o_proxy_config_vars_t;

/**
* delegates the request to given server, rewriting the path as specified
*/
int h2o_proxy_send(h2o_req_t *req, h2o_http1client_ctx_t *client_ctx, h2o_buf_t host, uint16_t port, size_t path_replace_length, h2o_buf_t path_prefix);
/**
* delegates the request to given server, rewriting the path as specified
*/
int h2o_proxy_send_with_pool(h2o_req_t *req, h2o_http1client_ctx_t *client_ctx, h2o_socketpool_t *sockpool, size_t path_replace_length, h2o_buf_t path_prefix);
/**
* registers the reverse proxy handler to the context
*/
void h2o_proxy_register_reverse_proxy(h2o_hostconf_t *host_config, const char *virtual_path, const char *host, uint16_t port, const char *real_path, uint64_t io_timeout);
void h2o_proxy_register_reverse_proxy(h2o_hostconf_t *host_config, const char *virtual_path, const char *host, uint16_t port, const char *real_path, h2o_proxy_config_vars_t *config);
/**
* registers the configurator
*/
Expand Down
4 changes: 4 additions & 0 deletions include/h2o/http1client.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "picohttpparser.h"
#include "h2o/memory.h"
#include "h2o/socket.h"
#include "h2o/socketpool.h"
#include "h2o/timeout.h"

typedef struct st_h2o_http1client_t h2o_http1client_t;
Expand All @@ -42,6 +43,7 @@ typedef struct st_h2o_http1client_ctx_t {
struct st_h2o_http1client_t {
h2o_http1client_ctx_t *ctx;
h2o_mempool_t *pool;
h2o_socketpool_t *sockpool;
h2o_socket_t *sock;
void *data;
union {
Expand All @@ -52,12 +54,14 @@ struct st_h2o_http1client_t {
const char *_errstr;
h2o_timeout_entry_t _timeout;
int _method_is_head;
int _can_keepalive;
size_t _body_bytesleft;
};

extern const char * const h2o_http1client_error_is_eos;

h2o_http1client_t *h2o_http1client_connect(h2o_http1client_ctx_t *ctx, h2o_mempool_t *pool, const char *host, uint16_t port, h2o_http1client_connect_cb cb);
h2o_http1client_t *h2o_http1client_connect_with_pool(h2o_http1client_ctx_t *ctx, h2o_mempool_t *pool, h2o_socketpool_t *sockpool, h2o_http1client_connect_cb cb);
void h2o_http1client_cancel(h2o_http1client_t *client);

#endif
33 changes: 29 additions & 4 deletions include/h2o/socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ typedef void (*h2o_socket_cb)(h2o_socket_t *sock, int err);
# include "socket/evloop.h"
#endif

typedef struct st_h2o_socket_peername_t {
struct sockaddr_storage addr;
socklen_t len;
} h2o_socket_peername_t;

/**
* abstraction layer for sockets (SSL vs. TCP)
*/
Expand All @@ -72,12 +77,32 @@ struct st_h2o_socket_t {
h2o_socket_cb write;
} _cb;
/* zero-filled in case of invalid address */
struct {
struct sockaddr_storage addr;
socklen_t len;
} peername;
h2o_socket_peername_t peername;
};

typedef struct st_h2o_socket_export_t {
int fd;
h2o_socket_peername_t peername;
struct st_h2o_socket_ssl_t *ssl;
h2o_input_buffer_t *input;
} h2o_socket_export_t;

/**
* returns the loop
*/
h2o_loop_t *h2o_socket_get_loop(h2o_socket_t *sock);
/**
* detaches a socket from loop.
*/
int h2o_socket_export(h2o_socket_t *sock, h2o_socket_export_t *info);
/**
* attaches a socket onto a loop.
*/
h2o_socket_t *h2o_socket_import(h2o_loop_t *loop, h2o_socket_export_t *info);
/**
* destroys an exported socket info.
*/
void h2o_socket_dispose_export(h2o_socket_export_t *info);
/**
* closes the socket
*/
Expand Down

0 comments on commit ba44789

Please sign in to comment.