diff --git a/common/include/tfe_utils.h b/common/include/tfe_utils.h index 525ea6e..8718c71 100644 --- a/common/include/tfe_utils.h +++ b/common/include/tfe_utils.h @@ -40,6 +40,12 @@ do { fprintf(stderr, fmt "\n", ##__VA_ARGS__); \ #define TFE_LOG_DEBUG(handler, fmt, ...) \ do { MESA_handle_runtime_log(handler, RLOG_LV_DEBUG, "tfe", fmt, ##__VA_ARGS__); } while(0) \ +#define CHECK_OR_EXIT(condition, fmt, ...) \ +do { if(!(condition)) { TFE_LOG_ERROR(g_default_logger, fmt, ##__VA_ARGS__); exit(EXIT_FAILURE); } } while(0) \ + +#define CHECK_OR_DIE(condition, fmt, ...) \ +do { if(!(condition)) { TFE_LOG_ERROR(g_default_logger, fmt, ##__VA_ARGS__); abort(); } } while(0) \ + #define TFE_STREAM_LOG_DEBUG(stream, fmt, ...) #define TFE_STREAM_LOG_INFO(stream, fmt, ...) #define TFE_STREAM_LOG_ERROR(stream, fmt, ...) diff --git a/platform/include/internal/platform.h b/platform/include/internal/platform.h index b2915c1..d8184a3 100644 --- a/platform/include/internal/platform.h +++ b/platform/include/internal/platform.h @@ -98,6 +98,9 @@ struct tfe_stream_private /* SUSPEND */ bool is_suspended; enum tfe_conn_dir suspended_by; + + /* KEYRING-ID */ + unsigned keyring_id; }; static inline void * __STREAM_LOGGER(struct tfe_stream_private * _stream) diff --git a/platform/include/internal/proxy.h b/platform/include/internal/proxy.h index 72effd1..3fc7479 100644 --- a/platform/include/internal/proxy.h +++ b/platform/include/internal/proxy.h @@ -34,6 +34,9 @@ struct tfe_proxy_accept_para bool is_set_session_type; enum tfe_stream_proto session_type; bool passthrough; + + /* addition info */ + unsigned int keyring_id; }; struct tfe_proxy diff --git a/platform/include/internal/tcp_stream.h b/platform/include/internal/tcp_stream.h index 76b7de7..63fcd9f 100644 --- a/platform/include/internal/tcp_stream.h +++ b/platform/include/internal/tcp_stream.h @@ -7,7 +7,8 @@ struct tfe_stream * tfe_stream_create(struct tfe_proxy * pxy, struct tfe_thread_ enum tfe_stream_option { TFE_STREAM_OPT_SESSION_TYPE, - TFE_STREAM_OPT_PASSTHROUGH + TFE_STREAM_OPT_PASSTHROUGH, + TFE_STREAM_OPT_KEYRING_ID }; int tfe_stream_option_set(struct tfe_stream * stream, enum tfe_stream_option opt, const void * arg, size_t sz_arg); diff --git a/platform/src/kni_acceptor.cpp b/platform/src/kni_acceptor.cpp index 9ac9012..d88883e 100644 --- a/platform/src/kni_acceptor.cpp +++ b/platform/src/kni_acceptor.cpp @@ -22,22 +22,61 @@ #define TFE_CONFIG_KNI_UXDOMAIN_PATH_DEFAULT "/var/run/.tfe_kni_acceptor_handler" #endif +/* The KNI and TFE communicate with each other by UNIX-based socket, + * and the protocol between them is based on TLV format(Type-Length-Value). + * The byte order for each entry in the protocol are Host-Ordered. + * + * I. Magic and Total counts of T-L-V tuples, at front of the SOCKET stream. + * II. After Magic header, the stream consist of several T-L-V tuples. + * + * Note. Magic = 0x4d5a + * Consider of the byte align problem, the minimum length of the value is 4bytes(32-bits). + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Magic | Total counts of TLV | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Type | Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Value | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Type | Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Value | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | ....... | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +enum +{ + KNI_TLV_MAGIC = 0x4d5a +}; + enum KNI_TLV_TYPE { - KNI_TLV_TYPE_PRO = 0x01, + KNI_TLV_TYPE_PROTOCOL = 0x0001, + KNI_TLV_TYPE_KEYRING_ID = 0x0002 }; enum KNI_TLV_VALUE { - KNI_TLV_VALUE_HTTP = 0x01, - KNI_TLV_VALUE_SSL = 0x02, + KNI_TLV_VALUE_HTTP = 0x1, + KNI_TLV_VALUE_SSL = 0x2, +}; + +struct kni_tlv_header +{ + uint16_t magic; + uint16_t counts; }; struct kni_tlv_info { - char type; - short len; - char value; + uint16_t type; + uint16_t len; + uint8_t value[0]; }; struct kni_acceptor @@ -70,6 +109,80 @@ void __kni_conn_close(struct kni_acceptor * ctx) if (ctx->pid_kni_conn != 0) ctx->pid_kni_conn = 0; } +static int __kni_parse_tlv_data(struct kni_acceptor * ctx, + struct tfe_proxy_accept_para * out_para, const char * data, size_t sz_data) +{ + const char * __cursor = data; + size_t __left_data_len = sz_data; + + /* Parse the STREAM header */ + struct kni_tlv_header * tlv_header = (struct kni_tlv_header *)__cursor; + if (__left_data_len < sizeof(struct kni_tlv_header)) + { + TFE_LOG_ERROR(ctx->logger, "Invalid KNI TLV header format, length is not enough."); + return -1; + } + + if (tlv_header->magic != KNI_TLV_MAGIC) + { + TFE_LOG_ERROR(ctx->logger, "Invalid KNI TLV header magic number %x", tlv_header->magic); + return -2; + } + + unsigned int nr_tlv_tuples = tlv_header->counts; + assert(nr_tlv_tuples != 0 && nr_tlv_tuples < 255); + + __left_data_len -= sizeof(struct kni_tlv_header); + __cursor += sizeof(struct kni_tlv_header); + + for(unsigned int iter_tlv_tuples = 0; iter_tlv_tuples < nr_tlv_tuples; iter_tlv_tuples++) + { + struct kni_tlv_info * tlv_info = (struct kni_tlv_info *) __cursor; + size_t sz_tlv_info = tlv_info->len + sizeof(struct kni_tlv_info); + + if (__left_data_len < sz_tlv_info) + { + TFE_LOG_ERROR(ctx->logger, "TLV info declares invalid value length, Too long."); + return -3; + } + + switch (tlv_info->type) + { + /* VALUE is uint32_t, length is 4 */ + case KNI_TLV_TYPE_PROTOCOL: + { + uint32_t __value = *(uint32_t *)(tlv_info->value); + if(__value == KNI_TLV_VALUE_HTTP) + { + out_para->session_type = STREAM_PROTO_PLAIN; + } + if (__value == KNI_TLV_VALUE_SSL) + { + out_para->session_type = STREAM_PROTO_SSL; + } + assert(tlv_info->len == sizeof(uint32_t)); + break; + } + + /* VALUE is uint32_t, length is 4 */ + case KNI_TLV_TYPE_KEYRING_ID: + { + uint32_t __value = *(uint32_t *)(tlv_info->value); + out_para->keyring_id = __value; + assert(tlv_info->len == sizeof(uint32_t)); + break; + } + + default: assert(0); + } + + __cursor += sz_tlv_info; + __left_data_len -= sz_tlv_info; + } + + return 0; +} + void __kni_event_cb(evutil_socket_t fd, short what, void * user) { struct kni_acceptor * __ctx = (struct kni_acceptor *)user; @@ -89,12 +202,11 @@ void __kni_event_cb(evutil_socket_t fd, short what, void * user) constexpr static int __CONTROLLEN = CMSG_SPACE(__TRANS_FDS_MAX * sizeof(int)); char __buffer[512] = {0}; - struct kni_tlv_info * __tlv_info = (struct kni_tlv_info *)(__buffer); - struct iovec __iovec[1]; struct msghdr __msghdr; char __cmptr[__CONTROLLEN]; + __iovec[0].iov_base = __buffer; __iovec[0].iov_len = sizeof(__buffer); @@ -124,27 +236,13 @@ void __kni_event_cb(evutil_socket_t fd, short what, void * user) __cmsghdr = CMSG_FIRSTHDR(&__msghdr); __fds = (int *) (CMSG_DATA(__cmsghdr)); - assert(__tlv_info->type == KNI_TLV_TYPE_PRO); - - enum tfe_stream_proto __session_proto; - if (__tlv_info->value == KNI_TLV_VALUE_HTTP) + if(__kni_parse_tlv_data(__ctx, &__accept_para, __buffer, (size_t)rd) < 0) { - __session_proto = STREAM_PROTO_PLAIN; - } - else if (__tlv_info->value == KNI_TLV_VALUE_SSL) - { - __session_proto = STREAM_PROTO_SSL; - } - else - { - assert(0); goto __close_kni_connection; } - __accept_para.session_type = __session_proto; __accept_para.downstream_fd = __fds[0]; __accept_para.upstream_fd = __fds[1]; - __accept_para.passthrough = false; if (tfe_proxy_fds_accept(__ctx->proxy, &__accept_para) < 0) { diff --git a/platform/src/proxy.cpp b/platform/src/proxy.cpp index 6df17b0..e76d315 100644 --- a/platform/src/proxy.cpp +++ b/platform/src/proxy.cpp @@ -93,6 +93,7 @@ int tfe_proxy_fds_accept(struct tfe_proxy * ctx, const struct tfe_proxy_accept_p struct tfe_stream * stream = tfe_stream_create(ctx, worker_thread_ctx); tfe_stream_option_set(stream, TFE_STREAM_OPT_SESSION_TYPE, ¶->session_type, sizeof(para->session_type)); + tfe_stream_option_set(stream, TFE_STREAM_OPT_KEYRING_ID, ¶->keyring_id, sizeof(para->keyring_id)); /* FOR DEBUG */ if (para->passthrough || ctx->tcp_all_passthrough) @@ -266,10 +267,6 @@ int tfe_stat_init(struct tfe_proxy * proxy, const char * profile) return 0; } - -#define CHECK_OR_EXIT(condition, fmt, ...) \ -do { if(!(condition)) { TFE_LOG_ERROR(g_default_logger, fmt, ##__VA_ARGS__); exit(EXIT_FAILURE); } } while(0) \ - int main(int argc, char *argv[]) { const char* main_profile="./conf/tfe.conf"; diff --git a/platform/src/tcp_stream.cpp b/platform/src/tcp_stream.cpp index 24d17a6..e683f89 100644 --- a/platform/src/tcp_stream.cpp +++ b/platform/src/tcp_stream.cpp @@ -132,7 +132,7 @@ void tfe_stream_resume(const struct tfe_stream * stream) bufferevent_enable(_stream->conn_upstream->bev, EV_READ | EV_WRITE); bufferevent_enable(_stream->conn_downstream->bev, EV_READ | EV_WRITE); - if(_stream->suspended_by == CONN_DIR_DOWNSTREAM) + if (_stream->suspended_by == CONN_DIR_DOWNSTREAM) { bufferevent_trigger(_stream->conn_downstream->bev, EV_READ, BEV_OPT_DEFER_CALLBACKS); } @@ -745,7 +745,7 @@ void ssl_upstream_create_on_success(future_result_t * result, void * user) 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); + _stream->ssl_upstream, _stream->defer_fd_downstream, _stream->keyring_id, ev_base); } void ssl_upstream_create_on_fail(enum e_future_error err, const char * what, void * user) @@ -1034,6 +1034,11 @@ int tfe_stream_option_set(struct tfe_stream * stream, enum tfe_stream_option opt assert(sz_arg == sizeof(bool)); _stream->passthough = *(bool *) arg; } + else if (opt == TFE_STREAM_OPT_KEYRING_ID) + { + assert(sz_arg == sizeof(unsigned int)); + _stream->keyring_id = *(unsigned int *) arg; + } return 0; }