diff --git a/.gitignore b/.gitignore index 20dc051..f658074 100644 --- a/.gitignore +++ b/.gitignore @@ -61,3 +61,7 @@ DerivedData # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control # # Pods/ + +## googletest +test/acceltcp_unittest +gtest* diff --git a/CMakeLists.txt b/CMakeLists.txt index 41bc66d..2f84c3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,8 +3,11 @@ cmake_minimum_required(VERSION 2.6.2) include_directories(/usr/local/include /usr/include) link_directories(/usr/local/lib /usr/lib) -set(acceltcp_srcs acceltcp.c evsock.c http_handler.c http_parser.c) +set(acceltcp_srcs acceltcp_main.c acceltcp.c evsock.c http_handler.c http_parser.c) add_executable(acceltcp ${acceltcp_srcs}) target_link_libraries(acceltcp ev) target_link_libraries(acceltcp ssl) target_link_libraries(acceltcp crypto) + +add_subdirectory(gtest-1.7.0) +add_subdirectory(test) diff --git a/acceltcp.c b/acceltcp.c index b4c86f0..38a5ad8 100644 --- a/acceltcp.c +++ b/acceltcp.c @@ -23,159 +23,10 @@ * THE SOFTWARE. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "evsock.h" -#include "http_handler.h" +#include "acceltcp.h" -#define APP_NAME "acceltcp" -#define APP_DESCRIPTION "ACCELerate TCP proxy" -#define APP_VERSION "0.2" -#define APP_AUTHOR "Masaya YAMAMOTO " - -#define DEFAULT_SSL_CERITIFICATE_FILE "server.crt" -#define DEFAULT_SSL_PRIVATEKEY_FILE "server.key" - -#ifndef SOL_TCP -#define SOL_TCP IPPROTO_TCP -#endif - -#define ACCELTCP_TCP_KEEPIDLE 90 -#define ACCELTCP_TCP_KEEPINTVL 30 -#define ACCELTCP_TCP_KEEPCNT 6 - -#define ACCELTCP_HDR_MAGIC 0xacce1381 -#define ACCELTCP_HDR_FLG_SYN 0x0100 -#define ACCELTCP_HDR_FLG_FIN 0x0200 -#define ACCELTCP_HDR_FLG_RST 0x0300 - -#define DEBUG(fmt, ...) \ - do { \ - if (config.debug) { \ - fprintf(stderr, fmt, ## __VA_ARGS__); \ - } \ - } while (0); - -#define STRSAFEPRINT(x) ((x) ? (x) : "") - -#ifndef MIN -#define MIN(x, y) ((x) < (y) ? (x) : (y)) -#endif -#ifndef MAX -#define MAX(x, y) ((x) > (y) ? (x) : (y)) -#endif - -#define BACKLOG 1024 - -struct hdr { - uint32_t ___; - uint32_t xid; - uint16_t flg; - uint16_t len; -}; - -#define HDR_LEN (sizeof(struct hdr)) - -struct config_tunnel { - int ipv4only; - int ipv6only; - int http; - char *http_host; - int server; - int ssl_accept; - char *ssl_certificate; - char *ssl_privatekey; - int ssl_connect; - int rbuf; - int sbuf; - int connection_num; - char *self_addr; - char *self_port; - char *peer_addr; - char *peer_port; - struct config_tunnel *next; -}; - -struct config { - int debug; - int quiet; - int verbose; - struct config_tunnel *tunnels; -}; - -struct ssock { - struct evsock sock; - struct tunnel *tunnel; - struct ssock *next; -}; - -struct econn { - struct evsock sock; - struct { - http_parser parser; - struct http_handler_env env; - } http; - struct tunnel *tunnel; - struct session *session; - struct econn *next; -}; - -struct pconn { - int ready; - struct evsock sock; - struct tunnel *tunnel; - struct session *session; - struct pconn *next; -}; - -struct session { - uint32_t xid; - struct { - int closed; - struct buffer buf; - size_t bytes; - } e2p; - struct { - int closed; - struct buffer buf; - size_t bytes; - } p2e; - struct econn *econn; - struct pconn *pconn; -}; - -struct tunnel { - int id; - struct { - SSL_CTX *server_ctx; - SSL_CTX *client_ctx; - } ssl; - struct config_tunnel *config; - struct ssock *ssocks; - struct pconn *pconns; - struct tunnel *next; -}; - -static struct config config; -static struct tunnel *tunnels; +struct config config; +struct tunnel *tunnels; void hexdump (FILE *fp, void *data, size_t size) { @@ -800,7 +651,7 @@ pconn_pre_accept_cb (struct evsock *sock) { return &p->sock; } -static void +void usage (void) { printf("usage: %s [options] -- [tunnel_options] tunnel\n", APP_NAME); printf(" Options:\n"); @@ -882,7 +733,7 @@ strisdigit (const char *s) { return 1; } -static int +int option_parse_tunnel (char *s, struct config_tunnel *c) { char *p, *t[4]; size_t n; @@ -921,7 +772,7 @@ option_parse_tunnel (char *s, struct config_tunnel *c) { return 0; } -static int +int option_parse (int argc, char *argv[], struct config *config) { int opt; struct config_tunnel *c; @@ -956,8 +807,8 @@ option_parse (int argc, char *argv[], struct config *config) { config->debug = 1; break; case 'h': - usage(); - exit(EXIT_SUCCESS); + usage(); + return -2; case 'q': config->quiet = 1; break; @@ -966,7 +817,7 @@ option_parse (int argc, char *argv[], struct config *config) { break; case 'V': version(); - exit(EXIT_SUCCESS); + return -2; default: return -1; } @@ -1342,7 +1193,7 @@ tunnel_setup_pconns (struct ev_loop *loop, struct tunnel *tunnel) { return count; } -static struct tunnel * +struct tunnel * tunnel_setup (struct ev_loop *loop, struct config_tunnel *c) { struct tunnel *tunnel; int ret; @@ -1418,18 +1269,18 @@ print_pconn_status (void) { } } -static void +void timeout_cb (struct ev_loop *loop, struct ev_timer *w, int revents) { print_pconn_status(); } -static void +void signal_cb (struct ev_loop *loop, struct ev_signal *w, int revents) { print_pconn_status(); } int -main (int argc, char *argv[]) { +acceltcp (int argc, char *argv[]) { struct sigaction sig; struct ev_loop *loop; struct ev_signal signal_w; @@ -1443,8 +1294,12 @@ main (int argc, char *argv[]) { sigemptyset(&sig.sa_mask); sig.sa_flags= 0; sigaction(SIGPIPE, &sig, NULL); - if (option_parse(argc, argv, &config) == -1) { - usage(); + int option_parse_status = option_parse(argc, argv, &config); + if (option_parse_status != 0) { + if (option_parse_status == -2) { + return EXIT_SUCCESS; + } + usage(); return -1; } if (config.debug) { diff --git a/acceltcp.h b/acceltcp.h new file mode 100644 index 0000000..5a52985 --- /dev/null +++ b/acceltcp.h @@ -0,0 +1,209 @@ +/* + * AccelTCP (ACCELerate TCP proxy) + * + * Copyright (c) 2013,2014, KLab Inc. + * All rights reserved. + * + * 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 acceltcp_h +#define acceltcp_h +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "evsock.h" +#include "http_handler.h" + +#define APP_NAME "acceltcp" +#define APP_DESCRIPTION "ACCELerate TCP proxy" +#define APP_VERSION "0.2" +#define APP_AUTHOR "Masaya YAMAMOTO " + +#define DEFAULT_SSL_CERITIFICATE_FILE "server.crt" +#define DEFAULT_SSL_PRIVATEKEY_FILE "server.key" + +#ifndef SOL_TCP +#define SOL_TCP IPPROTO_TCP +#endif + +#define ACCELTCP_TCP_KEEPIDLE 90 +#define ACCELTCP_TCP_KEEPINTVL 30 +#define ACCELTCP_TCP_KEEPCNT 6 + +#define ACCELTCP_HDR_MAGIC 0xacce1381 +#define ACCELTCP_HDR_FLG_SYN 0x0100 +#define ACCELTCP_HDR_FLG_FIN 0x0200 +#define ACCELTCP_HDR_FLG_RST 0x0300 + +#define DEBUG(fmt, ...) \ + do { \ + if (config.debug) { \ + fprintf(stderr, fmt, ## __VA_ARGS__); \ + } \ + } while (0); + +#define STRSAFEPRINT(x) ((x) ? (x) : "") + +#ifndef MIN +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#endif +#ifndef MAX +#define MAX(x, y) ((x) > (y) ? (x) : (y)) +#endif + +#define BACKLOG 1024 + +struct hdr { + uint32_t ___; + uint32_t xid; + uint16_t flg; + uint16_t len; +}; + +#define HDR_LEN (sizeof(struct hdr)) + +struct config_tunnel { + int ipv4only; + int ipv6only; + int http; + char *http_host; + int server; + int ssl_accept; + char *ssl_certificate; + char *ssl_privatekey; + int ssl_connect; + int rbuf; + int sbuf; + int connection_num; + char *self_addr; + char *self_port; + char *peer_addr; + char *peer_port; + struct config_tunnel *next; +}; + +struct config { + int debug; + int quiet; + int verbose; + struct config_tunnel *tunnels; +}; + +struct ssock { + struct evsock sock; + struct tunnel *tunnel; + struct ssock *next; +}; + +struct econn { + struct evsock sock; + struct { + http_parser parser; + struct http_handler_env env; + } http; + struct tunnel *tunnel; + struct session *session; + struct econn *next; +}; + +struct pconn { + int ready; + struct evsock sock; + struct tunnel *tunnel; + struct session *session; + struct pconn *next; +}; + +struct session { + uint32_t xid; + struct { + int closed; + struct buffer buf; + size_t bytes; + } e2p; + struct { + int closed; + struct buffer buf; + size_t bytes; + } p2e; + struct econn *econn; + struct pconn *pconn; +}; + +struct tunnel { + int id; + struct { + SSL_CTX *server_ctx; + SSL_CTX *client_ctx; + } ssl; + struct config_tunnel *config; + struct ssock *ssocks; + struct pconn *pconns; + struct tunnel *next; +}; + +extern struct config config; +extern struct tunnel *tunnels; + +extern void +usage (void); + +extern int +option_parse_tunnel (char *s, struct config_tunnel *c); + +extern int +option_parse (int argc, char *argv[], struct config *config); + +extern struct tunnel * +tunnel_setup (struct ev_loop *loop, struct config_tunnel *c); + +extern void +timeout_cb (struct ev_loop *loop, struct ev_timer *w, int revents); + +extern void +signal_cb (struct ev_loop *loop, struct ev_signal *w, int revents); + +extern int +acceltcp (int argc, char *argv[]); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/acceltcp_main.c b/acceltcp_main.c new file mode 100644 index 0000000..a196ad8 --- /dev/null +++ b/acceltcp_main.c @@ -0,0 +1,31 @@ +/* + * AccelTCP (ACCELerate TCP proxy) + * + * Copyright (c) 2013,2014, KLab Inc. + * All rights reserved. + * + * 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 "acceltcp.h" + +int +main (int argc, char *argv[]) { + return acceltcp(argc, argv); +} diff --git a/evsock.c b/evsock.c index 6430e17..24ca936 100644 --- a/evsock.c +++ b/evsock.c @@ -58,6 +58,10 @@ void evsock_suspend (struct evsock *sock, int how) { + if (sock == NULL) { + return; + } + if (how & EVSOCK_HOW_RX) { sock->rx.suspend = 1; } @@ -69,6 +73,10 @@ evsock_suspend (struct evsock *sock, int how) { void evsock_wakeup (struct evsock *sock, int how) { + if (sock == NULL) { + return; + } + if (how & EVSOCK_HOW_RX) { sock->rx.suspend = 0; } @@ -525,6 +533,13 @@ evsock_write_handler (struct evsock *sock) { void evsock_handler (struct ev_loop *loop, struct ev_io *w, int revents) { + if (loop == NULL) { + return; + } + if (w == NULL) { + return; + } + struct evsock *sock; (void)loop; diff --git a/http_parser.c b/http_parser.c index a131a38..9e6ef71 100644 --- a/http_parser.c +++ b/http_parser.c @@ -575,6 +575,16 @@ size_t http_parser_execute (http_parser *parser, const char *data, size_t len) { + if (parser == NULL) { + return 0; + } + if (settings == NULL) { + return 0; + } + if (data == NULL) { + return 0; + } + char c, ch; int8_t unhex_val; const char *p = data; @@ -1950,6 +1960,10 @@ http_method_str (enum http_method m) void http_parser_init (http_parser *parser, enum http_parser_type t) { + if (parser == NULL) { + return; + } + void *data = parser->data; /* preserve application data */ memset(parser, 0, sizeof(*parser)); parser->data = data; diff --git a/http_parser.h b/http_parser.h index 1a91c23..6c7b277 100644 --- a/http_parser.h +++ b/http_parser.h @@ -275,14 +275,16 @@ struct http_parser_url { */ unsigned long http_parser_version(void); -void http_parser_init(http_parser *parser, enum http_parser_type type); +extern void +http_parser_init(http_parser *parser, enum http_parser_type type); -size_t http_parser_execute(http_parser *parser, - const http_parser_settings *settings, - const char *data, - size_t len); - +extern size_t +http_parser_execute(http_parser *parser, + const http_parser_settings *settings, + const char *data, + size_t len); + /* If http_should_keep_alive() in the on_headers_complete or * on_message_complete callback returns 0, then this should be diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..155f866 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,16 @@ +include_directories(${gtest_SOURCE_DIR}/include ..) +set(test_sources + test_acceltcp.cc + test_evsock.cc + test_http_handler.cc + test_http_parser.cc + ../acceltcp.c + ../evsock.c + ../http_handler.c + ../http_parser.c +) +add_executable(acceltcp_unittest ${test_sources}) +target_link_libraries(acceltcp_unittest gtest_main) +target_link_libraries(acceltcp_unittest ev) +target_link_libraries(acceltcp_unittest ssl) +target_link_libraries(acceltcp_unittest crypto) diff --git a/test/test_acceltcp.cc b/test/test_acceltcp.cc new file mode 100644 index 0000000..a73620b --- /dev/null +++ b/test/test_acceltcp.cc @@ -0,0 +1,69 @@ +#include +#include "gtest/gtest.h" + +extern "C" +{ +#include "acceltcp.h" +} + +// + +TEST(AcceltcpTest, AssertionTrue) { + ASSERT_EQ(1, 1); +} + + +TEST(AcceltcpTest, AcceltcpTest_00) { + int expected = -1; + int argc = 1; + char *argv[] = {"acceltcp_unittest"}; + int actual = acceltcp(argc, argv); + EXPECT_EQ(expected, actual); +} + + +TEST(AcceltcpTest, AcceltcpTest_01) { + int expected = 0; + int argc = 2; + char *argv[] = {"acceltcp_unittest", "-V"}; + int actual = acceltcp(argc, argv); + EXPECT_EQ(expected, actual); +} + + +TEST(AcceltcpTest, AcceltcpTest_02) { + int expected = -1; + int argc = 2; + char *argv[] = {"acceltcp_unittest", "-h"}; + int actual = acceltcp(argc, argv); + EXPECT_EQ(expected, actual); +} + + +TEST(AcceltcpTest, OptionParseTest_00) { + int expected = 0; + int argc = -1; + char *argv[] = {"acceltcp_unittest"}; + struct config config; + int actual = option_parse(argc, argv, &config); + EXPECT_EQ(expected, actual); +} + + +TEST(AcceltcpTest, OptionParseTunnelTest_00) { + int expected = -1; + char *s = ""; + struct config_tunnel c; + int actual = option_parse_tunnel(s, &c); + EXPECT_EQ(expected, actual); +} + + +TEST(AcceltcpTest, TunnelSetupTest_00) { + struct tunnel *expected = NULL; + struct ev_loop *loop = NULL; + struct config_tunnel c; + struct tunnel *actual = tunnel_setup(loop, &c); + EXPECT_EQ(expected, actual); +} + diff --git a/test/test_evsock.cc b/test/test_evsock.cc new file mode 100644 index 0000000..9cf7c7d --- /dev/null +++ b/test/test_evsock.cc @@ -0,0 +1,39 @@ +#include +#include "gtest/gtest.h" + +extern "C" +{ +#include "evsock.h" +} + +// + +TEST(EvsockTest, AssertionTrue) { + ASSERT_EQ(1, 1); +} + + +TEST(EvsockTest, EvsockHandlerTest_00) { + struct ev_loop *loop = NULL; + struct ev_io *w = NULL; + int revents; + evsock_handler(loop, w, revents); + EXPECT_EQ(1, 1); +} + + +TEST(EvsockTest, EvsockSuspendTest_00) { + struct evsock *sock = NULL; + int how; + evsock_suspend (sock, how); + EXPECT_EQ(1, 1); +} + + +TEST(EvsockTest, EvsockWakeupTest_00) { + struct evsock *sock = NULL; + int how; + evsock_wakeup (sock, how); + EXPECT_EQ(1, 1); +} + diff --git a/test/test_http_handler.cc b/test/test_http_handler.cc new file mode 100644 index 0000000..a85157c --- /dev/null +++ b/test/test_http_handler.cc @@ -0,0 +1,21 @@ +#include +#include "gtest/gtest.h" + +extern "C" +{ +#include "http_handler.h" +} + +// + +TEST(HttpHandlerTest, AssertionTrue) { + ASSERT_EQ(1, 1); +} + + +TEST(HttpHandlerTest, HttpRequestSettingsTest_00) { + struct http_parser_settings *expected = NULL; + struct http_parser_settings *actual = &http_request_settings; + ASSERT_NE(expected, actual); +} + diff --git a/test/test_http_parser.cc b/test/test_http_parser.cc new file mode 100644 index 0000000..8d26615 --- /dev/null +++ b/test/test_http_parser.cc @@ -0,0 +1,31 @@ +#include +#include "gtest/gtest.h" + +extern "C" +{ +#include "http_parser.h" +} + +// + +TEST(HttpParserTest, AssertionTrue) { + ASSERT_EQ(1, 1); +} + + +TEST(HttpParserTest, HttpParserInitTest_00) { + http_parser *parser = NULL; + enum http_parser_type type; + http_parser_init(parser, type); + ASSERT_EQ(1, 1); +} + + +TEST(HttpParserTest, HttpParserExecuteTest_00) { + http_parser *parser = NULL; + http_parser_settings *settings = NULL; + char *data = NULL; + size_t len; + size_t actual = http_parser_execute(parser, settings, data, len); + ASSERT_EQ(1, 1); +}