Commit 673f9c7d authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa

Merge branch 'rproxy'

parents c0b5009d 6b5beeac
...@@ -41,11 +41,16 @@ needed: ...@@ -41,11 +41,16 @@ needed:
* OpenSSL >= 1.0.1 * OpenSSL >= 1.0.1
To enable ``-a`` option (getting linked assets from the downloaded To enable ``-a`` option (getting linked assets from the downloaded
resouce) in spdycat (one of the example program), the following resouce) in ``spdycat`` (one of the example program), the following
packages are needed: packages are needed:
* libxml2 >= 2.7.7 * libxml2 >= 2.7.7
To build SPDY/HTTPS to HTTP reverse proxy ``shrpx`` (one of the
example program), the following packages are needed:
* libevent-openssl >= 2.0.8
Build from git Build from git
-------------- --------------
...@@ -88,6 +93,9 @@ purposes. Please note that OpenSSL with `NPN ...@@ -88,6 +93,9 @@ purposes. Please note that OpenSSL with `NPN
required in order to build and run these programs. At the time of required in order to build and run these programs. At the time of
this writing, the OpenSSL 1.0.1 supports NPN. this writing, the OpenSSL 1.0.1 supports NPN.
Spdycat - SPDY client
+++++++++++++++++++++
The SPDY client is called ``spdycat``. It is a dead simple downloader The SPDY client is called ``spdycat``. It is a dead simple downloader
like wget/curl. It connects to SPDY server and gets resources given in like wget/curl. It connects to SPDY server and gets resources given in
the command-line:: the command-line::
...@@ -154,6 +162,9 @@ the command-line:: ...@@ -154,6 +162,9 @@ the command-line::
[ 0.077] send GOAWAY frame <version=3, flags=0, length=8> [ 0.077] send GOAWAY frame <version=3, flags=0, length=8>
(last_good_stream_id=0) (last_good_stream_id=0)
Spdyd - SPDY server
+++++++++++++++++++
SPDY server is called ``spdyd`` and serves static files. It is single SPDY server is called ``spdyd`` and serves static files. It is single
threaded and multiplexes connections using non-blocking socket. The threaded and multiplexes connections using non-blocking socket. The
static files are read using blocking I/O system call, read(2). It static files are read using blocking I/O system call, read(2). It
...@@ -193,6 +204,45 @@ speaks SPDY/2 and SPDY/3:: ...@@ -193,6 +204,45 @@ speaks SPDY/2 and SPDY/3::
Currently, ``spdyd`` needs ``epoll`` or ``kqueue``. Currently, ``spdyd`` needs ``epoll`` or ``kqueue``.
Shrpx - A reverse proxy for SPDY/HTTPS
++++++++++++++++++++++++++++++++++++++
The ``shrpx`` is a multi-threaded reverse proxy for SPDY/HTTPS. It
converts SPDY/HTTPS traffic to plain HTTP.
Here is the command-line options::
Usage: shrpx [-Dh] [-b <HOST,PORT>] [-f <HOST,PORT>] [-n <CORES>]
[-c <NUM>] [-L <LEVEL>] <PRIVATE_KEY> <CERT>
A reverse proxy for SPDY/HTTPS.
OPTIONS:
-b, --backend=<HOST,PORT>
Set backend host and port.
Default: 'localhost,80'
-f, --frontend=<HOST,PORT>
Set frontend host and port.
Default: 'localhost,3000'
-n, --workers=<CORES>
Set the number of worker threads.
-c, --spdy-max-concurrent-streams=<NUM>
Set the maximum number of the concurrent
streams in one SPDY session.
-L, --log-level=<LEVEL>
Set the severity level of log output.
INFO, WARNING, ERROR and FATAL
-D, --daemon Run in a background. If -D is used, the
current working directory is changed to '/'.
-h, --help Print this help.
For those of you who are curious, ``shrpx`` is an abbreviation of
"Spdy/https to Http Reverse ProXy".
Other examples
++++++++++++++
There is another SPDY server called ``spdynative``, which is There is another SPDY server called ``spdynative``, which is
`node.native <https://github.com/d5/node.native>`_ style simple SPDY `node.native <https://github.com/d5/node.native>`_ style simple SPDY
server:: server::
......
...@@ -95,6 +95,17 @@ if test "x${have_openssl}" = "xno"; then ...@@ -95,6 +95,17 @@ if test "x${have_openssl}" = "xno"; then
AC_MSG_NOTICE([The example programs will not be built.]) AC_MSG_NOTICE([The example programs will not be built.])
fi fi
# libevent_openssl
# 2.0.8 is required because we use evconnlistener_set_error_cb()
PKG_CHECK_MODULES([LIBEVENT_OPENSSL], [libevent_openssl >= 2.0.8],
[have_libevent_openssl=yes], [have_libevent_openssl=no])
if test "x${have_libevent_openssl}" = "xno"; then
AC_MSG_NOTICE($LIBEVENT_OPENSSL_PKG_ERRORS)
AC_MSG_NOTICE([Shrpx example program will not be built.])
fi
AM_CONDITIONAL([HAVE_LIBEVENT_OPENSSL],
[ test "x${have_libevent_openssl}" = "xyes" ])
# libxml2 (for examples/spdycat) # libxml2 (for examples/spdycat)
AM_PATH_XML2(2.7.7, [have_libxml2=yes], [have_libxml2=no]) AM_PATH_XML2(2.7.7, [have_libxml2=yes], [have_libxml2=no])
if test "x${have_libxml2}" = "xyes"; then if test "x${have_libxml2}" = "xyes"; then
...@@ -178,5 +189,6 @@ AC_MSG_NOTICE([summary of build options: ...@@ -178,5 +189,6 @@ AC_MSG_NOTICE([summary of build options:
CUnit: ${have_cunit} CUnit: ${have_cunit}
OpenSSL: ${have_openssl} OpenSSL: ${have_openssl}
Libxml2: ${have_libxml2} Libxml2: ${have_libxml2}
Libevent(SSL): ${have_libevent_openssl}
Examples: ${enable_examples} Examples: ${enable_examples}
]) ])
...@@ -2,3 +2,4 @@ spdycat ...@@ -2,3 +2,4 @@ spdycat
spdyd spdyd
spdynative spdynative
spdycli spdycli
shrpx
...@@ -25,12 +25,16 @@ if ENABLE_EXAMPLES ...@@ -25,12 +25,16 @@ if ENABLE_EXAMPLES
AM_CFLAGS = -Wall AM_CFLAGS = -Wall
AM_CPPFLAGS = -Wall -I$(srcdir)/../lib/includes -I$(builddir)/../lib/includes \ AM_CPPFLAGS = -Wall -I$(srcdir)/../lib/includes -I$(builddir)/../lib/includes \
@OPENSSL_CFLAGS@ @XML_CPPFLAGS@ @DEFS@ @OPENSSL_CFLAGS@ @XML_CPPFLAGS@ @LIBEVENT_OPENSSL_CFLAGS@ @DEFS@
AM_LDFLAGS = @OPENSSL_LIBS@ @XML_LIBS@ AM_LDFLAGS = @OPENSSL_LIBS@ @XML_LIBS@ @LIBEVENT_OPENSSL_LIBS@
LDADD = $(top_builddir)/lib/libspdylay.la LDADD = $(top_builddir)/lib/libspdylay.la
bin_PROGRAMS = spdycat spdyd bin_PROGRAMS = spdycat spdyd
if HAVE_LIBEVENT_OPENSSL
bin_PROGRAMS += shrpx
endif # HAVE_LIBEVENT_OPENSSL
HELPER_OBJECTS = uri.cc util.cc spdylay_ssl.cc HELPER_OBJECTS = uri.cc util.cc spdylay_ssl.cc
HELPER_HFILES = uri.h util.h spdylay_ssl.h HELPER_HFILES = uri.h util.h spdylay_ssl.h
...@@ -65,6 +69,26 @@ spdyd_SOURCES = ${HELPER_OBJECTS} ${HELPER_HFILES} \ ...@@ -65,6 +69,26 @@ spdyd_SOURCES = ${HELPER_OBJECTS} ${HELPER_HFILES} \
${SPDY_SERVER_OBJECTS} ${SPDY_SERVER_HFILES} \ ${SPDY_SERVER_OBJECTS} ${SPDY_SERVER_HFILES} \
spdyd.cc spdyd.cc
if HAVE_LIBEVENT_OPENSSL
shrpx_SOURCES = ${HELPER_OBJECTS} ${HELPER_HFILES} \
shrpx_config.cc shrpx_config.h \
shrpx.cc \
shrpx_listen_handler.cc shrpx_listen_handler.h \
shrpx_client_handler.cc shrpx_client_handler.h \
shrpx_upstream.h \
shrpx_spdy_upstream.cc shrpx_spdy_upstream.h \
shrpx_https_upstream.cc shrpx_https_upstream.h \
shrpx_downstream_queue.cc shrpx_downstream_queue.h \
shrpx_downstream.cc shrpx_downstream.h \
shrpx_log.cc shrpx_log.h \
shrpx_http.cc shrpx_http.h \
shrpx_io_control.cc shrpx_io_control.h \
shrpx_ssl.cc shrpx_ssl.h \
shrpx_thread_event_receiver.cc shrpx_thread_event_receiver.h \
shrpx_worker.cc shrpx_worker.h \
htparse/htparse.c htparse/htparse.h
endif # HAVE_LIBEVENT_OPENSSL
noinst_PROGRAMS = spdycli noinst_PROGRAMS = spdycli
spdycli_SOURCES = spdycli.c spdycli_SOURCES = spdycli.c
......
Libevhtp is available for use under the following license, commonly known
as the 3-clause (or "modified") BSD license:
==============================
Copyright (c) 2010-2011 Mark Ellzey
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.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
==============================
Portions of Libevhtp are based on works by others, also made available by them
under the three-clause BSD license above. The functions include:
evhtp.c: _evhtp_glob_match():
Copyright (c) 2006-2009, Salvatore Sanfilippo
SRC = htparse.c
OUT = libhtparse.a
OBJ = $(SRC:.c=.o)
INCLUDES = -I.
CFLAGS += -ggdb -Wall -Wextra
LDFLAGS +=
CC = gcc
.SUFFIXES: .c
default: $(OUT)
.c.o:
$(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@
$(OUT): $(OBJ)
ar rcs $(OUT) $(OBJ)
test: $(OUT) test.c
$(CC) $(INCLUDES) $(CFLAGS) test.c -o test $(OUT)
clean:
rm -f $(OBJ) $(OUT) test
This diff is collapsed.
#ifndef __HTPARSE_H__
#define __HTPARSE_H__
struct htparser;
enum htp_type {
htp_type_request = 0,
htp_type_response
};
enum htp_scheme {
htp_scheme_none = 0,
htp_scheme_ftp,
htp_scheme_http,
htp_scheme_https,
htp_scheme_nfs,
htp_scheme_unknown
};
enum htp_method {
htp_method_GET = 0,
htp_method_HEAD,
htp_method_POST,
htp_method_PUT,
htp_method_DELETE,
htp_method_MKCOL,
htp_method_COPY,
htp_method_MOVE,
htp_method_OPTIONS,
htp_method_PROPFIND,
htp_method_PROPPATCH,
htp_method_LOCK,
htp_method_UNLOCK,
htp_method_TRACE,
htp_method_UNKNOWN
};
enum htpparse_error {
htparse_error_none = 0,
htparse_error_too_big,
htparse_error_inval_method,
htparse_error_inval_reqline,
htparse_error_inval_schema,
htparse_error_inval_proto,
htparse_error_inval_ver,
htparse_error_inval_hdr,
htparse_error_inval_chunk_sz,
htparse_error_inval_chunk,
htparse_error_inval_state,
htparse_error_user,
htparse_error_status,
htparse_error_generic
};
typedef struct htparser htparser;
typedef struct htparse_hooks htparse_hooks;
typedef enum htp_scheme htp_scheme;
typedef enum htp_method htp_method;
typedef enum htp_type htp_type;
typedef enum htpparse_error htpparse_error;
typedef int (*htparse_hook)(htparser *);
typedef int (*htparse_data_hook)(htparser *, const char *, size_t);
struct htparse_hooks {
htparse_hook on_msg_begin;
htparse_data_hook method;
htparse_data_hook scheme; /* called if scheme is found */
htparse_data_hook host; /* called if a host was in the request scheme */
htparse_data_hook port; /* called if a port was in the request scheme */
htparse_data_hook path; /* only the path of the uri */
htparse_data_hook args; /* only the arguments of the uri */
htparse_data_hook uri; /* the entire uri including path/args */
htparse_hook on_hdrs_begin;
htparse_data_hook hdr_key;
htparse_data_hook hdr_val;
htparse_hook on_hdrs_complete;
htparse_hook on_new_chunk; /* called after parsed chunk octet */
htparse_hook on_chunk_complete; /* called after single parsed chunk */
htparse_hook on_chunks_complete; /* called after all parsed chunks processed */
htparse_data_hook body;
htparse_hook on_msg_complete;
};
size_t htparser_run(htparser *, htparse_hooks *, const char *, size_t);
int htparser_should_keep_alive(htparser * p);
htp_scheme htparser_get_scheme(htparser *);
htp_method htparser_get_method(htparser *);
const char * htparser_get_methodstr(htparser *);
void htparser_set_major(htparser *, unsigned char);
void htparser_set_minor(htparser *, unsigned char);
unsigned char htparser_get_major(htparser *);
unsigned char htparser_get_minor(htparser *);
unsigned int htparser_get_status(htparser *);
uint64_t htparser_get_content_length(htparser *);
uint64_t htparser_get_total_bytes_read(htparser *);
htpparse_error htparser_get_error(htparser *);
const char * htparser_get_strerror(htparser *);
void * htparser_get_userdata(htparser *);
void htparser_set_userdata(htparser *, void *);
void htparser_init(htparser *, htp_type);
htparser * htparser_new(void);
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include "htparse.h"
static int
_on_msg_start(htparser * p) {
printf("START {\n");
return 0;
}
static int
_on_msg_end(htparser * p) {
printf("}\n");
return 0;
}
static int
_path(htparser * p, const char * data, size_t len) {
printf("\tpath = '%.*s'\n", (int)len, data);
return 0;
}
static int
_method(htparser * p, const char * data, size_t len) {
printf("\tmethod = '%.*s'\n", (int)len, data);
return 0;
}
static int
_uri(htparser * p, const char * data, size_t len) {
printf("\turi = '%.*s'\n", (int)len, data);
return 0;
}
static int
_args(htparser * p, const char * data, size_t len) {
printf("\targs = '%.*s'\n", (int)len, data);
return 0;
}
static int
_hdrs_end(htparser * p) {
printf("\t}\n");
return 0;
}
static int
_hdrs_start(htparser * p) {
printf("\thdrs {\n");
return 0;
}
static int
_hdr_key(htparser * p, const char * data, size_t len) {
printf("\t\thdr_key = '%.*s'\n", (int)len, data);
return 0;
}
static int
_hdr_val(htparser * p, const char * data, size_t len) {
printf("\t\thdr_val = '%.*s'\n", (int)len, data);
return 0;
}
static int
_read_body(htparser * p, const char * data, size_t len) {
printf("\t'%.*s'\n", (int)len, data);
return 0;
}
static int
_on_new_chunk(htparser * p) {
printf("\t--chunk payload (%zu)--\n", htparser_get_content_length(p));
/* printf("..chunk..\n"); */
return 0;
}
static void
_test(htparser * p, htparse_hooks * hooks, const char * l, htp_type type) {
printf("---- test ----\n");
printf("%zu, %s\n", strlen(l), l);
htparser_init(p, type);
printf("%zu == %zu\n", htparser_run(p, hooks, l, strlen(l)), strlen(l));
if (htparser_get_error(p)) {
printf("ERROR: %s\n", htparser_get_strerror(p));
}
printf("\n");
}
static void
_test_fragments(htparser * p, htparse_hooks * hooks, const char ** fragments,
htp_type type) {
int i = 0;
printf("---- test fragment ----\n");
htparser_init(p, type);
while (1) {
const char * l = fragments[i++];
if (l == NULL) {
break;
}
htparser_run(p, hooks, l, strlen(l));
if (htparser_get_error(p)) {
printf("ERROR: %s\n", htparser_get_strerror(p));
}
}
printf("\n");
}
static const char * test_fragment_1[] = {
"GET \0",
" /fjdksf\0",
"jfkdslfds H\0",
"TTP/1.\0",
"1\r\0",
"\n\0",
"\r\0",
"\n\0",
NULL
};
static const char * test_fragment_2[] = {
"POST /\0",
"h?a=b HTTP/1.0\r\n\0",
"Content-Len\0",
"gth\0",
": 1\0",
"0\r\n\0",
"\r\n\0",
"12345\0",
"67890\0",
NULL
};
static const char * test_chunk_fragment_1[] = {
"POST /stupid HTTP/1.1\r\n",
"Transfer-Encoding: chunked\r\n",
"\r\n",
"25\r\n",
"This is the data in the first chunk\r\n",
"\r\n",
"1C\r\n",
"and this is the second one\r\n",
"\r\n",
"3\r\n",
"con\r\n",
"8\r\n",
"sequence\r\n",
"0\r\n",
"\r\n",
NULL
};
static const char * test_chunk_fragment_2[] = {
"POST /stupid HTTP/1.1\r\n",
"Transfer-Encoding: chunked\r\n",
"\r\n",
"25\r\n",
"This is the data in the first chunk\r\n",
"\r\n",
"1C\r\n",
"and this is the second one\r\n",
"\r\n",
"3\r\n",
"c",
"on\r\n",
"8\r\n",
"sequence\r\n",
"0\r\n",
"\r\n",
"GET /foo?bar/baz? HTTP/1.0\r\n",
"Host: stupid.com\r\n",
"\r\n",
NULL
};
int
main(int argc, char ** argv) {
htparser * p = htparser_new();
htparse_hooks hooks = {
.on_msg_begin = _on_msg_start,
.method = _method,
.scheme = NULL,
.host = NULL,
.port = NULL,
.path = _path,
.args = _args,
.uri = _uri,
.on_hdrs_begin = _hdrs_start,
.hdr_key = _hdr_key,
.hdr_val = _hdr_val,
.on_hdrs_complete = _hdrs_end,
.on_new_chunk = _on_new_chunk,
.on_chunk_complete = NULL,
.on_chunks_complete = NULL,
.body = _read_body,
.on_msg_complete = _on_msg_end
};
const char * test_1 = "GET / HTTP/1.0\r\n\r\n";
const char * test_2 = "GET /hi?a=b&c=d HTTP/1.1\r\n\r\n";
const char * test_3 = "GET /hi/die/?a=b&c=d HTTP/1.1\r\n\r\n";
const char * test_4 = "POST /fjdls HTTP/1.0\r\n"
"Content-Length: 4\r\n"
"\r\n"
"abcd";
const char * test_7 = "POST /derp HTTP/1.1\r\n"
"Transfer-Encoding: chunked\r\n\r\n"
"1e\r\nall your base are belong to us\r\n"
"0\r\n"
"\r\n\0";
const char * test_8 = "GET /DIE HTTP/1.1\r\n"
"HERP: DE\r\n"
"\tRP\r\nthings:stuff\r\n\r\n";
const char * test_9 = "GET /big_content_len HTTP/1.1\r\n"
"Content-Length: 18446744073709551615\r\n\r\n";
const char * test_fail = "GET /JF HfD]\r\n\r\n";
const char * test_resp_1 = "HTTP/1.0 200 OK\r\n"
"Stuff: junk\r\n\r\n";
_test(p, &hooks, test_resp_1, htp_type_response);
_test(p, &hooks, test_1, htp_type_request);
_test(p, &hooks, test_2, htp_type_request);
_test(p, &hooks, test_3, htp_type_request);
_test(p, &hooks, test_4, htp_type_request);
_test(p, &hooks, test_7, htp_type_request);
_test(p, &hooks, test_8, htp_type_request);
_test(p, &hooks, test_9, htp_type_request);
_test(p, &hooks, test_fail, htp_type_request);
_test_fragments(p, &hooks, test_fragment_1, htp_type_request);
_test_fragments(p, &hooks, test_fragment_2, htp_type_request);
_test_fragments(p, &hooks, test_chunk_fragment_1, htp_type_request);
_test_fragments(p, &hooks, test_chunk_fragment_2, htp_type_request);
return 0;
} /* main */
This diff is collapsed.
/*
* Spdylay - SPDY Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SHRPX_H
#define SHRPX_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif // HAVE_CONFIG_H
#include <cassert>
#include "shrpx_log.h"
#define DIE() \
assert(0);
#endif // SHRPX_H
/*
* Spdylay - SPDY Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "shrpx_client_handler.h"
#include "shrpx_upstream.h"
#include "shrpx_spdy_upstream.h"
#include "shrpx_https_upstream.h"
#include "shrpx_config.h"
namespace shrpx {
namespace {
void upstream_readcb(bufferevent *bev, void *arg)
{
ClientHandler *handler = reinterpret_cast<ClientHandler*>(arg);
int rv = handler->on_read();
if(rv != 0) {
if(ENABLE_LOG) {
LOG(INFO) << "<upstream> Read operation (application level) failure";
}
delete handler;
}
}
} // namespace
namespace {
void upstream_writecb(bufferevent *bev, void *arg)
{
ClientHandler *handler = reinterpret_cast<ClientHandler*>(arg);
// We actually depend on write low-warter mark == 0.
if(handler->get_should_close_after_write()) {
delete handler;
} else {
Upstream *upstream = handler->get_upstream();
upstream->on_write();
}
}
} // namespace
namespace {
void upstream_eventcb(bufferevent *bev, short events, void *arg)
{
ClientHandler *handler = reinterpret_cast<ClientHandler*>(arg);
bool finish = false;
if(events & BEV_EVENT_EOF) {
if(ENABLE_LOG) {
LOG(INFO) << "Upstream handshake EOF";
}
finish = true;
}
if(events & BEV_EVENT_ERROR) {
if(ENABLE_LOG) {
LOG(INFO) << "Upstream network error";
}
finish = true;
}
if(events & BEV_EVENT_TIMEOUT) {
if(ENABLE_LOG) {
LOG(INFO) << "Upstream time out";
}
finish = true;
}
if(finish) {
delete handler;
} else {
if(events & BEV_EVENT_CONNECTED) {
if(ENABLE_LOG) {
LOG(INFO) << "Upstream connected. handler " << handler;
}
handler->set_bev_cb(upstream_readcb, upstream_writecb, upstream_eventcb);
handler->validate_next_proto();
// At this point, input buffer is already filled with some
// bytes. The read callback is not called until new data
// come. So consume input buffer here.
handler->get_upstream()->on_read();
}
}
}
} // namespace
ClientHandler::ClientHandler(bufferevent *bev, SSL *ssl, const char *ipaddr)
: bev_(bev),
ssl_(ssl),
upstream_(0),
ipaddr_(ipaddr),
should_close_after_write_(false)
{
bufferevent_enable(bev_, EV_READ | EV_WRITE);
set_upstream_timeouts(&get_config()->upstream_read_timeout,
&get_config()->upstream_write_timeout);
set_bev_cb(0, upstream_writecb, upstream_eventcb);
}
ClientHandler::~ClientHandler()
{
if(ENABLE_LOG) {
LOG(INFO) << "Deleting ClientHandler " << this;
}
int fd = SSL_get_fd(ssl_);
SSL_shutdown(ssl_);
bufferevent_disable(bev_, EV_READ | EV_WRITE);
bufferevent_free(bev_);
SSL_free(ssl_);
shutdown(fd, SHUT_WR);
close(fd);
delete upstream_;
if(ENABLE_LOG) {
LOG(INFO) << "Deleted";
}
}
Upstream* ClientHandler::get_upstream()
{
return upstream_;
}
bufferevent* ClientHandler::get_bev() const
{
return bev_;
}
event_base* ClientHandler::get_evbase() const
{
return bufferevent_get_base(bev_);
}
void ClientHandler::set_bev_cb
(bufferevent_data_cb readcb, bufferevent_data_cb writecb,
bufferevent_event_cb eventcb)
{
bufferevent_setcb(bev_, readcb, writecb, eventcb, this);
}
void ClientHandler::set_upstream_timeouts(const timeval *read_timeout,
const timeval *write_timeout)
{
bufferevent_set_timeouts(bev_, read_timeout, write_timeout);
}
int ClientHandler::validate_next_proto()
{
const unsigned char *next_proto = 0;
unsigned int next_proto_len;
SSL_get0_next_proto_negotiated(ssl_, &next_proto, &next_proto_len);
if(next_proto) {
std::string proto(next_proto, next_proto+next_proto_len);
if(ENABLE_LOG) {
LOG(INFO) << "Upstream negotiated next protocol: " << proto;
}
uint16_t version = spdylay_npn_get_version(next_proto, next_proto_len);
if(version) {
SpdyUpstream *spdy_upstream = new SpdyUpstream(version, this);
upstream_ = spdy_upstream;
return 0;
}
} else {
if(ENABLE_LOG) {
LOG(INFO) << "No proto negotiated.";
}
}
if(ENABLE_LOG) {
LOG(INFO) << "Use HTTP/1.1";
}
HttpsUpstream *https_upstream = new HttpsUpstream(this);
upstream_ = https_upstream;
return 0;
}
int ClientHandler::on_read()
{
return upstream_->on_read();
}
int ClientHandler::on_event()
{
return upstream_->on_event();
}
const std::string& ClientHandler::get_ipaddr() const
{
return ipaddr_;
}
bool ClientHandler::get_should_close_after_write() const
{
return should_close_after_write_;
}
void ClientHandler::set_should_close_after_write(bool f)
{
should_close_after_write_ = f;
}
} // namespace shrpx
/*
* Spdylay - SPDY Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SHRPX_CLIENT_HANDLER_H
#define SHRPX_CLIENT_HANDLER_H
#include "shrpx.h"
#include <event.h>
#include <openssl/ssl.h>
namespace shrpx {
class Upstream;
class ClientHandler {
public:
ClientHandler(bufferevent *bev, SSL *ssl, const char *ipaddr);
~ClientHandler();
int on_read();
int on_event();
bufferevent* get_bev() const;
event_base* get_evbase() const;
void set_bev_cb(bufferevent_data_cb readcb, bufferevent_data_cb writecb,
bufferevent_event_cb eventcb);
void set_upstream_timeouts(const timeval *read_timeout,
const timeval *write_timeout);
int validate_next_proto();
const std::string& get_ipaddr() const;
bool get_should_close_after_write() const;
void set_should_close_after_write(bool f);
Upstream* get_upstream();
private:
bufferevent *bev_;
SSL *ssl_;
Upstream *upstream_;
std::string ipaddr_;
bool should_close_after_write_;
};
} // namespace shrpx
#endif // SHRPX_CLIENT_HANDLER_H
/*
* Spdylay - SPDY Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "shrpx_config.h"
namespace shrpx {
Config::Config()
: verbose(false),
daemon(false),
host(0),
port(0),
private_key_file(0),
cert_file(0),
verify_client(false),
server_name(0),
downstream_host(0),
downstream_port(0),
downstream_hostport(0),
downstream_addrlen(0),
num_worker(0),
spdy_max_concurrent_streams(0)
{}
namespace {
Config *config = 0;
} // namespace
const Config* get_config()
{
return config;
}
Config* mod_config()
{
return config;
}
void create_config()
{
config = new Config();
}
} // namespace shrpx
/*
* Spdylay - SPDY Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SHRPX_CONFIG_H
#define SHRPX_CONFIG_H
#include "shrpx.h"
#include <stdint.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string>
namespace shrpx {
union sockaddr_union {
sockaddr sa;
sockaddr_storage storage;
sockaddr_in6 in6;
sockaddr_in in;
};
struct Config {
bool verbose;
bool daemon;
const char *host;
uint16_t port;
const char *private_key_file;
const char *cert_file;
bool verify_client;
const char *server_name;
const char *downstream_host;
uint16_t downstream_port;
const char *downstream_hostport;
sockaddr_union downstream_addr;
size_t downstream_addrlen;
timeval upstream_read_timeout;
timeval upstream_write_timeout;
timeval spdy_upstream_read_timeout;
timeval spdy_upstream_write_timeout;
timeval downstream_read_timeout;
timeval downstream_write_timeout;
size_t num_worker;
size_t spdy_max_concurrent_streams;
Config();
};
const Config* get_config();
Config* mod_config();
void create_config();
} // namespace shrpx
#endif // SHRPX_CONFIG_H
This diff is collapsed.
/*
* Spdylay - SPDY Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SHRPX_DOWNSTREAM_H
#define SHRPX_DOWNSTREAM_H
#include "shrpx.h"
#include <stdint.h>
#include <vector>
#include <string>
#include <event.h>
#include <event2/bufferevent.h>
extern "C" {
#include "htparse/htparse.h"
}
#include "shrpx_io_control.h"
namespace shrpx {
class Upstream;
typedef std::vector<std::pair<std::string, std::string> > Headers;
class Downstream {
public:
Downstream(Upstream *upstream, int stream_id, int priority);
~Downstream();
int start_connection();
Upstream* get_upstream() const;
int32_t get_stream_id() const;
void pause_read(IOCtrlReason reason);
bool resume_read(IOCtrlReason reason);
void force_resume_read();
// downstream request API
const Headers& get_request_headers() const;
void add_request_header(const std::string& name, const std::string& value);
void set_last_request_header_value(const std::string& value);
void set_request_method(const std::string& method);
void set_request_path(const std::string& path);
void set_request_major(int major);
void set_request_minor(int minor);
int push_request_headers();
bool get_chunked_request() const;
bool get_request_connection_close() const;
void set_request_connection_close(bool f);
int push_upload_data_chunk(const uint8_t *data, size_t datalen);
int end_upload_data();
enum {
INITIAL,
HEADER_COMPLETE,
MSG_COMPLETE,
STREAM_CLOSED,
CONNECT_FAIL
};
void set_request_state(int state);
int get_request_state() const;
// downstream response API
const Headers& get_response_headers() const;
void add_response_header(const std::string& name, const std::string& value);
void set_last_response_header_value(const std::string& value);
unsigned int get_response_http_status() const;
void set_response_http_status(unsigned int status);
void set_response_major(int major);
void set_response_minor(int minor);
int get_response_major() const;
int get_response_minor() const;
bool get_chunked_response() const;
int parse_http_response();
void set_response_state(int state);
int get_response_state() const;
int init_response_body_buf();
evbuffer* get_response_body_buf();
private:
Upstream *upstream_;
bufferevent *bev_;
int32_t stream_id_;
int priority_;
IOControl ioctrl_;
int request_state_;
std::string request_method_;
std::string request_path_;
int request_major_;
int request_minor_;
bool chunked_request_;
bool request_connection_close_;
Headers request_headers_;
int response_state_;
unsigned int response_http_status_;
int response_major_;
int response_minor_;
bool chunked_response_;
Headers response_headers_;
htparser *response_htp_;
// This buffer is used to temporarily store downstream response
// body. Spdylay reads data from this in the callback.
evbuffer *response_body_buf_;
};
} // namespace shrpx
#endif // SHRPX_DOWNSTREAM_H
/*
* Spdylay - SPDY Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "shrpx_downstream_queue.h"
#include "shrpx_downstream.h"
namespace shrpx {
DownstreamQueue::DownstreamQueue()
{}
DownstreamQueue::~DownstreamQueue()
{
for(std::map<int32_t, Downstream*>::iterator i = downstreams_.begin();
i != downstreams_.end(); ++i) {
delete (*i).second;
}
}
void DownstreamQueue::add(Downstream *downstream)
{
downstreams_[downstream->get_stream_id()] = downstream;
}
int DownstreamQueue::start(Downstream *downstream)
{
return downstream->start_connection();
}
void DownstreamQueue::remove(Downstream *downstream)
{
downstreams_.erase(downstream->get_stream_id());
}
Downstream* DownstreamQueue::find(int32_t stream_id)
{
std::map<int32_t, Downstream*>::iterator i = downstreams_.find(stream_id);
if(i == downstreams_.end()) {
return 0;
} else {
return (*i).second;
}
}
} // namespace shrpx
/*
* Spdylay - SPDY Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SHRPX_DOWNSTREAM_QUEUE_H
#define SHRPX_DOWNSTREAM_QUEUE_H
#include "shrpx.h"
#include <stdint.h>
#include <map>
namespace shrpx {
class Downstream;
class DownstreamQueue {
public:
DownstreamQueue();
~DownstreamQueue();
void add(Downstream *downstream);
int start(Downstream *downstream);
void remove(Downstream *downstream);
Downstream* find(int32_t stream_id);
private:
std::map<int32_t, Downstream*> downstreams_;
};
} // namespace shrpx
#endif // SHRPX_DOWNSTREAM_QUEUE_H
/*
* Spdylay - SPDY Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SHRPX_ERROR_H
#define SHRPX_ERROR_H
#include "shrpx.h"
namespace shrpx {
enum ErrorCode {
SHRPX_ERR_SUCCESS = 0,
SHRPX_ERR_UNKNOWN = -1,
SHRPX_ERR_HTTP_PARSE = -2,
SHRPX_ERR_NETWORK = -3
};
} // namespace shrpx
#endif // SHRPX_ERROR_H
/*
* Spdylay - SPDY Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "shrpx_http.h"
#include <sstream>
#include "shrpx_config.h"
namespace shrpx {
namespace http {
const char* get_status_string(int status_code)
{
switch(status_code) {
case 100: return "100 Continue";
case 101: return "101 Switching Protocols";
case 200: return "200 OK";
case 201: return "201 Created";
case 202: return "202 Accepted";
case 203: return "203 Non-Authoritative Information";
case 204: return "204 No Content";
case 205: return "205 Reset Content";
case 206: return "206 Partial Content";
case 300: return "300 Multiple Choices";
case 301: return "301 Moved Permanently";
case 302: return "302 Found";
case 303: return "303 See Other";
case 304: return "304 Not Modified";
case 305: return "305 Use Proxy";
// case 306: return "306 (Unused)";
case 307: return "307 Temporary Redirect";
case 400: return "400 Bad Request";
case 401: return "401 Unauthorized";
case 402: return "402 Payment Required";
case 403: return "403 Forbidden";
case 404: return "404 Not Found";
case 405: return "405 Method Not Allowed";
case 406: return "406 Not Acceptable";
case 407: return "407 Proxy Authentication Required";
case 408: return "408 Request Timeout";
case 409: return "409 Conflict";
case 410: return "410 Gone";
case 411: return "411 Length Required";
case 412: return "412 Precondition Failed";
case 413: return "413 Request Entity Too Large";
case 414: return "414 Request-URI Too Long";
case 415: return "415 Unsupported Media Type";
case 416: return "416 Requested Range Not Satisfiable";
case 417: return "417 Expectation Failed";
case 500: return "500 Internal Server Error";
case 501: return "501 Not Implemented";
case 502: return "502 Bad Gateway";
case 503: return "503 Service Unavailable";
case 504: return "504 Gateway Timeout";
case 505: return "505 HTTP Version Not Supported";
default: return "";
}
}
std::string create_error_html(int status_code)
{
std::stringstream ss;
const char *status = http::get_status_string(status_code);
ss << "<html><head><title>" << status << "</title></head><body>"
<< "<h1>" << status << "</h1>"
<< "<hr>"
<< "<address>" << get_config()->server_name << " at port "
<< get_config()->port
<< "</address>"
<< "</body></html>\n";
return ss.str();
}
std::string create_via_header_value(int major, int minor)
{
std::string hdrs;
hdrs += static_cast<char>(major+'0');
hdrs += ".";
hdrs += static_cast<char>(minor+'0');
hdrs += " shrpx";
return hdrs;
}
} // namespace http
} // namespace shrpx
/*
* Spdylay - SPDY Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SHRPX_HTTP_H
#define SHRPX_HTTP_H
#include <string>
namespace shrpx {
namespace http {
const char* get_status_string(int status_code);
std::string create_error_html(int status_code);
std::string create_via_header_value(int major, int minor);
} // namespace http
} // namespace shrpx
#endif // SHRPX_HTTP_H
This diff is collapsed.
/*
* Spdylay - SPDY Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SHRPX_HTTPS_UPSTREAM_H
#define SHRPX_HTTPS_UPSTREAM_H
#include "shrpx.h"
#include <stdint.h>
#include <deque>
extern "C" {
#include "htparse/htparse.h"
}
#include "shrpx_upstream.h"
#include "shrpx_io_control.h"
namespace shrpx {
class ClientHandler;
class HttpsUpstream : public Upstream {
public:
HttpsUpstream(ClientHandler *handler);
virtual ~HttpsUpstream();
virtual int on_read();
virtual int on_write();
virtual int on_event();
//int send();
virtual ClientHandler* get_client_handler() const;
virtual bufferevent_data_cb get_downstream_readcb();
virtual bufferevent_data_cb get_downstream_writecb();
virtual bufferevent_event_cb get_downstream_eventcb();
void add_downstream(Downstream *downstream);
void pop_downstream();
Downstream* get_top_downstream();
Downstream* get_last_downstream();
void error_reply(int status_code);
void pause_read(IOCtrlReason reason);
void resume_read(IOCtrlReason reason);
virtual int on_downstream_header_complete(Downstream *downstream);
virtual int on_downstream_body(Downstream *downstream,
const uint8_t *data, size_t len);
virtual int on_downstream_body_complete(Downstream *downstream);
void reset_current_header_length();
private:
ClientHandler *handler_;
htparser *htp_;
size_t current_header_length_;
std::deque<Downstream*> downstream_queue_;
IOControl ioctrl_;
};
} // namespace shrpx
#endif // SHRPX_HTTPS_UPSTREAM_H
/*
* Spdylay - SPDY Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "shrpx_io_control.h"
#include <algorithm>
namespace shrpx {
IOControl::IOControl(bufferevent *bev)
: bev_(bev),
ctrlv_(SHRPX_REASON_MAX)
{}
IOControl::~IOControl()
{}
void IOControl::set_bev(bufferevent *bev)
{
bev_ = bev;
}
void IOControl::pause_read(IOCtrlReason reason)
{
ctrlv_[reason] = 1;
bufferevent_disable(bev_, EV_READ);
}
bool IOControl::resume_read(IOCtrlReason reason)
{
ctrlv_[reason] = 0;
if(std::find(ctrlv_.begin(), ctrlv_.end(), 1) == ctrlv_.end()) {
bufferevent_enable(bev_, EV_READ);
return true;
} else {
return false;
}
}
void IOControl::force_resume_read()
{
std::fill(ctrlv_.begin(), ctrlv_.end(), 0);
bufferevent_enable(bev_, EV_READ);
}
} // namespace shrpx
/*
* Spdylay - SPDY Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SHRPX_IO_CONTROL_H
#define SHRPX_IO_CONTROL_H
#include "shrpx.h"
#include <vector>
#include <event.h>
#include <event2/bufferevent.h>
namespace shrpx {
enum IOCtrlReason {
SHRPX_NO_BUFFER = 0,
SHRPX_MSG_BLOCK,
SHRPX_REASON_MAX
};
class IOControl {
public:
IOControl(bufferevent *bev);
~IOControl();
void set_bev(bufferevent *bev);
void pause_read(IOCtrlReason reason);
// Returns true if read operation is enabled after this call
bool resume_read(IOCtrlReason reason);
// Clear all pause flags and enable read
void force_resume_read();
private:
bufferevent *bev_;
std::vector<int> ctrlv_;
};
} // namespace shrpx
#endif // SHRPX_IO_CONTROL_H
/*
* Spdylay - SPDY Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "shrpx_listen_handler.h"
#include <pthread.h>
#include <cerrno>
#include <event2/bufferevent_ssl.h>
#include "shrpx_client_handler.h"
#include "shrpx_thread_event_receiver.h"
#include "shrpx_ssl.h"
#include "shrpx_worker.h"
namespace shrpx {
ListenHandler::ListenHandler(event_base *evbase)
: evbase_(evbase),
ssl_ctx_(ssl::create_ssl_context()),
worker_round_robin_cnt_(0),
workers_(0),
num_worker_(0)
{}
ListenHandler::~ListenHandler()
{}
void ListenHandler::create_worker_thread(size_t num)
{
workers_ = new WorkerInfo[num];
num_worker_ = 0;
for(size_t i = 0; i < num; ++i) {
int rv;
pthread_t thread;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
WorkerInfo *info = &workers_[num_worker_];
rv = socketpair(AF_UNIX, SOCK_STREAM, 0, info->sv);
if(rv == -1) {
LOG(ERROR) << "socketpair() failed: " << strerror(errno);
continue;
}
rv = pthread_create(&thread, &attr, start_threaded_worker, &info->sv[1]);
if(rv != 0) {
LOG(ERROR) << "pthread_create() failed: " << strerror(rv);
for(size_t j = 0; j < 2; ++j) {
close(info->sv[j]);
}
continue;
}
bufferevent *bev = bufferevent_socket_new(evbase_, info->sv[0],
BEV_OPT_DEFER_CALLBACKS);
info->bev = bev;
if(ENABLE_LOG) {
LOG(INFO) << "Created thread#" << num_worker_;
}
++num_worker_;
}
}
int ListenHandler::accept_connection(evutil_socket_t fd,
sockaddr *addr, int addrlen)
{
if(ENABLE_LOG) {
LOG(INFO) << "<listener> Accepted connection. fd=" << fd;
}
if(num_worker_ == 0) {
/*ClientHandler* client = */
ssl::accept_ssl_connection(evbase_, ssl_ctx_, fd, addr, addrlen);
} else {
size_t idx = worker_round_robin_cnt_ % num_worker_;
++worker_round_robin_cnt_;
WorkerEvent wev;
memset(&wev, 0, sizeof(wev));
wev.client_fd = fd;
memcpy(&wev.client_addr, addr, addrlen);
wev.client_addrlen = addrlen;
evbuffer *output = bufferevent_get_output(workers_[idx].bev);
evbuffer_add(output, &wev, sizeof(wev));
}
return 0;
}
event_base* ListenHandler::get_evbase() const
{
return evbase_;
}
} // namespace shrpx
/*
* Spdylay - SPDY Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SHRPX_LISTEN_HANDLER_H
#define SHRPX_LISTEN_HANDLER_H
#include "shrpx.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <openssl/ssl.h>
#include <event.h>
namespace shrpx {
struct WorkerInfo {
int sv[2];
bufferevent *bev;
};
class ListenHandler {
public:
ListenHandler(event_base *evbase);
~ListenHandler();
int accept_connection(evutil_socket_t fd, sockaddr *addr, int addrlen);
void create_worker_thread(size_t num);
event_base* get_evbase() const;
private:
event_base *evbase_;
SSL_CTX *ssl_ctx_;
unsigned int worker_round_robin_cnt_;
WorkerInfo *workers_;
size_t num_worker_;
};
} // namespace shrpx
#endif // SHRPX_LISTEN_HANDLER_H
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -169,6 +169,21 @@ bool strieq(const char *a, const char *b) ...@@ -169,6 +169,21 @@ bool strieq(const char *a, const char *b)
return !*a && !*b; return !*a && !*b;
} }
bool strifind(const char *a, const char *b)
{
if(!a || !b) {
return false;
}
for(size_t i = 0; a[i]; ++i) {
const char *ap = &a[i], *bp = b;
for(; *ap && *bp && lowcase(*ap) == lowcase(*bp); ++ap, ++bp);
if(!*bp) {
return true;
}
}
return false;
}
} // namespace util } // namespace util
} // namespace spdylay } // namespace spdylay
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment