变更stream系列文件的名称,修正了部分编译错误
* 变更stream系列文件的名称为ssl_stream, tcp_stream等; * 变更stream.h为platform.h,因该文件为平台整体公用; * 修正了ssl_stream, ssl_sess_cache文件中的编译错误,部分实现的bug。 * 调整了tfe_future的路径,由平台实现改为公用组件。
This commit is contained in:
@@ -3,6 +3,7 @@ project(tfe)
|
|||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
set(CMAKE_C_STANDARD 11)
|
set(CMAKE_C_STANDARD 11)
|
||||||
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
||||||
add_subdirectory(vendor)
|
add_subdirectory(vendor)
|
||||||
add_subdirectory(common)
|
add_subdirectory(common)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
|
|
||||||
add_library(common src/tfe_stat.cpp src/tfe_utils.cpp)
|
add_library(common src/tfe_stat.cpp src/tfe_utils.cpp src/tfe_future.cpp)
|
||||||
target_include_directories(common PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
|
target_include_directories(common PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
|
||||||
target_link_libraries(common MESA_handle_logger)
|
target_link_libraries(common MESA_handle_logger)
|
||||||
|
|||||||
@@ -15,6 +15,13 @@
|
|||||||
|
|
||||||
#define ALLOC(type, number) ((type *)calloc(sizeof(type), number))
|
#define ALLOC(type, number) ((type *)calloc(sizeof(type), number))
|
||||||
|
|
||||||
|
#define TFE_STRUCT_ALLOC(struct_type) __extension__ \
|
||||||
|
({ \
|
||||||
|
((struct_type) * ) __struct_ptr; \
|
||||||
|
__struct_ptr = ((struct_type) *)malloc(sizeof((struct_type))); \
|
||||||
|
__struct_ptr; \
|
||||||
|
})
|
||||||
|
|
||||||
#define likely(expr) __builtin_expect((expr), 1)
|
#define likely(expr) __builtin_expect((expr), 1)
|
||||||
#define unlikely(expr) __builtin_expect((expr), 0)
|
#define unlikely(expr) __builtin_expect((expr), 0)
|
||||||
|
|
||||||
@@ -27,6 +34,33 @@ do { MESA_handle_runtime_log(handler, RLOG_LV_INFO, NULL, fmt, ##__VA_ARGS__); }
|
|||||||
#define TFE_LOG_DEBUG(handler, fmt, ...) \
|
#define TFE_LOG_DEBUG(handler, fmt, ...) \
|
||||||
do { MESA_handle_runtime_log(handler, RLOG_LV_DEBUG, NULL, fmt, ##__VA_ARGS__); } while(0) \
|
do { MESA_handle_runtime_log(handler, RLOG_LV_DEBUG, NULL, fmt, ##__VA_ARGS__); } while(0) \
|
||||||
|
|
||||||
|
#ifndef offsetof
|
||||||
|
/** Return the offset of a field in a structure. */
|
||||||
|
#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return pointer to the wrapping struct instance.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* struct wrapper {
|
||||||
|
* ...
|
||||||
|
* struct child c;
|
||||||
|
* ...
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* struct child *x = obtain(...);
|
||||||
|
* struct wrapper *w = container_of(x, struct wrapper, c);
|
||||||
|
*/
|
||||||
|
#ifndef container_of
|
||||||
|
#define container_of(ptr, type, member) __extension__ ({ \
|
||||||
|
const typeof(((type *)0)->member) *_ptr = (ptr); \
|
||||||
|
__attribute__((unused)) type *_target_ptr = (type *)(ptr); \
|
||||||
|
(type *)(((uintptr_t)_ptr) - offsetof(type, member)); \
|
||||||
|
})
|
||||||
|
#endif
|
||||||
|
|
||||||
int addr_sock_to_layer(struct sockaddr * sock_addr, int sockaddrlen, struct layer_addr * layer_addr);
|
int addr_sock_to_layer(struct sockaddr * sock_addr, int sockaddrlen, struct layer_addr * layer_addr);
|
||||||
int addr_layer_to_sock(struct layer_addr * layer_addr, struct sockaddr * sock_addr);
|
int addr_layer_to_sock(struct layer_addr * layer_addr, struct sockaddr * sock_addr);
|
||||||
char* tfe_strdup(const char* s);
|
char* tfe_strdup(const char* s);
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
add_executable(tfe src/cert.cpp src/future.cpp src/kni.cpp src/tfe_stream.cpp src/main.cpp src/proxy.cpp)
|
add_executable(tfe src/key_keeper.cpp src/kni_acceptor.cpp src/ssl_stream.cpp src/ssl_sess_cache.cpp
|
||||||
|
src/tcp_stream.cpp src/main.cpp src/proxy.cpp)
|
||||||
|
|
||||||
target_include_directories(tfe PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include/external)
|
target_include_directories(tfe PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include/external)
|
||||||
target_include_directories(tfe PRIVATE ${CMAKE_CURRENT_LIST_DIR}/include/internal)
|
target_include_directories(tfe PRIVATE ${CMAKE_CURRENT_LIST_DIR}/include/internal)
|
||||||
|
|
||||||
target_link_libraries(tfe common)
|
target_link_libraries(tfe common)
|
||||||
target_link_libraries(tfe pthread dl openssl-ssl-static openssl-crypto-static pthread libevent-static
|
target_link_libraries(tfe pthread dl openssl-ssl-static openssl-crypto-static pthread libevent-static
|
||||||
libevent-static-openssl libevent-static-pthreads MESA_handle_logger MESA_prof_load wiredcfg)
|
libevent-static-openssl libevent-static-pthreads MESA_handle_logger MESA_prof_load MESA_htable wiredcfg)
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#ifndef CERT_H
|
#pragma once
|
||||||
#define CERT_H
|
|
||||||
|
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <tfe_future.h>
|
||||||
|
|
||||||
struct keyring
|
struct keyring
|
||||||
{
|
{
|
||||||
@@ -16,6 +16,5 @@ struct key_keeper * key_keeper_destroy(struct key_keeper *keeper);
|
|||||||
|
|
||||||
struct keyring* key_keeper_release_cert(future_result_t* result);
|
struct keyring* key_keeper_release_cert(future_result_t* result);
|
||||||
void key_keeper_free_keyring(struct keyring* cert);
|
void key_keeper_free_keyring(struct keyring* cert);
|
||||||
void key_keeper_async_ask(struct future * f, struct key_keeper * keeper, int keyring_id,
|
void key_keeper_async_ask(struct future * f, struct key_keeper * keeper, int keyring_id,
|
||||||
X509 * origin_cert, int is_cert_valid, struct event_base * evbase);
|
X509 * origin_cert, int is_cert_valid, struct event_base * evbase);
|
||||||
#endif /* !CERT_H */
|
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
|
|
||||||
#include <tfe_stream.h>
|
#include <tfe_stream.h>
|
||||||
#include <tfe_stat.h>
|
#include <tfe_stat.h>
|
||||||
#include <cert.h>
|
#include <tfe_future.h>
|
||||||
|
#include <proxy.h>
|
||||||
|
|
||||||
struct tfe_thread_ctx
|
struct tfe_thread_ctx
|
||||||
{
|
{
|
||||||
@@ -26,26 +27,6 @@ struct tfe_thread_ctx
|
|||||||
const struct tfe_plugin * modules;
|
const struct tfe_plugin * modules;
|
||||||
};
|
};
|
||||||
|
|
||||||
//Downstream: comunication form client to proxy
|
|
||||||
//Upstream: communication form proxy to server
|
|
||||||
struct ssl_downstream
|
|
||||||
{
|
|
||||||
/* server name indicated by client in SNI TLS extension */
|
|
||||||
char * sni;
|
|
||||||
SSL * ssl;
|
|
||||||
X509 * fake_cert_ref;//?
|
|
||||||
int keyring_id;
|
|
||||||
struct future * future_sni_peek;
|
|
||||||
struct future * future_get_cert;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ssl_upstream
|
|
||||||
{
|
|
||||||
X509 * orig_cert;
|
|
||||||
SSL * ssl;
|
|
||||||
struct future * conn_ssl_srv;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum tfe_plugin_state
|
enum tfe_plugin_state
|
||||||
{
|
{
|
||||||
PLUG_STATE_READONLY,
|
PLUG_STATE_READONLY,
|
||||||
@@ -78,22 +59,18 @@ struct tfe_conn_private
|
|||||||
struct tfe_stream_private
|
struct tfe_stream_private
|
||||||
{
|
{
|
||||||
struct tfe_stream head;
|
struct tfe_stream head;
|
||||||
struct tfe_proxy *proxy;
|
struct tfe_proxy * proxy_ref;
|
||||||
|
struct tfe_thread_ctx * thread_ref;
|
||||||
|
|
||||||
enum tfe_session_proto session_type;
|
enum tfe_session_proto session_type;
|
||||||
struct tfe_conn_private conn_upstream;
|
struct tfe_conn_private * conn_upstream;
|
||||||
struct tfe_conn_private conn_downstream;
|
struct tfe_conn_private * conn_downstream;
|
||||||
|
|
||||||
union
|
struct
|
||||||
{
|
{
|
||||||
struct ssl_downstream * ssl_downstream;
|
struct ssl_mgr * ssl_mgr;
|
||||||
void * raw_downstream;
|
struct ssl_stream * ssl_downstream;
|
||||||
};
|
struct ssl_stream * ssl_upstream;
|
||||||
|
|
||||||
union
|
|
||||||
{
|
|
||||||
struct ssl_upstream * ssl_upstream;
|
|
||||||
void * raw_upstream;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t is_plugin_opened;
|
uint8_t is_plugin_opened;
|
||||||
@@ -109,15 +86,17 @@ struct tfe_stream_private
|
|||||||
struct plugin_ctx * plug_ctx;
|
struct plugin_ctx * plug_ctx;
|
||||||
unsigned char passthrough; /* 1 if SSL passthrough is active */
|
unsigned char passthrough; /* 1 if SSL passthrough is active */
|
||||||
|
|
||||||
evutil_socket_t fd_downstream;
|
/* For defer connection setup */
|
||||||
evutil_socket_t fd_upstream;
|
evutil_socket_t defer_fd_downstream;
|
||||||
|
evutil_socket_t defer_fd_upstream;
|
||||||
|
|
||||||
struct tfe_thread_ctx * thrmgr_ref;
|
/* ASYNC UPSTREAM */
|
||||||
future * async_future;
|
future * future_upstream_create;
|
||||||
|
/* ASYNC DOWNSTREAM */
|
||||||
|
future * future_downstream_create;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tfe_stream_private * tfe_stream_create(evutil_socket_t fd_downstream, evutil_socket_t fd_upstream,
|
static inline void * __STREAM_LOGGER(struct tfe_stream_private * _stream)
|
||||||
enum tfe_session_proto session_type, tfe_thread_ctx * thread);
|
{
|
||||||
|
return _stream->proxy_ref->main_logger;
|
||||||
void tfe_stream_setup(struct tfe_stream_private * _stream);
|
}
|
||||||
|
|
||||||
@@ -2,8 +2,32 @@
|
|||||||
|
|
||||||
#include <tfe_stream.h>
|
#include <tfe_stream.h>
|
||||||
#include <event2/event.h>
|
#include <event2/event.h>
|
||||||
|
#include <ssl_stream.h>
|
||||||
|
|
||||||
|
struct ssl_mgr;
|
||||||
|
struct key_keeper;
|
||||||
|
|
||||||
|
struct tfe_proxy
|
||||||
|
{
|
||||||
|
char name[TFE_SYMBOL_MAX];
|
||||||
|
struct event_base * evbase;
|
||||||
|
struct event * sev[8];
|
||||||
|
struct event * gcev;
|
||||||
|
|
||||||
|
struct tfe_config * opts;
|
||||||
|
void * main_logger;
|
||||||
|
|
||||||
|
unsigned int nr_work_threads;
|
||||||
|
struct tfe_thread_ctx * work_threads;
|
||||||
|
|
||||||
|
unsigned int nr_modules;
|
||||||
|
struct tfe_plugin * modules;
|
||||||
|
void * io_mod;
|
||||||
|
|
||||||
|
struct ssl_mgr * ssl_mgr_handler;
|
||||||
|
struct key_keeper * key_keeper_handler;
|
||||||
|
};
|
||||||
|
|
||||||
struct tfe_proxy;
|
|
||||||
struct tfe_proxy_accept_para
|
struct tfe_proxy_accept_para
|
||||||
{
|
{
|
||||||
/* Both upstream and downstream FDs */
|
/* Both upstream and downstream FDs */
|
||||||
@@ -17,3 +41,4 @@ struct tfe_proxy_accept_para
|
|||||||
struct tfe_proxy * tfe_proxy_new(const char * profile);
|
struct tfe_proxy * tfe_proxy_new(const char * profile);
|
||||||
int tfe_proxy_fds_accept(struct tfe_proxy * ctx, const struct tfe_proxy_accept_para * para);
|
int tfe_proxy_fds_accept(struct tfe_proxy * ctx, const struct tfe_proxy_accept_para * para);
|
||||||
void tfe_proxy_run(struct tfe_proxy * proxy);
|
void tfe_proxy_run(struct tfe_proxy * proxy);
|
||||||
|
|
||||||
|
|||||||
16
platform/include/internal/ssl_sess_cache.h
Normal file
16
platform/include/internal/ssl_sess_cache.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <tfe_stream.h>
|
||||||
|
|
||||||
|
struct sess_cache;
|
||||||
|
struct sess_cache * ssl_sess_cache_create(unsigned int slot_size, unsigned int expire_seconds, enum tfe_conn_dir served);
|
||||||
|
void ssl_sess_cache_destroy(struct sess_cache * cache);
|
||||||
|
|
||||||
|
void up_session_set(struct sess_cache * cache, struct sockaddr * addr, socklen_t addr_len, const char * sni, SSL_SESSION * value);
|
||||||
|
SSL_SESSION * up_session_get(struct sess_cache * cache, struct sockaddr * addr, socklen_t addr_len, const char * sni);
|
||||||
|
|
||||||
|
void down_session_set(struct sess_cache * cache, const SSL_SESSION * sess);
|
||||||
|
void down_session_del(struct sess_cache * cache, const SSL_SESSION * sess);
|
||||||
|
SSL_SESSION * down_session_get(struct sess_cache * cache, const unsigned char * id, int idlen);
|
||||||
@@ -1,22 +1,29 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <event2/event.h>
|
#include <event2/event.h>
|
||||||
#include <tfe_future.h>
|
#include <tfe_future.h>
|
||||||
#include <field_stat2.h>
|
|
||||||
|
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
#include <openssl/x509.h>
|
||||||
|
#include <openssl/x509v3.h>
|
||||||
|
|
||||||
|
#include <MESA/field_stat2.h>
|
||||||
|
|
||||||
struct ssl_stream;
|
struct ssl_stream;
|
||||||
|
|
||||||
struct ssl_mgr;
|
struct ssl_mgr;
|
||||||
struct ssl_mgr* ssl_manager_init(const char* ini_profile, const char* section, struct event_base *evbase, void* logger, screen_stat_handle_t* fs);
|
struct ssl_mgr * ssl_manager_init(const char * ini_profile, const char * section, struct event_base * evbase,
|
||||||
void ssl_manager_destroy(struct ssl_mgr* mgr);
|
void * logger, screen_stat_handle_t * fs);
|
||||||
|
void ssl_manager_destroy(struct ssl_mgr * mgr);
|
||||||
|
|
||||||
struct ssl_stream* ssl_upstream_create_result_release_stream(future_result_t* result);
|
struct ssl_stream * ssl_upstream_create_result_release_stream(future_result_t * result);
|
||||||
struct bufferevent* ssl_upstream_create_result_release_bev(future_result_t* result);
|
struct bufferevent * ssl_upstream_create_result_release_bev(future_result_t * result);
|
||||||
void ssl_async_upstream_create(struct future* f, struct ssl_mgr* mgr, evutil_socket_t fd_upstream, evutil_socket_t fd_downstream, struct event_base *evbase);
|
void ssl_async_upstream_create(struct future * f, struct ssl_mgr * mgr, evutil_socket_t fd_upstream,
|
||||||
|
evutil_socket_t fd_downstream, struct event_base * evbase);
|
||||||
struct ssl_stream* ssl_downstream_create_result_release_stream(future_result_t* result);
|
|
||||||
struct bufferevent* ssl_downstream_create_result_release_bev(future_result_t* result);
|
|
||||||
void ssl_async_downstream_create(struct future* f, struct ssl_mgr* mgr, struct ssl_stream* upstream, evutil_socket_t fd_downstream, int keyring_id, struct event_base *evbase);
|
|
||||||
|
|
||||||
void ssl_stream_free_and_close_fd(struct ssl_stream* stream, struct event_base *evbase, evutil_socket_t fd);
|
|
||||||
|
|
||||||
|
struct ssl_stream * ssl_downstream_create_result_release_stream(future_result_t * result);
|
||||||
|
struct bufferevent * ssl_downstream_create_result_release_bev(future_result_t * result);
|
||||||
|
void ssl_async_downstream_create(struct future * f, struct ssl_mgr * mgr, struct ssl_stream * upstream,
|
||||||
|
evutil_socket_t fd_downstream, int keyring_id, struct event_base * evbase);
|
||||||
|
void ssl_stream_free_and_close_fd(struct ssl_stream * stream, struct event_base * evbase, evutil_socket_t fd);
|
||||||
|
|||||||
8
platform/include/internal/tcp_stream.h
Normal file
8
platform/include/internal/tcp_stream.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <platform.h>
|
||||||
|
|
||||||
|
struct tfe_stream * tfe_stream_create(struct tfe_proxy * pxy, struct tfe_thread_ctx * thread_ctx);
|
||||||
|
void tfe_stream_init_by_fds(struct tfe_stream * stream, enum tfe_session_proto session_type,
|
||||||
|
evutil_socket_t fd_downstream, evutil_socket_t fd_upstream);
|
||||||
|
void tfe_stream_destory(struct tfe_stream_private * stream);
|
||||||
@@ -5,15 +5,18 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/errno.h>
|
#include <sys/errno.h>
|
||||||
|
|
||||||
#include <MESA/MESA_prof_load.h>
|
|
||||||
#include <tfe_stream.h>
|
|
||||||
#include <evutil.h>
|
|
||||||
#include <event2/listener.h>
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <event2/listener.h>
|
||||||
|
#include <event2/util.h>
|
||||||
|
|
||||||
|
#include <MESA/MESA_prof_load.h>
|
||||||
|
|
||||||
|
#include <tfe_stream.h>
|
||||||
|
#include <kni_acceptor.h>
|
||||||
#include <proxy.h>
|
#include <proxy.h>
|
||||||
#include <kni.h>
|
#include <platform.h>
|
||||||
|
|
||||||
#ifndef TFE_CONFIG_KNI_UXDOMAIN_PATH_DEFAULT
|
#ifndef TFE_CONFIG_KNI_UXDOMAIN_PATH_DEFAULT
|
||||||
#define TFE_CONFIG_KNI_UXDOMAIN_PATH_DEFAULT "/var/run/.tfe_kni_acceptor_handler"
|
#define TFE_CONFIG_KNI_UXDOMAIN_PATH_DEFAULT "/var/run/.tfe_kni_acceptor_handler"
|
||||||
@@ -24,34 +24,14 @@
|
|||||||
#include <MESA/MESA_handle_logger.h>
|
#include <MESA/MESA_handle_logger.h>
|
||||||
#include <tfe_utils.h>
|
#include <tfe_utils.h>
|
||||||
#include <tfe_stream.h>
|
#include <tfe_stream.h>
|
||||||
#include <stream.h>
|
#include <platform.h>
|
||||||
#include <proxy.h>
|
#include <proxy.h>
|
||||||
#include <sescache.h>
|
#include <kni_acceptor.h>
|
||||||
#include <kni.h>
|
#include <tcp_stream.h>
|
||||||
|
|
||||||
static int signals[] = {SIGTERM, SIGQUIT, SIGHUP, SIGINT, SIGPIPE, SIGUSR1};
|
static int signals[] = {SIGTERM, SIGQUIT, SIGHUP, SIGINT, SIGPIPE, SIGUSR1};
|
||||||
|
|
||||||
struct tfe_proxy
|
|
||||||
{
|
|
||||||
char name[TFE_SYMBOL_MAX];
|
|
||||||
struct event_base * evbase;
|
|
||||||
struct event * sev[sizeof(signals) / sizeof(int)];
|
|
||||||
struct event * gcev;
|
|
||||||
|
|
||||||
struct tfe_config * opts;
|
|
||||||
void * main_logger;
|
|
||||||
|
|
||||||
struct sess_cache * dsess_cache;
|
|
||||||
struct sess_cache * ssess_cache;
|
|
||||||
|
|
||||||
unsigned int nr_work_threads;
|
|
||||||
struct tfe_thread_ctx * work_threads;
|
|
||||||
|
|
||||||
unsigned int nr_modules;
|
|
||||||
struct tfe_plugin * modules;
|
|
||||||
|
|
||||||
void * io_mod;
|
|
||||||
};
|
|
||||||
|
|
||||||
const char * module_name_pxy = "TFE_PXY";
|
const char * module_name_pxy = "TFE_PXY";
|
||||||
extern struct tfe_instance * g_tfe_instance;
|
extern struct tfe_instance * g_tfe_instance;
|
||||||
@@ -142,14 +122,10 @@ int tfe_proxy_fds_accept(struct tfe_proxy * ctx, const struct tfe_proxy_accept_p
|
|||||||
unsigned int worker_tid = select_work_thread(ctx);
|
unsigned int worker_tid = select_work_thread(ctx);
|
||||||
tfe_thread_ctx * worker_thread_ctx = &ctx->work_threads[worker_tid];
|
tfe_thread_ctx * worker_thread_ctx = &ctx->work_threads[worker_tid];
|
||||||
|
|
||||||
struct tfe_stream_private * stream = tfe_stream_create(para->upstream_fd,
|
struct tfe_stream * stream = tfe_stream_create(ctx, worker_thread_ctx);
|
||||||
para->downstream_fd, para->session_type, worker_thread_ctx);
|
tfe_stream_init_by_fds(stream, para->session_type, para->downstream_fd, para->upstream_fd);
|
||||||
|
|
||||||
if (stream == NULL) goto __errout;
|
return 0;
|
||||||
tfe_stream_setup(stream);
|
|
||||||
|
|
||||||
__errout:
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -169,9 +145,6 @@ struct tfe_proxy * tfe_proxy_new(const char * profile)
|
|||||||
event_enable_debug_mode();
|
event_enable_debug_mode();
|
||||||
|
|
||||||
proxy->evbase = event_base_new();
|
proxy->evbase = event_base_new();
|
||||||
proxy->dsess_cache = session_cache_init();
|
|
||||||
proxy->ssess_cache = session_cache_init();
|
|
||||||
|
|
||||||
proxy->nr_modules = 2;
|
proxy->nr_modules = 2;
|
||||||
proxy->modules = ALLOC(struct tfe_plugin, proxy->nr_modules);
|
proxy->modules = ALLOC(struct tfe_plugin, proxy->nr_modules);
|
||||||
|
|
||||||
@@ -185,8 +158,6 @@ struct tfe_proxy * tfe_proxy_new(const char * profile)
|
|||||||
{
|
{
|
||||||
proxy->work_threads[i].thread_id = i;
|
proxy->work_threads[i].thread_id = i;
|
||||||
proxy->work_threads[i].evbase = event_base_new();
|
proxy->work_threads[i].evbase = event_base_new();
|
||||||
proxy->work_threads[i].dsess_cache = proxy->dsess_cache;
|
|
||||||
proxy->work_threads[i].ssess_cache = proxy->ssess_cache;
|
|
||||||
proxy->work_threads[i].nr_modules = proxy->nr_modules;
|
proxy->work_threads[i].nr_modules = proxy->nr_modules;
|
||||||
proxy->work_threads[i].modules = proxy->modules;
|
proxy->work_threads[i].modules = proxy->modules;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,72 +2,85 @@
|
|||||||
|
|
||||||
#include <ssl_sess_cache.h>
|
#include <ssl_sess_cache.h>
|
||||||
#include <ssl.h>
|
#include <ssl.h>
|
||||||
#include <MESA_htable.h>
|
|
||||||
#include <field_stat2.h>
|
|
||||||
|
|
||||||
#define SESS_CACHE_NOT_FOUND -1
|
#include <MESA/MESA_htable.h>
|
||||||
#define SESS_CACHE_FOUND 0
|
#include <MESA/field_stat2.h>
|
||||||
#define SESS_CACHE_UPDATE_OLD 1
|
|
||||||
#define SESS_CACHE_ADD_NEW 2
|
#define SESS_CACHE_NOT_FOUND -1
|
||||||
#define SESS_CACHE_INVALID 3
|
#define SESS_CACHE_FOUND 0
|
||||||
|
#define SESS_CACHE_UPDATE_OLD 1
|
||||||
|
#define SESS_CACHE_ADD_NEW 2
|
||||||
|
#define SESS_CACHE_INVALID 3
|
||||||
|
|
||||||
struct asn1_sess
|
struct asn1_sess
|
||||||
{
|
{
|
||||||
unsigned char* buff;
|
unsigned char * buff;
|
||||||
size_t size;
|
size_t size;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sess_set_args
|
struct sess_set_args
|
||||||
{
|
{
|
||||||
MESA_htable_handle hash;
|
MESA_htable_handle hash;
|
||||||
struct asn1_sess* new_sess;
|
struct asn1_sess * new_sess;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sess_cache
|
struct sess_cache
|
||||||
{
|
{
|
||||||
enum tfe_conn_dir served_for;
|
enum tfe_conn_dir served_for;
|
||||||
MESA_htable_handle hash;
|
MESA_htable_handle hash;
|
||||||
long long hit_cnt, miss_cnt,del_err;
|
long long hit_cnt, miss_cnt, del_err;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void ssl_sess_free_serialized(void *data)
|
static void ssl_sess_free_serialized(void * data)
|
||||||
{
|
{
|
||||||
struct asn1_sess* p=(struct asn1_sess*)data;
|
struct asn1_sess * p = (struct asn1_sess *) data;
|
||||||
free(p->buff);
|
free(p->buff);
|
||||||
p->size=0;
|
p->size = 0;
|
||||||
free(p);
|
free(p);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
static struct asn1_sess* ssl_sess_serialize(SSL_SESSION *sess)
|
|
||||||
|
static struct asn1_sess * ssl_sess_serialize(SSL_SESSION * sess)
|
||||||
{
|
{
|
||||||
struct asn1_sess* result=ALLOC(struct asn1_sess,1);
|
struct asn1_sess * result = ALLOC(struct asn1_sess, 1);
|
||||||
result->size = i2d_SSL_SESSION(sess, NULL);
|
|
||||||
/*When using i2d_SSL_SESSION(), the memory location pointed to by pp must be large enough to hold the binary representation of the session.
|
int __i2d_size = i2d_SSL_SESSION(sess, NULL);
|
||||||
There is no known limit on the size of the created ASN1 representation, so the necessary amount of space should be obtained by first calling
|
result->size = (size_t) __i2d_size;
|
||||||
i2d_SSL_SESSION() with pp=NULL, and obtain the size needed, then allocate the memory and call i2d_SSL_SESSION() again.*/
|
assert(__i2d_size > 0);
|
||||||
result->buff=ALLOC(unsigned char,result->size);
|
|
||||||
|
/* When using i2d_SSL_SESSION(), the memory location pointed to by pp must be large enough to
|
||||||
|
* hold the binary representation of the session. There is no known limit on the size of the
|
||||||
|
* created ASN1 representation, so the necessary amount of space should be obtained by first
|
||||||
|
* calling i2d_SSL_SESSION() with pp=NULL, and obtain the size needed,
|
||||||
|
* then allocate the memory and call i2d_SSL_SESSION() again.*/
|
||||||
|
|
||||||
|
result->buff = ALLOC(unsigned char, result->size);
|
||||||
i2d_SSL_SESSION(sess, &(result->buff));
|
i2d_SSL_SESSION(sess, &(result->buff));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
static SSL_SESSION * ssl_sess_deserialize(const struct asn1_sess* asn1)
|
|
||||||
|
static SSL_SESSION * ssl_sess_deserialize(const struct asn1_sess * asn1)
|
||||||
{
|
{
|
||||||
SSL_SESSION *sess=NULL;
|
SSL_SESSION * sess = NULL;
|
||||||
sess = d2i_SSL_SESSION(NULL, &(asn1->buff), asn1->size); /* increments asn1 */
|
d2i_SSL_SESSION(&sess, (const unsigned char **) &(asn1->buff), (long) asn1->size); /* increments asn1 */
|
||||||
return sess;
|
return sess;
|
||||||
}
|
}
|
||||||
static int ssl_sess_varify_cb(void *data, int eliminate_type)
|
|
||||||
|
static int ssl_sess_verify_cb(void * data, int eliminate_type)
|
||||||
{
|
{
|
||||||
SSL_SESSION *sess=NULL;
|
const struct asn1_sess * asn1 = (struct asn1_sess *) data;
|
||||||
int ret=0;
|
if (eliminate_type == ELIMINATE_TYPE_NUM)
|
||||||
const struct asn1_sess* asn1=(struct asn1_sess*)data;
|
|
||||||
if(eliminate_type==ELIMINATE_TYPE_NUM)
|
|
||||||
{
|
{
|
||||||
return 1; //direct expired.
|
return 1; //direct expired.
|
||||||
}
|
}
|
||||||
sess=ssl_sess_deserialize(asn1);
|
|
||||||
ret=ssl_session_is_valid(sess);
|
SSL_SESSION * sess = ssl_sess_deserialize(asn1);
|
||||||
|
int ret = ssl_session_is_valid(sess);
|
||||||
SSL_SESSION_free(sess);
|
SSL_SESSION_free(sess);
|
||||||
if(ret==0)
|
|
||||||
|
if (ret == 0)
|
||||||
{
|
{
|
||||||
return 1; //should be expired (deleted).
|
return 1; //should be expired (deleted).
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -75,126 +88,134 @@ static int ssl_sess_varify_cb(void *data, int eliminate_type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static long sess_cache_get_cb(void *data, const uchar *key, uint size, void *user_arg)
|
static long sess_cache_get_cb(void * data, const uchar * key, uint size, void * user_arg)
|
||||||
{
|
{
|
||||||
SSL_SESSION *sess=NULL;
|
SSL_SESSION * sess = NULL;
|
||||||
int is_valid=0;
|
int is_valid = 0;
|
||||||
if(data==NULL)
|
if (data == NULL)
|
||||||
{
|
{
|
||||||
return SESS_CACHE_NOT_FOUND;
|
return SESS_CACHE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
const struct asn1_sess* asn1=(struct asn1_sess*)data;
|
|
||||||
sess=ssl_sess_deserialize(data,asn1);
|
const struct asn1_sess * asn1 = (struct asn1_sess *) data;
|
||||||
is_valid=ssl_session_is_valid(sess);
|
sess = ssl_sess_deserialize(asn1);
|
||||||
if(is_valid==0)
|
is_valid = ssl_session_is_valid(sess);
|
||||||
|
|
||||||
|
if (is_valid == 0)
|
||||||
{
|
{
|
||||||
SSL_SESSION_free(sess);
|
SSL_SESSION_free(sess);
|
||||||
return SESS_CACHE_INVALID;
|
return SESS_CACHE_INVALID;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*(SSL_SESSION **)user_arg=sess;
|
*(SSL_SESSION **) user_arg = sess;
|
||||||
return SESS_CACHE_FOUND;
|
return SESS_CACHE_FOUND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static long sess_cache_set_cb(void *data, const uchar *key, uint size, void *user_arg)
|
static long sess_cache_set_cb(void * data, const uchar * key, uint size, void * user_arg)
|
||||||
{
|
{
|
||||||
|
struct sess_set_args * args = (struct sess_set_args *) user_arg;
|
||||||
struct sess_set_args* args=(struct sess_set_args*)user_arg;
|
struct asn1_sess * new_asn1 = args->new_sess;
|
||||||
struct asn1_sess* new_asn1=args->new_sess;
|
struct asn1_sess * cur_asn1 = (struct asn1_sess *) data;
|
||||||
struct asn1_sess *cur_asn1=(struct asn1_sess*)data;
|
|
||||||
int ret=0;
|
int ret = 0;
|
||||||
if(cur_asn1!=NULL)
|
if (cur_asn1 != NULL)
|
||||||
{
|
{
|
||||||
free(cur_asn1->buff);
|
free(cur_asn1->buff);
|
||||||
cur_asn1->size=new_asn1->size;
|
cur_asn1->size = new_asn1->size;
|
||||||
cur_asn1->buff=ALLOC(unsigned char, cur_asn1->size);
|
cur_asn1->buff = ALLOC(unsigned char, cur_asn1->size);
|
||||||
memcpy(cur_asn1->buff,new_asn1->buff,cur_asn1->size);
|
memcpy(cur_asn1->buff, new_asn1->buff, cur_asn1->size);
|
||||||
return SESS_CACHE_UPDATE_OLD;
|
return SESS_CACHE_UPDATE_OLD;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ret=MESA_htable_add(args->hash, key, size, new_asn1);
|
ret = MESA_htable_add(args->hash, key, size, new_asn1);
|
||||||
assert(ret>=0);
|
assert(ret >= 0);
|
||||||
return SESS_CACHE_ADD_NEW;
|
return SESS_CACHE_ADD_NEW;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int upsess_mk_key(struct sockaddr * addr, socklen_t addr_len, const char* sni, unsigned char** key_buf)
|
static size_t upsess_mk_key(struct sockaddr * addr, socklen_t addrlen, const char * sni, unsigned char ** key_buf)
|
||||||
{
|
{
|
||||||
size_t key_size=0;
|
size_t key_size = 0;
|
||||||
unsigned char* tmp=NULL, p=NULL;
|
unsigned char * tmp = NULL;
|
||||||
size_t tmp_size;
|
size_t tmp_size;
|
||||||
dynbuf_t tmp, *db;
|
|
||||||
short port;
|
short port;
|
||||||
size_t snilen;
|
size_t snilen;
|
||||||
|
|
||||||
switch (((struct sockaddr_storage *)addr)->ss_family) {
|
switch (addr->sa_family)
|
||||||
|
{
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
tmp = (unsigned char *)
|
tmp = (unsigned char *)&((struct sockaddr_in *) addr)->sin_addr;
|
||||||
&((struct sockaddr_in*)addr)->sin_addr;
|
|
||||||
tmp_size = sizeof(struct in_addr);
|
tmp_size = sizeof(struct in_addr);
|
||||||
port = ((struct sockaddr_in*)addr)->sin_port;
|
port = ((struct sockaddr_in *) addr)->sin_port;
|
||||||
break;
|
break;
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
tmp = (unsigned char *)
|
tmp = (unsigned char *)&((struct sockaddr_in6 *) addr)->sin6_addr;
|
||||||
&((struct sockaddr_in6*)addr)->sin6_addr;
|
|
||||||
tmp_size = sizeof(struct in6_addr);
|
tmp_size = sizeof(struct in6_addr);
|
||||||
port = ((struct sockaddr_in6*)addr)->sin6_port;
|
port = ((struct sockaddr_in6 *) addr)->sin6_port;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
//should never happens.
|
//should never happens.
|
||||||
assert(0);
|
assert(0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
snilen = sni ? strlen(sni) : 0;
|
|
||||||
key_size=tmp_size+sizeof(port)+snilen;
|
|
||||||
*key_buf=ALLOC(unsigned char, key_size);
|
|
||||||
p=*key_buff;
|
|
||||||
memcpy(p,tmp,tmp_size);
|
|
||||||
p+=tmp_size;
|
|
||||||
memcpy(p, (char*)&port, sizeof(port));
|
|
||||||
p+=sizeof(port);
|
|
||||||
return key_size;
|
|
||||||
|
|
||||||
|
snilen = sni ? strlen(sni) : 0;
|
||||||
|
key_size = tmp_size + sizeof(port) + snilen;
|
||||||
|
|
||||||
|
*key_buf = ALLOC(unsigned char, key_size);
|
||||||
|
unsigned char * p = *key_buf;
|
||||||
|
|
||||||
|
memcpy(p, tmp, tmp_size);
|
||||||
|
p += tmp_size;
|
||||||
|
memcpy(p, (char *) &port, sizeof(port));
|
||||||
|
p += sizeof(port);
|
||||||
|
return key_size;
|
||||||
}
|
}
|
||||||
void up_session_set(struct sess_cache* cache, struct sockaddr * addr, socklen_t addr_len, const char* sni, SSL_SESSION * sess)
|
|
||||||
|
void up_session_set(struct sess_cache * cache, struct sockaddr * addr, socklen_t addr_len, const char * sni,
|
||||||
|
SSL_SESSION * sess)
|
||||||
{
|
{
|
||||||
char* key=NULL;
|
unsigned char * key = NULL;
|
||||||
int ret=0;
|
int ret = 0;
|
||||||
size_t key_size=0;
|
size_t key_size = 0;
|
||||||
long cb_ret=0;
|
long cb_ret = 0;
|
||||||
void* no_use=NULL;
|
void * no_use = NULL;
|
||||||
assert(cache->served_for==CONN_DIR_UPSTREAM);
|
assert(cache->served_for == CONN_DIR_UPSTREAM);
|
||||||
key_size=upsess_mk_key(addr, addr_len, sni, &key);
|
key_size = upsess_mk_key(addr, addr_len, sni, &key);
|
||||||
struct asn1_sess* asn1=NULL;
|
|
||||||
asn1=ssl_sess_serialize(sess);
|
struct asn1_sess * asn1 = NULL;
|
||||||
|
asn1 = ssl_sess_serialize(sess);
|
||||||
|
|
||||||
struct sess_set_args set_args;
|
struct sess_set_args set_args;
|
||||||
set_args.hash=cache->hash;
|
set_args.hash = cache->hash;
|
||||||
set_args.new_sess=asn1;
|
set_args.new_sess = asn1;
|
||||||
no_use=MESA_htable_search_cb(cache->hash, key, key_size, sess_cache_set_cb, &set_args,&cb_ret);
|
no_use = MESA_htable_search_cb(cache->hash, key, key_size, sess_cache_set_cb, &set_args, &cb_ret);
|
||||||
if(cb_ret==SESS_CACHE_UPDATE_OLD)
|
if (cb_ret == SESS_CACHE_UPDATE_OLD)
|
||||||
{
|
{
|
||||||
ssl_sess_free_serialized(asn1);
|
ssl_sess_free_serialized(asn1);
|
||||||
}
|
}
|
||||||
free(key);
|
free(key);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SSL_SESSION* up_session_get(struct sess_cache* cache, struct sockaddr * addr, socklen_t addr_len, const char* sni)
|
|
||||||
|
SSL_SESSION * up_session_get(struct sess_cache * cache, struct sockaddr * addr, socklen_t addr_len, const char * sni)
|
||||||
{
|
{
|
||||||
SSL_SESSION* sess=NULL;
|
SSL_SESSION * sess = NULL;
|
||||||
void* no_use=NULL;
|
void * no_use = NULL;
|
||||||
long cb_ret=0;
|
long cb_ret = 0;
|
||||||
char* key=NULL;
|
|
||||||
size_t key_size=0;
|
size_t key_size = 0;
|
||||||
assert(cache->served_for==CONN_DIR_UPSTREAM);
|
assert(cache->served_for == CONN_DIR_UPSTREAM);
|
||||||
key_size=upsess_mk_key(addr, addr_len, sni, &key);
|
|
||||||
no_use=MESA_htable_search_cb(cache->hash, key, key_size,sess_cache_get_cb, &sess, &cb_ret);
|
unsigned char * key = NULL;
|
||||||
|
key_size = upsess_mk_key(addr, addr_len, sni, &key);
|
||||||
|
no_use = MESA_htable_search_cb(cache->hash, key, key_size, sess_cache_get_cb, &sess, &cb_ret);
|
||||||
free(key);
|
free(key);
|
||||||
key=NULL;
|
key = NULL;
|
||||||
if(cb_ret==1)
|
if (cb_ret == 1)
|
||||||
{
|
{
|
||||||
cache->hit_cnt++;
|
cache->hit_cnt++;
|
||||||
return sess;
|
return sess;
|
||||||
@@ -206,39 +227,41 @@ SSL_SESSION* up_session_get(struct sess_cache* cache, struct sockaddr *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void down_session_set(struct sess_cache* cache, const SSL_SESSION* sess)
|
void down_session_set(struct sess_cache * cache, const SSL_SESSION * sess)
|
||||||
{
|
{
|
||||||
unsigned int idlen=0;
|
unsigned int idlen = 0;
|
||||||
struct asn1_sess* asn1=NULL;
|
struct asn1_sess * asn1 = NULL;
|
||||||
long cb_ret=0;
|
long cb_ret = 0;
|
||||||
void* no_use=NULL;
|
void * no_use = NULL;
|
||||||
int ret=0;
|
int ret = 0;
|
||||||
assert(cache->served_for==CONN_DIR_DOWNSTREAM);
|
assert(cache->served_for == CONN_DIR_DOWNSTREAM);
|
||||||
asn1=ssl_sess_serialize(sess);
|
asn1 = ssl_sess_serialize((SSL_SESSION *) sess);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SSL_SESSION_get_id() returns a pointer to the internal session id value for the session s.
|
* SSL_SESSION_get_id() returns a pointer to the internal session id value for the session s.
|
||||||
* The length of the id in bytes is stored in *idlen. The length may be 0.
|
* The length of the id in bytes is stored in *idlen. The length may be 0.
|
||||||
* The caller should not free the returned pointer directly.
|
* The caller should not free the returned pointer directly.
|
||||||
*/
|
*/
|
||||||
const unsigned char* id = SSL_SESSION_get_id(sess, &idlen);
|
|
||||||
struct sess_set_args set_args;
|
const unsigned char * id = SSL_SESSION_get_id(sess, &idlen);
|
||||||
set_args.hash=cache->hash;
|
struct sess_set_args set_args{.hash = cache->hash, .new_sess = asn1};
|
||||||
set_args.new_sess=asn1;
|
|
||||||
no_use=MESA_htable_search_cb(cache->hash, id, (unsigned int)idlen, sess_cache_set_cb, &set_args,&cb_ret);
|
no_use = MESA_htable_search_cb(cache->hash, id, (unsigned int) idlen, sess_cache_set_cb, &set_args, &cb_ret);
|
||||||
if(cb_ret==SESS_CACHE_UPDATE_OLD)
|
if (cb_ret == SESS_CACHE_UPDATE_OLD)
|
||||||
{
|
{
|
||||||
ssl_sess_free_serialized(asn1);
|
ssl_sess_free_serialized(asn1);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SSL_SESSION* down_session_get(struct sess_cache* cache, unsigned char * id, int idlen)
|
|
||||||
|
SSL_SESSION * down_session_get(struct sess_cache * cache, const unsigned char * id, int idlen)
|
||||||
{
|
{
|
||||||
SSL_SESSION* sess=NULL;
|
SSL_SESSION * sess = NULL;
|
||||||
void* no_use=NULL;
|
void * no_use = NULL;
|
||||||
long cb_ret=0;
|
long cb_ret = 0;
|
||||||
assert(cache->served_for==CONN_DIR_DOWNSTREAM);
|
assert(cache->served_for == CONN_DIR_DOWNSTREAM);
|
||||||
no_use=MESA_htable_search_cb(cache->hash, id, (unsigned int)idlen, sess_cache_get_cb, &sess,&cb_ret);
|
no_use = MESA_htable_search_cb(cache->hash, id, (unsigned int) idlen, sess_cache_get_cb, &sess, &cb_ret);
|
||||||
if(cb_ret==1)
|
if (cb_ret == 1)
|
||||||
{
|
{
|
||||||
cache->hit_cnt++;
|
cache->hit_cnt++;
|
||||||
return sess;
|
return sess;
|
||||||
@@ -250,49 +273,66 @@ SSL_SESSION* down_session_get(struct sess_cache* cache, unsigned char
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void down_session_del(struct sess_cache* cache, const SSL_SESSION* sess)
|
void down_session_del(struct sess_cache * cache, const SSL_SESSION * sess)
|
||||||
{
|
{
|
||||||
assert(cache->served_for==CONN_DIR_DOWNSTREAM);
|
assert(cache->served_for == CONN_DIR_DOWNSTREAM);
|
||||||
unsigned int len=0;
|
unsigned int len = 0;
|
||||||
const unsigned char* id = SSL_SESSION_get_id(sess, &len);
|
const unsigned char * id = SSL_SESSION_get_id(sess, &len);
|
||||||
int ret=MESA_htable_del(cache->hash, id, len, NULL);
|
int ret = MESA_htable_del(cache->hash, id, len, NULL);
|
||||||
if(ret!=MESA_HTABLE_RET_OK)
|
if (ret != MESA_HTABLE_RET_OK)
|
||||||
{
|
{
|
||||||
cache->del_err++;
|
cache->del_err++;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct sess_cache* ssl_sess_cache_create(int slot_size, int expire_seconds, enum tfe_conn_dir served)
|
|
||||||
|
int __wrapper_MESA_htable_set_opt(MESA_htable_handle table, enum MESA_htable_opt opt_type, unsigned value)
|
||||||
{
|
{
|
||||||
struct sess_cache* cache=ALLOC(struct sess_cache, 1);
|
int ret = MESA_htable_set_opt(table, opt_type, &value, (int)(sizeof(value)));
|
||||||
MESA_htable_handle htable=NULL;
|
assert(ret == 0);
|
||||||
int ret=0,max_num=slot_size*4;
|
return ret;
|
||||||
htable=MESA_htable_born();
|
}
|
||||||
value=0;//no print
|
|
||||||
ret=MESA_htable_set_opt(htable, MHO_SCREEN_PRINT_CTRL, &(value), sizeof(value));
|
int __wrapper_MESA_htable_set_opt(MESA_htable_handle table, enum MESA_htable_opt opt_type, void * val, size_t len)
|
||||||
value=1;//thread safe
|
{
|
||||||
ret=MESA_htable_set_opt(htable, MHO_THREAD_SAFE, value, sizeof(value));
|
int ret = MESA_htable_set_opt(table, opt_type, val, (int)len);
|
||||||
assert(ret==0);
|
assert(ret == 0);
|
||||||
value=16;
|
return ret;
|
||||||
ret=MESA_htable_set_opt(htable, MHO_MUTEX_NUM, value, sizeof(value));
|
}
|
||||||
ret=MESA_htable_set_opt(htable, MHO_HASH_SLOT_SIZE, &(slot_size), sizeof(slot_size));
|
|
||||||
ret=MESA_htable_set_opt(htable, MHO_HASH_MAX_ELEMENT_NUM, &(max_num), sizeof(max_num));
|
struct sess_cache * ssl_sess_cache_create(unsigned int slot_size, unsigned int expire_seconds, enum tfe_conn_dir served)
|
||||||
ret=MESA_htable_set_opt(htable, MHO_EXPIRE_TIME, &(expire_seconds), sizeof(expire_seconds));
|
{
|
||||||
value=HASH_ELIMINATE_ALGO_FIFO;
|
struct sess_cache * cache = ALLOC(struct sess_cache, 1);
|
||||||
ret=MESA_htable_set_opt(htable, MHO_ELIMIMINATE_TYPE, &(value), sizeof(value));
|
unsigned max_num = slot_size * 4;
|
||||||
ret=MESA_htable_set_opt(htable, MHO_CBFUN_DATA_FREE, ssl_sess_free_serialized, sizeof(ssl_sess_free_serialized));
|
int ret = 0;
|
||||||
ret=MESA_htable_set_opt(htable, MHO_CBFUN_DATA_EXPIRE_NOTIFY, ssl_sess_varify_cb, sizeof(ssl_sess_varify_cb));
|
|
||||||
assert(ret==0);
|
MESA_htable_handle htable = MESA_htable_born();
|
||||||
ret=MESA_htable_mature(htable);
|
ret = __wrapper_MESA_htable_set_opt(htable, MHO_SCREEN_PRINT_CTRL, 0);
|
||||||
assert(ret==0);
|
ret = __wrapper_MESA_htable_set_opt(htable, MHO_THREAD_SAFE, 1);
|
||||||
cache->hash=htable;
|
|
||||||
cache->served_for=served;
|
ret = __wrapper_MESA_htable_set_opt(htable, MHO_MUTEX_NUM, 16);
|
||||||
|
ret = __wrapper_MESA_htable_set_opt(htable, MHO_HASH_SLOT_SIZE, slot_size);
|
||||||
|
ret = __wrapper_MESA_htable_set_opt(htable, MHO_HASH_MAX_ELEMENT_NUM, max_num);
|
||||||
|
ret = __wrapper_MESA_htable_set_opt(htable, MHO_EXPIRE_TIME, expire_seconds);
|
||||||
|
|
||||||
|
ret = __wrapper_MESA_htable_set_opt(htable, MHO_ELIMIMINATE_TYPE,
|
||||||
|
HASH_ELIMINATE_ALGO_FIFO);
|
||||||
|
ret = __wrapper_MESA_htable_set_opt(htable, MHO_CBFUN_DATA_FREE,
|
||||||
|
(void *)ssl_sess_free_serialized, sizeof(&ssl_sess_free_serialized));
|
||||||
|
ret = __wrapper_MESA_htable_set_opt(htable, MHO_CBFUN_DATA_EXPIRE_NOTIFY,
|
||||||
|
(void *)ssl_sess_verify_cb, sizeof(&ssl_sess_verify_cb));
|
||||||
|
|
||||||
|
ret = MESA_htable_mature(htable);
|
||||||
|
assert(ret == 0);
|
||||||
|
|
||||||
|
cache->hash = htable;
|
||||||
|
cache->served_for = served;
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
void ssl_sess_cache_destroy(struct sess_cache* cache)
|
void ssl_sess_cache_destroy(struct sess_cache * cache)
|
||||||
{
|
{
|
||||||
MESA_htable_destroy(cache->hash, NULL);
|
MESA_htable_destroy(cache->hash, NULL);
|
||||||
cache->hash=NULL;
|
cache->hash = NULL;
|
||||||
free(cache);
|
free(cache);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <openssl/ssl.h>
|
|
||||||
|
|
||||||
#include <tfe_stream.h>
|
|
||||||
|
|
||||||
struct sess_cache;
|
|
||||||
struct sess_cache* ssl_sess_cache_create(int slot_size, int expire_seconds, enum tfe_conn_dir served);
|
|
||||||
void ssl_sess_cache_destroy(struct sess_cache* cache);
|
|
||||||
|
|
||||||
void up_session_set(struct sess_cache* cache, struct sockaddr * addr, socklen_t addr_len, const char* sni, SSL_SESSION * value)
|
|
||||||
SSL_SESSION* up_session_get(struct sess_cache* cache, struct sockaddr *addr, socklen_t addr_len, const char* sni);
|
|
||||||
void down_session_set(struct sess_cache* cache, const SSL_SESSION* sess);
|
|
||||||
SSL_SESSION* down_session_get(struct sess_cache* cache, unsigned char * id, int idlen);
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
492
platform/src/tcp_stream.cpp
Normal file
492
platform/src/tcp_stream.cpp
Normal file
@@ -0,0 +1,492 @@
|
|||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <event2/event.h>
|
||||||
|
#include <event2/listener.h>
|
||||||
|
#include <event2/bufferevent.h>
|
||||||
|
#include <event2/bufferevent_ssl.h>
|
||||||
|
#include <event2/buffer.h>
|
||||||
|
#include <event2/thread.h>
|
||||||
|
#include <event2/dns.h>
|
||||||
|
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
#include <openssl/x509.h>
|
||||||
|
#include <openssl/x509v3.h>
|
||||||
|
|
||||||
|
#include <tfe_stream.h>
|
||||||
|
#include <tfe_utils.h>
|
||||||
|
#include <tfe_future.h>
|
||||||
|
|
||||||
|
#include <platform.h>
|
||||||
|
#include <ssl_stream.h>
|
||||||
|
#include <tcp_stream.h>
|
||||||
|
#include <cert.h>
|
||||||
|
#include <proxy.h>
|
||||||
|
|
||||||
|
#ifndef TFE_CONFIG_OUTPUT_LIMIT_DEFAULT
|
||||||
|
#define TFE_CONFIG_OUTPUT_LIMIT_DEFAULT (1024 * 1024)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* forward declaration of libevent callbacks */
|
||||||
|
static void tfe_stream_readcb(struct bufferevent *, void *);
|
||||||
|
static void tfe_stream_writecb(struct bufferevent *, void *);
|
||||||
|
static void tfe_stream_eventcb(struct bufferevent *, short, void *);
|
||||||
|
|
||||||
|
static inline struct tfe_stream_private * __TO_STREAM_PRIVATE(const struct tfe_stream * stream)
|
||||||
|
{
|
||||||
|
return container_of(stream, struct tfe_stream_private, head);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct tfe_conn_private * __THIS_CONN(struct tfe_stream_private * _stream, enum tfe_conn_dir dir)
|
||||||
|
{
|
||||||
|
return ((dir == CONN_DIR_UPSTREAM) ? (_stream->conn_upstream) : (_stream->conn_downstream));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct tfe_conn_private * __PEER_CONN(struct tfe_stream_private * _stream, enum tfe_conn_dir dir)
|
||||||
|
{
|
||||||
|
return ((dir == CONN_DIR_UPSTREAM) ? (_stream->conn_downstream) : (_stream->conn_upstream));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline enum tfe_conn_dir __DIR(struct tfe_stream_private * _stream, struct bufferevent * bev)
|
||||||
|
{
|
||||||
|
return ((bev == _stream->conn_downstream->bev) ? CONN_DIR_UPSTREAM : CONN_DIR_DOWNSTREAM);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool __IS_SSL(struct tfe_stream_private * _stream)
|
||||||
|
{
|
||||||
|
return (_stream->session_type == SESSION_PROTO_SSL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tfe_stream_detach(const struct tfe_stream * stream)
|
||||||
|
{
|
||||||
|
struct tfe_stream_private * _stream = __TO_STREAM_PRIVATE(stream);
|
||||||
|
int plug_id = _stream->calling_idx;
|
||||||
|
_stream->plug_ctx[plug_id].state = PLUG_STATE_DETACHED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tfe_stream_preempt(const struct tfe_stream * stream)
|
||||||
|
{
|
||||||
|
struct tfe_stream_private * _stream = __TO_STREAM_PRIVATE(stream);
|
||||||
|
int plug_id = _stream->calling_idx;
|
||||||
|
int i = 0;
|
||||||
|
for (i = 0; i < _stream->plugin_num; i++)
|
||||||
|
{
|
||||||
|
if (_stream->plug_ctx[i].state == PLUG_STATE_PREEPTION)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_stream->plug_ctx[plug_id].state = PLUG_STATE_PREEPTION;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct tfe_stream_write_ctx * tfe_stream_write_frag_start(const struct tfe_stream * stream, enum tfe_conn_dir dir)
|
||||||
|
{
|
||||||
|
struct tfe_stream_private * _stream = __TO_STREAM_PRIVATE(stream);
|
||||||
|
struct tfe_conn_private * this_conn = __THIS_CONN(_stream, dir);
|
||||||
|
struct tfe_conn_private * peer_conn = __PEER_CONN(_stream, dir);
|
||||||
|
|
||||||
|
if (this_conn->on_writing == 1)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
this_conn->w_ctx.dir = dir;
|
||||||
|
this_conn->w_ctx._stream = _stream;
|
||||||
|
this_conn->on_writing = 1;
|
||||||
|
bufferevent_disable(peer_conn->bev, EV_READ);
|
||||||
|
return &(this_conn->w_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
int tfe_stream_write_frag(struct tfe_stream_write_ctx * w_ctx, const unsigned char * data, size_t size)
|
||||||
|
{
|
||||||
|
struct tfe_conn_private * this_conn = __THIS_CONN(w_ctx->_stream, w_ctx->dir);;
|
||||||
|
int ret = bufferevent_write(this_conn->bev, data, size);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
void tfe_stream_write_frag_end(struct tfe_stream_write_ctx * w_ctx)
|
||||||
|
{
|
||||||
|
struct tfe_conn_private * this_conn = __THIS_CONN(w_ctx->_stream, w_ctx->dir);
|
||||||
|
struct tfe_conn_private * peer_conn = __PEER_CONN(w_ctx->_stream, w_ctx->dir);
|
||||||
|
this_conn->on_writing = 0;
|
||||||
|
bufferevent_enable(peer_conn->bev, EV_READ);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tfe_stream_write(const struct tfe_stream * stream, enum tfe_conn_dir dir, const unsigned char * data, size_t size)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct tfe_stream_write_ctx * wctx = tfe_stream_write_frag_start(stream, dir);
|
||||||
|
ret = tfe_stream_write_frag(wctx, data, size);
|
||||||
|
tfe_stream_write_frag_end(wctx);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Callback for read events on the up- and downstream connection bufferevents.
|
||||||
|
* Called when there is data ready in the input evbuffer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void tfe_stream_readcb(struct bufferevent * bev, void * arg)
|
||||||
|
{
|
||||||
|
struct tfe_stream_private * _stream = (struct tfe_stream_private *) arg;
|
||||||
|
enum tfe_conn_dir dir = __DIR(_stream, bev);
|
||||||
|
struct tfe_conn_private * this_conn = __THIS_CONN(_stream, dir);
|
||||||
|
struct tfe_conn_private * peer_conn = __PEER_CONN(_stream, dir);
|
||||||
|
|
||||||
|
int i = 0, ret = 0;
|
||||||
|
enum tfe_stream_action action_tmp = ACTION_FORWARD_DATA, action_final = ACTION_FORWARD_DATA;
|
||||||
|
|
||||||
|
const struct tfe_plugin * plugins = _stream->thread_ref->modules;
|
||||||
|
struct plugin_ctx * plug_ctx = NULL;
|
||||||
|
int plug_num = _stream->thread_ref->nr_modules;
|
||||||
|
|
||||||
|
struct evbuffer * inbuf = bufferevent_get_input(bev);
|
||||||
|
struct evbuffer * outbuf = bufferevent_get_output(peer_conn->bev);
|
||||||
|
|
||||||
|
size_t contigous_len = evbuffer_get_length(inbuf), drain_size = 0;
|
||||||
|
const unsigned char * contiguous_data = (const unsigned char *) evbuffer_pullup(inbuf, contigous_len);
|
||||||
|
|
||||||
|
_stream->defere_bytes = 0;
|
||||||
|
_stream->drop_bytes = 0;
|
||||||
|
_stream->forward_bytes = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < plug_num; i++)
|
||||||
|
{
|
||||||
|
_stream->calling_idx = i;
|
||||||
|
plug_ctx = _stream->plug_ctx + i;
|
||||||
|
|
||||||
|
if (_stream->is_plugin_opened == 0)
|
||||||
|
{
|
||||||
|
action_tmp = plugins[i].on_open(&_stream->head, _stream->thread_ref->thread_id,
|
||||||
|
dir, contiguous_data, contigous_len, &(plug_ctx->pme));
|
||||||
|
_stream->is_plugin_opened = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
action_tmp = plugins[i].on_data(&_stream->head, _stream->thread_ref->thread_id,
|
||||||
|
dir, contiguous_data, contigous_len, &(plug_ctx->pme));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (plug_ctx->state == PLUG_STATE_PREEPTION)
|
||||||
|
{
|
||||||
|
action_final = action_tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (action_final)
|
||||||
|
{
|
||||||
|
case ACTION_FORWARD_DATA:
|
||||||
|
if (_stream->forward_bytes > 0)
|
||||||
|
{
|
||||||
|
evbuffer_remove_buffer(inbuf, outbuf, _stream->forward_bytes);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
evbuffer_add_buffer(outbuf, inbuf);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ACTION_DROP_DATA:
|
||||||
|
if (_stream->drop_bytes > 0)
|
||||||
|
{
|
||||||
|
drain_size = _stream->drop_bytes;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
drain_size = evbuffer_get_length(inbuf);
|
||||||
|
}
|
||||||
|
evbuffer_drain(inbuf, drain_size);
|
||||||
|
case ACTION_DEFER_DATA:
|
||||||
|
if (_stream->defere_bytes > 0)
|
||||||
|
{
|
||||||
|
bufferevent_setwatermark(bev, EV_WRITE, _stream->defere_bytes, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: assert(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (evbuffer_get_length(inbuf) != 0)
|
||||||
|
{
|
||||||
|
bufferevent_trigger(bev, EV_READ, BEV_OPT_DEFER_CALLBACKS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (evbuffer_get_length(outbuf) >= TFE_CONFIG_OUTPUT_LIMIT_DEFAULT)
|
||||||
|
{
|
||||||
|
bufferevent_setwatermark(peer_conn->bev, EV_WRITE, TFE_CONFIG_OUTPUT_LIMIT_DEFAULT / 2,
|
||||||
|
TFE_CONFIG_OUTPUT_LIMIT_DEFAULT);
|
||||||
|
bufferevent_disable(bev, EV_READ);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Callback for write events on the up- and downstream connection bufferevents.
|
||||||
|
* Called when either all data from the output evbuffer has been written,
|
||||||
|
* or if the outbuf is only half full again after having been full.
|
||||||
|
*/
|
||||||
|
static void tfe_stream_writecb(struct bufferevent * bev, void * arg)
|
||||||
|
{
|
||||||
|
struct tfe_stream_private * _stream = (struct tfe_stream_private *) arg;
|
||||||
|
enum tfe_conn_dir dir = __DIR(_stream, bev);
|
||||||
|
struct tfe_conn_private * this_conn = __THIS_CONN(_stream, dir);
|
||||||
|
struct tfe_conn_private * peer_conn = __PEER_CONN(_stream, dir);
|
||||||
|
|
||||||
|
struct evbuffer * outbuf = bufferevent_get_output(bev);
|
||||||
|
|
||||||
|
if (peer_conn->bev && !(bufferevent_get_enabled(peer_conn->bev) & EV_READ))
|
||||||
|
{
|
||||||
|
/* data source temporarily disabled;
|
||||||
|
* re-enable and reset watermark to 0. */
|
||||||
|
bufferevent_setwatermark(bev, EV_WRITE, 0, 0);
|
||||||
|
bufferevent_enable(peer_conn->bev, EV_READ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Callback for meta events on the up- and downstream connection bufferevents.
|
||||||
|
* Called when EOF has been reached, a connection has been made, and on errors.
|
||||||
|
*/
|
||||||
|
static void tfe_stream_eventcb(struct bufferevent * bev, short events, void * arg)
|
||||||
|
{
|
||||||
|
struct tfe_stream_private * _stream = (struct tfe_stream_private *) arg;
|
||||||
|
enum tfe_conn_dir dir = __DIR(_stream, bev);
|
||||||
|
struct tfe_conn_private * this_conn = __THIS_CONN(_stream, dir);
|
||||||
|
struct tfe_conn_private * peer_conn = __PEER_CONN(_stream, dir);
|
||||||
|
|
||||||
|
const struct tfe_plugin * plugins = _stream->thread_ref->modules;
|
||||||
|
struct plugin_ctx * plug_ctx = NULL;
|
||||||
|
int plug_num = _stream->thread_ref->nr_modules, i = 0;
|
||||||
|
enum tfe_stream_close_reason reason = REASON_PASSIVE_CLOSED;
|
||||||
|
|
||||||
|
if (events & BEV_EVENT_ERROR)
|
||||||
|
{
|
||||||
|
this_conn->closed = 1;
|
||||||
|
reason = REASON_ERROR;
|
||||||
|
goto call_plugin_close;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (events & BEV_EVENT_EOF)
|
||||||
|
{
|
||||||
|
//generate a 0 size read callback to notify plugins.
|
||||||
|
tfe_stream_readcb(bev, arg);
|
||||||
|
this_conn->closed = 1;
|
||||||
|
}
|
||||||
|
if (peer_conn->closed == 1 && this_conn->closed == 1)
|
||||||
|
{
|
||||||
|
reason = REASON_PASSIVE_CLOSED;
|
||||||
|
goto call_plugin_close;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
call_plugin_close:
|
||||||
|
for (i = 0; i < plug_num; i++)
|
||||||
|
{
|
||||||
|
_stream->calling_idx = i;
|
||||||
|
plug_ctx = _stream->plug_ctx + i;
|
||||||
|
plugins[i].on_close(&(_stream->head), _stream->thread_ref->thread_id, reason, &(plug_ctx->pme));
|
||||||
|
}
|
||||||
|
|
||||||
|
tfe_stream_destory(_stream);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static tfe_conn_private * __conn_private_create(struct tfe_stream_private * stream, evutil_socket_t fd)
|
||||||
|
{
|
||||||
|
struct tfe_conn_private * __conn_private = ALLOC(struct tfe_conn_private, 1);
|
||||||
|
struct event_base * __ev_base = stream->thread_ref->evbase;
|
||||||
|
|
||||||
|
__conn_private->bev = bufferevent_socket_new(__ev_base, fd, BEV_OPT_DEFER_CALLBACKS);
|
||||||
|
__conn_private->fd = fd;
|
||||||
|
|
||||||
|
if (!__conn_private->bev)
|
||||||
|
{
|
||||||
|
TFE_LOG_ERROR(__STREAM_LOGGER(stream), "Failed at creating bufferevent for fd %d", fd);
|
||||||
|
goto __errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
bufferevent_setcb(__conn_private->bev, tfe_stream_readcb, tfe_stream_writecb, tfe_stream_eventcb, stream);
|
||||||
|
bufferevent_enable(__conn_private->bev, EV_READ | EV_WRITE);
|
||||||
|
return __conn_private;
|
||||||
|
|
||||||
|
__errout:
|
||||||
|
if (__conn_private != NULL) free(__conn_private);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static tfe_conn_private * __conn_private_create(struct tfe_stream_private * stream, struct bufferevent * bev)
|
||||||
|
{
|
||||||
|
struct tfe_conn_private * __conn_private = ALLOC(struct tfe_conn_private, 1);
|
||||||
|
__conn_private->bev = bev;
|
||||||
|
__conn_private->fd = bufferevent_getfd(bev);
|
||||||
|
|
||||||
|
bufferevent_setcb(__conn_private->bev, tfe_stream_readcb, tfe_stream_writecb, tfe_stream_eventcb, stream);
|
||||||
|
bufferevent_enable(__conn_private->bev, EV_READ | EV_WRITE);
|
||||||
|
return __conn_private;
|
||||||
|
}
|
||||||
|
|
||||||
|
evutil_socket_t __conn_private_release_fd(struct tfe_conn_private * conn)
|
||||||
|
{
|
||||||
|
evutil_socket_t __to_release_fd = conn->fd;
|
||||||
|
conn->fd = 0;
|
||||||
|
return __to_release_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __conn_private_destory(struct tfe_conn_private * conn)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ssl_downstream_create_on_success(future_result_t * result, void * user)
|
||||||
|
{
|
||||||
|
struct tfe_stream_private * _stream = (struct tfe_stream_private *) user;
|
||||||
|
struct ssl_stream * downstream = ssl_downstream_create_result_release_stream(result);
|
||||||
|
struct bufferevent * bev = ssl_downstream_create_result_release_bev(result);
|
||||||
|
|
||||||
|
_stream->conn_downstream = __conn_private_create(_stream, bev);
|
||||||
|
_stream->ssl_downstream = downstream;
|
||||||
|
|
||||||
|
future_destroy(_stream->future_downstream_create);
|
||||||
|
_stream->future_downstream_create = NULL;
|
||||||
|
_stream->defer_fd_downstream = 0;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ssl_downstream_create_on_fail(enum e_future_error err, const char * what, void * user)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ssl_upstream_create_on_success(future_result_t * result, void * user)
|
||||||
|
{
|
||||||
|
struct tfe_stream_private * _stream = (struct tfe_stream_private *) user;
|
||||||
|
struct event_base * ev_base = _stream->thread_ref->evbase;
|
||||||
|
|
||||||
|
struct ssl_stream * upstream = ssl_upstream_create_result_release_stream(result);
|
||||||
|
struct bufferevent * bev = ssl_upstream_create_result_release_bev(result);
|
||||||
|
assert(upstream != NULL && bev != NULL);
|
||||||
|
|
||||||
|
/* Create connection ctx by bev */
|
||||||
|
_stream->conn_upstream = __conn_private_create(_stream, bev);
|
||||||
|
_stream->ssl_upstream = upstream;
|
||||||
|
|
||||||
|
future_destroy(_stream->future_upstream_create);
|
||||||
|
_stream->future_upstream_create = NULL;
|
||||||
|
_stream->defer_fd_upstream = 0;
|
||||||
|
|
||||||
|
/* Next, create downstream */
|
||||||
|
_stream->future_downstream_create = future_create(ssl_downstream_create_on_success,
|
||||||
|
ssl_downstream_create_on_fail, _stream);
|
||||||
|
|
||||||
|
ssl_async_downstream_create(_stream->future_downstream_create, _stream->ssl_mgr,
|
||||||
|
_stream->ssl_upstream, _stream->defer_fd_downstream, /* KEYRING ID */ 0, ev_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ssl_upstream_create_on_fail(enum e_future_error err, const char * what, void * user)
|
||||||
|
{
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct tfe_stream * tfe_stream_create(struct tfe_proxy * pxy, struct tfe_thread_ctx * thread_ctx)
|
||||||
|
{
|
||||||
|
struct tfe_stream_private * _stream = ALLOC(struct tfe_stream_private, 1);
|
||||||
|
_stream->thread_ref = thread_ctx;
|
||||||
|
_stream->proxy_ref = pxy;
|
||||||
|
return (struct tfe_stream *) &_stream->head;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tfe_stream_destory(struct tfe_stream_private * stream)
|
||||||
|
{
|
||||||
|
struct tfe_thread_ctx * thread = stream->thread_ref;
|
||||||
|
struct tfe_proxy * proxy = stream->proxy_ref;
|
||||||
|
struct event_base * ev_base = thread->evbase;
|
||||||
|
|
||||||
|
if (__IS_SSL(stream) && stream->ssl_upstream)
|
||||||
|
{
|
||||||
|
evutil_socket_t __to_closed_fd = __conn_private_release_fd(stream->conn_upstream);
|
||||||
|
ssl_stream_free_and_close_fd(stream->ssl_upstream, ev_base, __to_closed_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (__IS_SSL(stream) && stream->ssl_downstream)
|
||||||
|
{
|
||||||
|
evutil_socket_t __to_closed_fd = __conn_private_release_fd(stream->conn_upstream);
|
||||||
|
ssl_stream_free_and_close_fd(stream->ssl_downstream, ev_base, __to_closed_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stream->conn_upstream)
|
||||||
|
{
|
||||||
|
__conn_private_destory(stream->conn_upstream);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stream->conn_downstream)
|
||||||
|
{
|
||||||
|
__conn_private_destory(stream->conn_downstream);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stream->defer_fd_downstream)
|
||||||
|
{
|
||||||
|
evutil_closesocket(stream->defer_fd_downstream);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stream->defer_fd_upstream)
|
||||||
|
{
|
||||||
|
evutil_closesocket(stream->defer_fd_upstream);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stream->future_downstream_create)
|
||||||
|
{
|
||||||
|
future_destroy(stream->future_downstream_create);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stream->future_upstream_create)
|
||||||
|
{
|
||||||
|
future_destroy(stream->future_upstream_create);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(stream);
|
||||||
|
thread->load--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tfe_stream_init_by_fds(struct tfe_stream * stream, enum tfe_session_proto session_type,
|
||||||
|
evutil_socket_t fd_downstream, evutil_socket_t fd_upstream)
|
||||||
|
{
|
||||||
|
struct tfe_stream_private * _stream = container_of(stream, struct tfe_stream_private, head);
|
||||||
|
struct event_base * ev_base = _stream->thread_ref->evbase;
|
||||||
|
|
||||||
|
if (session_type == SESSION_PROTO_PLAIN)
|
||||||
|
{
|
||||||
|
_stream->conn_downstream = __conn_private_create(_stream, fd_downstream);
|
||||||
|
_stream->conn_upstream = __conn_private_create(_stream, fd_upstream);
|
||||||
|
|
||||||
|
assert(_stream->conn_downstream != NULL);
|
||||||
|
assert(_stream->conn_upstream != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session_type == SESSION_PROTO_SSL)
|
||||||
|
{
|
||||||
|
_stream->ssl_mgr = _stream->proxy_ref->ssl_mgr_handler;
|
||||||
|
|
||||||
|
_stream->future_upstream_create = future_create(
|
||||||
|
ssl_upstream_create_on_success, ssl_upstream_create_on_fail, (void *) _stream);
|
||||||
|
|
||||||
|
/* Defer setup conn_downstream & conn_upstream in async callbacks. */
|
||||||
|
ssl_async_upstream_create(_stream->future_upstream_create,
|
||||||
|
_stream->ssl_mgr, fd_upstream, fd_downstream, ev_base);
|
||||||
|
|
||||||
|
_stream->defer_fd_downstream = fd_downstream;
|
||||||
|
_stream->defer_fd_upstream = fd_upstream;
|
||||||
|
}
|
||||||
|
|
||||||
|
_stream->session_type = session_type;
|
||||||
|
}
|
||||||
@@ -1,560 +0,0 @@
|
|||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include <event2/event.h>
|
|
||||||
#include <event2/listener.h>
|
|
||||||
#include <event2/bufferevent.h>
|
|
||||||
#include <event2/bufferevent_ssl.h>
|
|
||||||
#include <event2/buffer.h>
|
|
||||||
#include <event2/thread.h>
|
|
||||||
#include <event2/dns.h>
|
|
||||||
|
|
||||||
#include <openssl/ssl.h>
|
|
||||||
#include <openssl/err.h>
|
|
||||||
#include <openssl/rand.h>
|
|
||||||
#include <openssl/x509.h>
|
|
||||||
#include <openssl/x509v3.h>
|
|
||||||
|
|
||||||
#include <tfe_stream.h>
|
|
||||||
#include <tfe_utils.h>
|
|
||||||
#include <tfe_future.h>
|
|
||||||
|
|
||||||
#include <ssl_stream.h>
|
|
||||||
#include <stream.h>
|
|
||||||
#include <cert.h>
|
|
||||||
|
|
||||||
#define STREAM_EVBASE(s) ((s)->thrmgr_ref->evbase)
|
|
||||||
/*
|
|
||||||
* Maximum size of data to buffer per connection direction before
|
|
||||||
* temporarily stopping to read data from the other end.
|
|
||||||
*/
|
|
||||||
#define OUTBUF_LIMIT (1024*1024)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Print helper for logging code.
|
|
||||||
*/
|
|
||||||
#define STRORDASH(x) (((x)&&*(x))?(x):"-")
|
|
||||||
|
|
||||||
/* forward declaration of libevent callbacks */
|
|
||||||
static void tfe_stream_readcb(struct bufferevent *, void *);
|
|
||||||
static void tfe_stream_writecb(struct bufferevent *, void *);
|
|
||||||
static void tfe_stream_eventcb(struct bufferevent *, short, void *);
|
|
||||||
static void stream_fd_readcb(evutil_socket_t, short, void *);
|
|
||||||
|
|
||||||
static void tfe_stream_free(struct tfe_stream_private * stream)
|
|
||||||
{
|
|
||||||
struct tfe_thread_ctx * thread = stream->thrmgr_ref;
|
|
||||||
thread->load--;
|
|
||||||
|
|
||||||
switch (stream->session_type)
|
|
||||||
{
|
|
||||||
case SESSION_PROTO_SSL:
|
|
||||||
#if 0
|
|
||||||
ssl_upstream_free(stream->ssl_upstream);
|
|
||||||
ssl_downstream_free(stream->ssl_downstream);
|
|
||||||
#endif
|
|
||||||
thread->stat.value[SSL_NUM]--;
|
|
||||||
break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(stream);
|
|
||||||
thread->stat.value[STREAM_NUM]--;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tfe_stream_detach(const struct tfe_stream * stream)
|
|
||||||
{
|
|
||||||
struct tfe_stream_private * _stream = (struct tfe_stream_private *) stream;
|
|
||||||
int plug_id = _stream->calling_idx;
|
|
||||||
_stream->plug_ctx[plug_id].state = PLUG_STATE_DETACHED;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tfe_stream_preempt(const struct tfe_stream * stream)
|
|
||||||
{
|
|
||||||
struct tfe_stream_private * _stream = (struct tfe_stream_private *) stream;
|
|
||||||
int plug_id = _stream->calling_idx;
|
|
||||||
int i = 0;
|
|
||||||
for (i = 0; i < _stream->plugin_num; i++)
|
|
||||||
{
|
|
||||||
if (_stream->plug_ctx[i].state == PLUG_STATE_PREEPTION)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_stream->plug_ctx[plug_id].state = PLUG_STATE_PREEPTION;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct tfe_conn_private * __this_conn(struct tfe_stream_private * _stream, enum tfe_conn_dir dir)
|
|
||||||
{
|
|
||||||
struct tfe_conn_private * this_conn = NULL;
|
|
||||||
this_conn = ((dir == CONN_DIR_UPSTREAM) ? &(_stream->conn_downstream) : &(_stream->conn_upstream));
|
|
||||||
return this_conn;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct tfe_conn_private * __peer_conn(struct tfe_stream_private * _stream, enum tfe_conn_dir dir)
|
|
||||||
{
|
|
||||||
struct tfe_conn_private * peer_conn = NULL;
|
|
||||||
peer_conn = (dir == CONN_DIR_UPSTREAM) ? &(_stream->conn_downstream) : &(_stream->conn_upstream);
|
|
||||||
return peer_conn;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct tfe_stream_write_ctx * tfe_stream_write_frag_start(const struct tfe_stream * stream, enum tfe_conn_dir dir)
|
|
||||||
{
|
|
||||||
struct tfe_stream_private * _stream = (struct tfe_stream_private *) stream;
|
|
||||||
struct tfe_conn_private * this_conn = __this_conn(_stream, dir);
|
|
||||||
struct tfe_conn_private * peer_conn = __peer_conn(_stream, dir);
|
|
||||||
if (this_conn->on_writing == 1)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
this_conn->w_ctx.dir = dir;
|
|
||||||
this_conn->w_ctx._stream = _stream;
|
|
||||||
this_conn->on_writing = 1;
|
|
||||||
bufferevent_disable(peer_conn->bev, EV_READ);
|
|
||||||
return &(this_conn->w_ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
int tfe_stream_write_frag(struct tfe_stream_write_ctx * w_ctx, const unsigned char * data, size_t size)
|
|
||||||
{
|
|
||||||
struct tfe_conn_private * this_conn = __this_conn(w_ctx->_stream, w_ctx->dir);;
|
|
||||||
int ret = bufferevent_write(this_conn->bev, data, size);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
void tfe_stream_write_frag_end(struct tfe_stream_write_ctx * w_ctx)
|
|
||||||
{
|
|
||||||
struct tfe_conn_private * this_conn = __this_conn(w_ctx->_stream, w_ctx->dir);
|
|
||||||
struct tfe_conn_private * peer_conn = __peer_conn(w_ctx->_stream, w_ctx->dir);
|
|
||||||
this_conn->on_writing = 0;
|
|
||||||
bufferevent_enable(peer_conn->bev, EV_READ);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tfe_stream_write(const struct tfe_stream * stream, enum tfe_conn_dir dir, const unsigned char * data, size_t size)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
struct tfe_stream_write_ctx * wctx = tfe_stream_write_frag_start(stream, dir);
|
|
||||||
ret = tfe_stream_write_frag(wctx, data, size);
|
|
||||||
tfe_stream_write_frag_end(wctx);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
|
|
||||||
#define ON_OPEN_CALL 0
|
|
||||||
#define ON_DATA_CALL 1
|
|
||||||
#define ON_CLOSE_CALL 2
|
|
||||||
enum tfe_stream_action tfe_stream_call_plugin(struct tfe_stream_private* _stream, enum tfe_conn_dir dir, int what, struct evbuffer * inbuf)
|
|
||||||
{
|
|
||||||
|
|
||||||
size_t contigous_len=evbuffer_get_length(inbuf),drain_size=0;
|
|
||||||
const char* contiguous_data=evbuffer_pullup(inbuf,contigous_len);
|
|
||||||
int i=0,ret=0;
|
|
||||||
int plug_num=_stream->thrmgr_ref->module_num;
|
|
||||||
|
|
||||||
const struct tfe_plugin* plugins=_stream->thrmgr_ref->modules;
|
|
||||||
struct plugin_ctx* plug_ctx=NULL;
|
|
||||||
enum tfe_stream_action action_tmp=ACTION_FORWARD_DATA, action_final=ACTION_FORWARD_DATA;
|
|
||||||
|
|
||||||
_stream->defere_bytes=0;
|
|
||||||
_stream->drop_bytes=0;
|
|
||||||
_stream->forward_bytes=0;
|
|
||||||
switch(what)
|
|
||||||
{
|
|
||||||
case ON_OPEN_CALL:
|
|
||||||
for(i=0;i<plug_num;i++)
|
|
||||||
{
|
|
||||||
action_tmp=plugins[i].on_open(&_stream.head, _stream->thrmgr_ref->thread_id, dir, contiguous_data,contigous_len, &(plug_ctx->pme));
|
|
||||||
if(plug_ctx->state=PLUG_STATE_PREEPTION)
|
|
||||||
{
|
|
||||||
action_final=action_tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case ON_DATA_CALL:
|
|
||||||
for(i=0;i<plug_num;i++)
|
|
||||||
{
|
|
||||||
action_tmp=plugins[i].on_data(&_stream.head, _stream->thrmgr_ref->thread_id, dir, contiguous_data,contigous_len, &(plug_ctx->pme));
|
|
||||||
if(plug_ctx->state=PLUG_STATE_PREEPTION)
|
|
||||||
{
|
|
||||||
action_final=action_tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case ON_CLOSE_CALL:
|
|
||||||
for(i=0;i<plug_num;i++)
|
|
||||||
{
|
|
||||||
plugins[i].on_close(&_stream.head, _stream->thrmgr_ref->thread_id, dir, contiguous_data,contigous_len, &(plug_ctx->pme));
|
|
||||||
if(plug_ctx->state=PLUG_STATE_PREEPTION)
|
|
||||||
{
|
|
||||||
action_final=action_tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(i=0;i<plug_num;i++)
|
|
||||||
{
|
|
||||||
_stream->calling_idx=i;
|
|
||||||
switch(what)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
plug_ctx=_stream->plug_ctx+i;
|
|
||||||
if(_stream->is_fisrt_read==1)
|
|
||||||
{
|
|
||||||
action_tmp=plugins[i].on_open(&_stream.head, _stream->thrmgr_ref->thread_id, dir, contiguous_data,contigous_len, &(plug_ctx->pme));
|
|
||||||
_stream->is_fisrt_read=0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
action_tmp=plugins[i].on_data(&_stream.head, _stream->thrmgr_ref->thread_id, dir, contiguous_data,contigous_len, &(plug_ctx->pme));
|
|
||||||
}
|
|
||||||
if(plug_ctx->state=PLUG_STATE_PREEPTION)
|
|
||||||
{
|
|
||||||
action_final=action_tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* Callback for read events on the up- and downstream connection bufferevents.
|
|
||||||
* Called when there is data ready in the input evbuffer.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void tfe_stream_readcb(struct bufferevent * bev, void * arg)
|
|
||||||
{
|
|
||||||
struct tfe_stream_private * _stream = (struct tfe_stream_private *) arg;
|
|
||||||
enum tfe_conn_dir dir = (bev == _stream->conn_downstream.bev) ? CONN_DIR_UPSTREAM : CONN_DIR_DOWNSTREAM;
|
|
||||||
struct tfe_conn_private * this_conn = __this_conn(_stream, dir);
|
|
||||||
struct tfe_conn_private * peer_conn = __peer_conn(_stream, dir);
|
|
||||||
|
|
||||||
int i = 0, ret = 0;
|
|
||||||
enum tfe_stream_action action_tmp = ACTION_FORWARD_DATA, action_final = ACTION_FORWARD_DATA;
|
|
||||||
|
|
||||||
const struct tfe_plugin * plugins = _stream->thrmgr_ref->modules;
|
|
||||||
struct plugin_ctx * plug_ctx = NULL;
|
|
||||||
int plug_num = _stream->thrmgr_ref->nr_modules;
|
|
||||||
|
|
||||||
struct evbuffer * inbuf = bufferevent_get_input(bev);
|
|
||||||
struct evbuffer * outbuf = bufferevent_get_output(peer_conn->bev);
|
|
||||||
|
|
||||||
size_t contigous_len = evbuffer_get_length(inbuf), drain_size = 0;
|
|
||||||
const unsigned char * contiguous_data = (const unsigned char *)evbuffer_pullup(inbuf, contigous_len);
|
|
||||||
|
|
||||||
_stream->defere_bytes = 0;
|
|
||||||
_stream->drop_bytes = 0;
|
|
||||||
_stream->forward_bytes = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < plug_num; i++)
|
|
||||||
{
|
|
||||||
_stream->calling_idx = i;
|
|
||||||
plug_ctx = _stream->plug_ctx + i;
|
|
||||||
|
|
||||||
if (_stream->is_plugin_opened == 0)
|
|
||||||
{
|
|
||||||
action_tmp = plugins[i].on_open(&_stream->head, _stream->thrmgr_ref->thread_id,
|
|
||||||
dir, contiguous_data, contigous_len, &(plug_ctx->pme));
|
|
||||||
_stream->is_plugin_opened = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
action_tmp = plugins[i].on_data(&_stream->head, _stream->thrmgr_ref->thread_id,
|
|
||||||
dir, contiguous_data, contigous_len, &(plug_ctx->pme));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (plug_ctx->state == PLUG_STATE_PREEPTION)
|
|
||||||
{
|
|
||||||
action_final = action_tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (action_final)
|
|
||||||
{
|
|
||||||
case ACTION_FORWARD_DATA:
|
|
||||||
if (_stream->forward_bytes > 0)
|
|
||||||
{
|
|
||||||
evbuffer_remove_buffer(inbuf, outbuf, _stream->forward_bytes);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
evbuffer_add_buffer(outbuf, inbuf);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ACTION_DROP_DATA:
|
|
||||||
if (_stream->drop_bytes > 0)
|
|
||||||
{
|
|
||||||
drain_size = _stream->drop_bytes;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
drain_size = evbuffer_get_length(inbuf);
|
|
||||||
}
|
|
||||||
evbuffer_drain(inbuf, drain_size);
|
|
||||||
case ACTION_DEFER_DATA:
|
|
||||||
if (_stream->defere_bytes > 0)
|
|
||||||
{
|
|
||||||
bufferevent_setwatermark(bev, EV_WRITE, _stream->defere_bytes, 0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (evbuffer_get_length(inbuf) != 0)
|
|
||||||
{
|
|
||||||
bufferevent_trigger(bev, EV_READ, BEV_OPT_DEFER_CALLBACKS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (evbuffer_get_length(outbuf) >= OUTBUF_LIMIT)
|
|
||||||
{
|
|
||||||
/* temporarily disable data source;
|
|
||||||
* set an appropriate watermark. */
|
|
||||||
bufferevent_setwatermark(peer_conn->bev, EV_WRITE, OUTBUF_LIMIT / 2, OUTBUF_LIMIT);
|
|
||||||
bufferevent_disable(bev, EV_READ);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Callback for write events on the up- and downstream connection bufferevents.
|
|
||||||
* Called when either all data from the output evbuffer has been written,
|
|
||||||
* or if the outbuf is only half full again after having been full.
|
|
||||||
*/
|
|
||||||
static void tfe_stream_writecb(struct bufferevent * bev, void * arg)
|
|
||||||
{
|
|
||||||
struct tfe_stream_private * _stream = (struct tfe_stream_private *) arg;
|
|
||||||
enum tfe_conn_dir dir = (bev == _stream->conn_downstream.bev) ? CONN_DIR_UPSTREAM : CONN_DIR_DOWNSTREAM;
|
|
||||||
struct tfe_conn_private * this_conn = __this_conn(_stream, dir);
|
|
||||||
struct tfe_conn_private * peer_conn = __peer_conn(_stream, dir);
|
|
||||||
|
|
||||||
struct evbuffer * outbuf = bufferevent_get_output(bev);
|
|
||||||
|
|
||||||
if (peer_conn->bev && !(bufferevent_get_enabled(peer_conn->bev) & EV_READ))
|
|
||||||
{
|
|
||||||
/* data source temporarily disabled;
|
|
||||||
* re-enable and reset watermark to 0. */
|
|
||||||
bufferevent_setwatermark(bev, EV_WRITE, 0, 0);
|
|
||||||
bufferevent_enable(peer_conn->bev, EV_READ);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Callback for meta events on the up- and downstream connection bufferevents.
|
|
||||||
* Called when EOF has been reached, a connection has been made, and on errors.
|
|
||||||
*/
|
|
||||||
static void tfe_stream_eventcb(struct bufferevent * bev, short events, void * arg)
|
|
||||||
{
|
|
||||||
struct tfe_stream_private * _stream = (struct tfe_stream_private *) arg;
|
|
||||||
enum tfe_conn_dir dir = (bev == _stream->conn_downstream.bev) ? CONN_DIR_UPSTREAM : CONN_DIR_DOWNSTREAM;
|
|
||||||
struct tfe_conn_private * this_conn = __this_conn(_stream, dir);
|
|
||||||
struct tfe_conn_private * peer_conn = __peer_conn(_stream, dir);
|
|
||||||
|
|
||||||
const struct tfe_plugin * plugins = _stream->thrmgr_ref->modules;
|
|
||||||
struct plugin_ctx * plug_ctx = NULL;
|
|
||||||
int plug_num = _stream->thrmgr_ref->nr_modules, i = 0;
|
|
||||||
enum tfe_stream_close_reason reason = REASON_PASSIVE_CLOSED;
|
|
||||||
|
|
||||||
if (events & BEV_EVENT_ERROR)
|
|
||||||
{
|
|
||||||
this_conn->closed = 1;
|
|
||||||
reason = REASON_ERROR;
|
|
||||||
goto call_plugin_close;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (events & BEV_EVENT_EOF)
|
|
||||||
{
|
|
||||||
//generate a 0 size read callback to notify plugins.
|
|
||||||
tfe_stream_readcb(bev, arg);
|
|
||||||
this_conn->closed = 1;
|
|
||||||
}
|
|
||||||
if (peer_conn->closed == 1 && this_conn->closed == 1)
|
|
||||||
{
|
|
||||||
reason = REASON_PASSIVE_CLOSED;
|
|
||||||
goto call_plugin_close;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
|
|
||||||
call_plugin_close:
|
|
||||||
for (i = 0; i < plug_num; i++)
|
|
||||||
{
|
|
||||||
_stream->calling_idx = i;
|
|
||||||
plug_ctx = _stream->plug_ctx + i;
|
|
||||||
plugins[i].on_close(&(_stream->head), _stream->thrmgr_ref->thread_id, reason, &(plug_ctx->pme));
|
|
||||||
}
|
|
||||||
|
|
||||||
tfe_stream_free(_stream);
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void ssl_get_cert_on_succ(void * result, void * user)
|
|
||||||
{
|
|
||||||
cert_t * cert = (cert_t *) result;
|
|
||||||
struct tfe_stream_private * _stream = (struct tfe_stream_private *) user;
|
|
||||||
|
|
||||||
//_stream->ssl_downstream->ssl = downstream_ssl_create(_stream);
|
|
||||||
//_stream->ssl_downstream->ssl = downstream_ssl_create(_stream);
|
|
||||||
cert_free(cert);
|
|
||||||
|
|
||||||
bufferevent_setcb(_stream->head.upstream.bev, tfe_stream_readcb, tfe_stream_writecb, tfe_stream_eventcb, _stream);
|
|
||||||
bufferevent_setcb(_stream->head.downstream.bev, tfe_stream_readcb, tfe_stream_writecb, tfe_stream_eventcb, _stream);
|
|
||||||
bufferevent_enable(_stream->head.upstream.bev, EV_READ | EV_WRITE);
|
|
||||||
bufferevent_enable(_stream->head.downstream.bev, EV_READ | EV_WRITE);
|
|
||||||
|
|
||||||
future_destroy(_stream->ssl_downstream->future_get_cert);
|
|
||||||
_stream->ssl_downstream->future_get_cert = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ssl_get_cert_on_fail(enum e_future_error err, const char * what, void * user)
|
|
||||||
{
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ssl_conn_origin_on_succ(void * result, void * user)
|
|
||||||
{
|
|
||||||
struct bufferevent * bev = (struct bufferevent *) result;
|
|
||||||
struct tfe_stream_private * _stream = (struct tfe_stream_private *) user;
|
|
||||||
|
|
||||||
_stream->head.upstream.bev = bev;
|
|
||||||
_stream->ssl_upstream->ssl = bufferevent_openssl_get_ssl(bev); /* does not inc refc */
|
|
||||||
_stream->ssl_upstream->orig_cert = SSL_get_peer_certificate(_stream->ssl_upstream->ssl);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
up_session_set(_stream->thrmgr_ref->dsess_cache, _stream->ssl_downstream->sni,
|
|
||||||
SSL_get0_session(_stream->ssl_upstream->ssl));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
_stream->ssl_downstream->future_get_cert = future_create(ssl_get_cert_on_succ, ssl_get_cert_on_fail, _stream);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
cert_mgr_async_get(_stream->ssl_downstream->future_get_cert,
|
|
||||||
_stream->thrmgr_ref->cert_mgr,
|
|
||||||
_stream->ssl_downstream->sni,
|
|
||||||
_stream->ssl_downstream->keyring_id,
|
|
||||||
_stream->ssl_upstream->orig_cert);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
future_destroy(_stream->ssl_upstream->conn_ssl_srv);
|
|
||||||
_stream->ssl_upstream->conn_ssl_srv = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ssl_conn_origin_on_fail(enum e_future_error err, const char * what, void * user)
|
|
||||||
{
|
|
||||||
//TODO:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void peek_client_hello_on_succ(void * result, void * user)
|
|
||||||
{
|
|
||||||
struct tfe_stream_private * _stream = (struct tfe_stream_private *) user;
|
|
||||||
assert(_stream->session_type == SESSION_PROTO_SSL);
|
|
||||||
|
|
||||||
struct ssl_downstream * ssl_downstream = _stream->ssl_downstream;
|
|
||||||
struct ssl_upstream * ssl_upstream = _stream->ssl_upstream;
|
|
||||||
|
|
||||||
_stream->ssl_downstream->sni = tfe_strdup((const char *) result);
|
|
||||||
future_destroy(ssl_downstream->future_sni_peek);
|
|
||||||
ssl_downstream->future_sni_peek = NULL;
|
|
||||||
|
|
||||||
_stream->ssl_upstream = ALLOC(struct ssl_upstream, 1);
|
|
||||||
_stream->ssl_upstream->conn_ssl_srv = future_create(ssl_conn_origin_on_succ, ssl_conn_origin_on_fail, _stream);
|
|
||||||
ssl_async_upstream_create(_stream->ssl_upstream->conn_ssl_srv, _stream->fd_upstream, _stream->ssl_downstream->sni,
|
|
||||||
_stream->thrmgr_ref->evbase, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void peek_client_hello_on_fail(enum e_future_error err, const char * what, void * user)
|
|
||||||
{
|
|
||||||
//TODO:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int ssl_stream_setup(struct tfe_stream_private * _stream)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int __plain_stream_conn_private_init(struct tfe_stream_private * _stream,
|
|
||||||
struct tfe_conn_private * _conn, evutil_socket_t fd)
|
|
||||||
{
|
|
||||||
struct tfe_proxy * proxy = _stream->proxy;
|
|
||||||
struct event_base * ev_base = _stream->thrmgr_ref->evbase;
|
|
||||||
|
|
||||||
_conn->bev = bufferevent_socket_new(ev_base, fd, BEV_OPT_DEFER_CALLBACKS)
|
|
||||||
_conn->fd = fd;
|
|
||||||
_conn->closed = 0;
|
|
||||||
_conn->need_shutdown = 0;
|
|
||||||
_conn->on_writing = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int plain_stream_setup(struct tfe_stream_private * _stream)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tfe_stream_setup(struct tfe_stream_private * _stream)
|
|
||||||
{
|
|
||||||
struct future * f_sni = NULL;
|
|
||||||
tfe_thread_ctx * thread = _stream->thrmgr_ref;
|
|
||||||
|
|
||||||
if (_stream->session_type == SESSION_PROTO_SSL)
|
|
||||||
{
|
|
||||||
_stream->ssl_downstream = ssl_downstream_create();
|
|
||||||
_stream->async_future = future_create(peek_client_hello_on_succ, peek_client_hello_on_fail, _stream);
|
|
||||||
ssl_async_peek_client_hello(_stream->ssl_downstream->future_sni_peek, _stream->fd_downstream,
|
|
||||||
_stream->thrmgr_ref->evbase);
|
|
||||||
}
|
|
||||||
else if (_stream->session_type == SESSION_PROTO_PLAIN)
|
|
||||||
{
|
|
||||||
bufferevent_setcb(_stream->head.upstream.bev, tfe_stream_readcb, tfe_stream_writecb, tfe_stream_eventcb, _stream);
|
|
||||||
bufferevent_setcb(_stream->head.downstream.bev, tfe_stream_readcb, tfe_stream_writecb, tfe_stream_eventcb, _stream);
|
|
||||||
bufferevent_enable(_stream->head.upstream.bev, EV_READ | EV_WRITE);
|
|
||||||
bufferevent_enable(_stream->head.downstream.bev, EV_READ | EV_WRITE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
switch (_stream->session_type)
|
|
||||||
{
|
|
||||||
case SESSION_PROTO_SSL:
|
|
||||||
// for SSL, defer dst connection setup to initial_readcb
|
|
||||||
|
|
||||||
thread->stat.value[SSL_NUM]++;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
//todo:
|
|
||||||
stream_fd_readcb(_stream->fd_downstream, 0, _stream);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct tfe_stream_private * tfe_stream_create(evutil_socket_t fd_downstream, evutil_socket_t fd_upstream,
|
|
||||||
enum tfe_session_proto session_type, tfe_thread_ctx * thread)
|
|
||||||
{
|
|
||||||
struct tfe_stream_private * conn_private = NULL;
|
|
||||||
struct tfe_stream * conn_public = NULL;
|
|
||||||
conn_private = ALLOC(struct tfe_stream_private, 1);
|
|
||||||
conn_private->session_type = session_type;
|
|
||||||
conn_private->fd_downstream = fd_downstream;
|
|
||||||
conn_private->fd_upstream = fd_upstream;
|
|
||||||
conn_private->thrmgr_ref = thread;
|
|
||||||
conn_private->is_plugin_opened = 0;
|
|
||||||
conn_public = &(conn_private->head);
|
|
||||||
thread->stat.value[STREAM_NUM]++;
|
|
||||||
return conn_private;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* vim: set noet ft=c: */
|
|
||||||
Reference in New Issue
Block a user