From 2cc0d49d296121dd587594b2095232ece1e69c05 Mon Sep 17 00:00:00 2001 From: zhengchao Date: Tue, 21 Aug 2018 19:01:10 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=A2=9E=E5=8A=A0cast=20async=20result?= =?UTF-8?q?=E7=9A=84=E5=B7=A5=E5=85=B7=E5=87=BD=E6=95=B0=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- platform/src/ssl_stream.cpp | 95 +++++++++++++++++++++++++------------ 1 file changed, 64 insertions(+), 31 deletions(-) diff --git a/platform/src/ssl_stream.cpp b/platform/src/ssl_stream.cpp index 13c2e61..edf4c63 100644 --- a/platform/src/ssl_stream.cpp +++ b/platform/src/ssl_stream.cpp @@ -19,6 +19,7 @@ #include #include + #include #include #include @@ -26,19 +27,18 @@ #include #include -struct peek_sni_ctx +struct peek_client_hello_ctx { - /* ssl */ + unsigned char sni_peek_retries; /* max 64 SNI parse retries */ - char* sni; + struct event* ev; struct event_base* evbase; }; - -void peek_sni_ctx_free(void* ctx) +void peek_client_hello_ctx_free(void* ctx) { - struct peek_sni_ctx * _ctx=(struct peek_sni_ctx *)ctx; + struct peek_client_hello_ctx * _ctx=(struct peek_client_hello_ctx *)ctx; event_free(_ctx->ev); _ctx->ev = NULL; free(_ctx->sni); @@ -46,13 +46,40 @@ void peek_sni_ctx_free(void* ctx) free(_ctx); return; } +struct ssl_client_hello* ssl_get_peek_result(void* result) +{ + struct ssl_client_hello* p=(struct ssl_client_hello* )result, *copy=NULL; + copy=ALLOC(struct ssl_client_hello*,1); + if(p!=NULL) + { + copy->sni=tfe_strdup(p->sni); + copy->cipher_suites=tfe_strdup(p->cipher_suites); + copy->version=p->version; + } + return copy; +} +void ssl_free_peek_result(struct ssl_client_hello* p) +{ + if(p==NULL) + { + return; + } + free(p->sni); + p->sni=NULL; + free(p->cipher_suites); + p->cipher_suites=NULL; + p->cipher_suites=NULL; + free(p); + return; +} -static void peek_sni_cb(evutil_socket_t fd, short what, void * arg) +static void peek_client_hello_cb(evutil_socket_t fd, short what, void * arg) { struct promise* promise=(struct promise*)arg; - struct peek_sni_ctx* ctx= (struct peek_sni_ctx*)promise->ctx; - - + struct peek_client_hello_ctx* ctx= (struct peek_client_hello_ctx*)promise->ctx; + struct ssl_client_hello *result=NULL; + memset(&result, 0, sizeof(result)); + char* sni=NULL; unsigned char buf[1024]; ssize_t n=0; const unsigned char * chello=NULL; @@ -62,19 +89,20 @@ static void peek_sni_cb(evutil_socket_t fd, short what, void * arg) if (n == -1) { TFE_LOG_ERROR("Error peeking on fd, aborting connection\n"); - goto promise_failed; + goto failed; } if (n == 0) { - goto promise_failed; + goto failed; } - - rv = ssl_tls_clienthello_parse(buf, n, 0, &chello, &ctx->sni); + result=ssl_get_peek_result(NULL); + //todo: parse version and cipher suites. + rv = ssl_tls_clienthello_parse(buf, n, 0, &chello, &result->sni); if ((rv == 1) && !chello) { TFE_LOG_ERROR("Peeking did not yield a (truncated) ClientHello message, aborting connection\n"); - goto promise_failed; + goto failed; } if ((rv == 1) && chello && (ctx->sni_peek_retries++ < 50)) @@ -90,32 +118,37 @@ static void peek_sni_cb(evutil_socket_t fd, short what, void * arg) struct timeval retry_delay = {0, 100}; event_free(ctx->ev); - ctx->ev = event_new(ctx->evbase, fd, 0, peek_sni_cb, promise); + ctx->ev = event_new(ctx->evbase, fd, 0, peek_client_hello_cb, promise); assert(ctx->ev!=NULL); event_add(ctx->ev, &retry_delay); return; } - promise_set_ctx(promise, NULL, NULL); - promise->f.cb_success(ctx->sni,promise->f.user); - peek_sni_ctx_free(ctx); + + promise_dettach_ctx(promise); + promise_success(promise, result); + ssl_free_peek_result(result); + peek_client_hello_ctx_free(ctx); return; - -promise_failed: - promise->f.cb_failed(FUTURE_ERROR_EXCEPTION,"too many tries",promise->f.user); - peek_sni_ctx_free(ctx); - promise_set_ctx(promise, NULL,NULL); +failed: + promise_failed(promise,FUTURE_ERROR_EXCEPTION,"too many tries"); + peek_client_hello_ctx_free(ctx); + promise_dettach_ctx(promise); + ssl_free_peek_result(result); + return; } -void ssl_async_peek_sni( struct future* future, evutil_socket_t fd, struct event_base *evbase) + +void ssl_async_peek_client_hello(struct future* future, evutil_socket_t fd, struct event_base *evbase) { struct event * ev=NULL; struct promise* p=future_to_promise(future); - struct peek_sni_ctx* ctx=ALLOC(struct peek_sni_ctx, 1); - ctx->ev = event_new(evbase, fd, EV_READ, peek_sni_cb, p); + + struct peek_client_hello_ctx* ctx=ALLOC(struct peek_client_hello_ctx, 1); + ctx->ev = event_new(evbase, fd, EV_READ, peek_client_hello_cb, p); event_add(evbase, NULL); - promise_set_ctx(p, ctx,peek_sni_ctx_free); + promise_set_ctx(p, ctx, peek_client_hello_ctx_free); return; } @@ -166,8 +199,7 @@ static void ssl_connect_origin_eventcb(struct bufferevent * bev, short events, v return } -void ssl_async_connect_origin(struct future* future, evutil_socket_t fd, const char* sni, - struct event_base *evbase, struct tfe_config *opts) +void ssl_async_connect_origin(struct future* future, const struct ssl_client_hello* client_hello, evutil_socket_t fd, const char* sni, struct event_base *evbase) { struct promise* p=future_to_promise(future); struct ssl_connect_origin_ctx* ctx=ALLOC(struct ssl_connect_origin_ctx, 1); @@ -827,7 +859,8 @@ static int pxy_ossl_servername_cb(SSL * ssl, UNUSED int * al, void * arg) * Create new SSL context for outgoing connections to the original destination. * If hostname sni is provided, use it for Server Name Indication. */ -static SSL* upstream_ssl_create(tfe_config*opts, const char* sni) + +static SSL* upstream_ssl_create(const struct ssl_client_hello* client_hello, int sslversion, const char* sni, MESA_htable_handle* dsess_cache) { SSL_CTX* sslctx=NULL; SSL* ssl=NULL; From be813f99a4ac7c60a1d87d40f3d52c3ff390987a Mon Sep 17 00:00:00 2001 From: zhengchao Date: Tue, 21 Aug 2018 19:32:37 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=AE=9A=E4=B9=89future=5Fresult=5Ft?= =?UTF-8?q?=EF=BC=8C=E6=95=B4=E7=90=86ssl=5Fstream.h?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/include/tfe_future.h | 4 ++-- platform/include/internal/ssl_stream.h | 19 +++++++++++++++++++ platform/include/internal/stream.h | 8 -------- platform/src/ssl_stream.cpp | 3 +-- platform/src/tfe_stream.cpp | 8 ++++---- 5 files changed, 26 insertions(+), 16 deletions(-) create mode 100644 platform/include/internal/ssl_stream.h diff --git a/common/include/tfe_future.h b/common/include/tfe_future.h index e9fc5d2..80f2b27 100644 --- a/common/include/tfe_future.h +++ b/common/include/tfe_future.h @@ -8,8 +8,8 @@ enum e_future_error struct promise; struct future; - -typedef void (future_success_cb)(void * result, void * user); +typedef void future_result_t; +typedef void (future_success_cb)(future_result_t* result, void * user); typedef void (future_failed_cb)(enum e_future_error err, const char * what, void * user); typedef void (promise_ctx_destroy_cb)(struct promise * p); diff --git a/platform/include/internal/ssl_stream.h b/platform/include/internal/ssl_stream.h new file mode 100644 index 0000000..733bef9 --- /dev/null +++ b/platform/include/internal/ssl_stream.h @@ -0,0 +1,19 @@ +#pragma once +#include "tfe_future.h" + +struct ssl_client_hello +{ + int version; + char* sni; + char* cipher_suites; +}; +struct ssl_client_hello* ssl_get_peek_result(future_result_t* result); +void ssl_free_peek_result(struct ssl_client_hello* client_hello); +void ssl_async_peek_client_hello(struct future* future, evutil_socket_t fd, struct event_base *evbase); + +void ssl_async_connect_origin(struct future* future, const struct ssl_client_hello* client_hello, evutil_socket_t fd, const char* sni, struct event_base *evbase); + +struct ssl_downstream * ssl_downstream_create(); +void ssl_upstream_free(struct ssl_upstream * p); +void ssl_downstream_free(struct ssl_downstream * p); + diff --git a/platform/include/internal/stream.h b/platform/include/internal/stream.h index 35d9947..9ddb678 100644 --- a/platform/include/internal/stream.h +++ b/platform/include/internal/stream.h @@ -116,11 +116,3 @@ struct tfe_stream_private * tfe_stream_create(evutil_socket_t fd_downstream, evu void tfe_stream_setup(struct tfe_stream_private * _stream); -void ssl_async_connect_origin(struct future * future, evutil_socket_t fd, const char * sni, - struct event_base * evbase, struct tfe_config * opts); - -void ssl_async_peek_sni(struct future * future, evutil_socket_t fd, struct event_base * evbase); - -struct ssl_downstream * ssl_downstream_create(); -void ssl_upstream_free(struct ssl_upstream * p); -void ssl_downstream_free(struct ssl_downstream * p); diff --git a/platform/src/ssl_stream.cpp b/platform/src/ssl_stream.cpp index edf4c63..75b2ca8 100644 --- a/platform/src/ssl_stream.cpp +++ b/platform/src/ssl_stream.cpp @@ -31,7 +31,6 @@ struct peek_client_hello_ctx { unsigned char sni_peek_retries; /* max 64 SNI parse retries */ - struct event* ev; struct event_base* evbase; @@ -46,7 +45,7 @@ void peek_client_hello_ctx_free(void* ctx) free(_ctx); return; } -struct ssl_client_hello* ssl_get_peek_result(void* result) +struct ssl_client_hello* ssl_get_peek_result(future_result_t* result) { struct ssl_client_hello* p=(struct ssl_client_hello* )result, *copy=NULL; copy=ALLOC(struct ssl_client_hello*,1); diff --git a/platform/src/tfe_stream.cpp b/platform/src/tfe_stream.cpp index 6ba40bf..820ab3d 100644 --- a/platform/src/tfe_stream.cpp +++ b/platform/src/tfe_stream.cpp @@ -457,7 +457,7 @@ void ssl_conn_origin_on_fail(enum e_future_error err, const char * what, void * assert(0); } -void peek_sni_on_succ(void * result, void * user) +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); @@ -475,7 +475,7 @@ void peek_sni_on_succ(void * result, void * user) _stream->thrmgr_ref->evbase, NULL); } -void peek_sni_on_fail(enum e_future_error err, const char * what, void * user) +void peek_client_hello_on_fail(enum e_future_error err, const char * what, void * user) { //TODO: assert(0); @@ -501,8 +501,8 @@ void tfe_stream_setup(struct tfe_stream_private * _stream) case SESSION_PROTO_SSL: // for SSL, defer dst connection setup to initial_readcb _stream->ssl_downstream = ssl_downstream_create(); - _stream->async_future = future_create(peek_sni_on_succ, peek_sni_on_fail, _stream); - ssl_async_peek_sni(_stream->ssl_downstream->future_sni_peek, _stream->fd_downstream, + _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); thread->stat.value[SSL_NUM]++; break;