summaryrefslogtreecommitdiff
path: root/plugin/protocol/http2/src/http2_plugin.cpp
diff options
context:
space:
mode:
authorfengweihao <[email protected]>2019-02-22 15:42:20 +0800
committerzhengchao <[email protected]>2019-05-24 18:45:44 +0800
commit10c0ef7b762799987eb713b66b4b694155f969fc (patch)
treea753030e3e3ca1052675523725843ae9bc69c647 /plugin/protocol/http2/src/http2_plugin.cpp
parentfcb1581a1ccf931a41e880d921cbee2d5db99aa1 (diff)
*由于git rebase冲突删除原tfe-new-http2分支
*提交包括http2数据替换,转发,截断,缓存代码 *合并最新develop-tfe3a后,http2验证代码提交 *http2重构验证代码提交 *http2添加br压缩解压缩接口和测试用例 *http2定时删除session信息代码提交 *修复bug,访问二级链接时由于nghttp2库收到control ping后,自发control ping包 造成链接断开后重连现象 *修复bug, 链接建立后服务端优先发送control包,未处理此数据包,造成页面访问失败
Diffstat (limited to 'plugin/protocol/http2/src/http2_plugin.cpp')
-rw-r--r--plugin/protocol/http2/src/http2_plugin.cpp207
1 files changed, 207 insertions, 0 deletions
diff --git a/plugin/protocol/http2/src/http2_plugin.cpp b/plugin/protocol/http2/src/http2_plugin.cpp
new file mode 100644
index 0000000..7576fef
--- /dev/null
+++ b/plugin/protocol/http2/src/http2_plugin.cpp
@@ -0,0 +1,207 @@
+/*************************************************************************
+ > File Name: detect_http2_plugin.cpp
+ > Author:
+ > Mail:
+ > Created Time: 2018年09月11日 星期二 15时38分54秒
+ ************************************************************************/
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <assert.h>
+#include <event.h>
+
+#include <tfe_stream.h>
+#include <tfe_utils.h>
+#include <tfe_plugin.h>
+#include <tfe_proxy.h>
+#include <malloc.h>
+
+#include <http2_stream.h>
+#include <http2_common.h>
+
+#include <MESA/MESA_prof_load.h>
+
+/* Magic Header : PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n */
+static const uint8_t kMagicHello[] = {
+ 0x50, 0x52, 0x49, 0x20, 0x2a, 0x20, 0x48, 0x54,
+ 0x54, 0x50, 0x2f, 0x32, 0x2e, 0x30, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x53, 0x4d, 0x0d, 0x0a, 0x0d, 0x0a
+};
+
+#define get_u_int8_t(X,O) (*(u_int8_t *)(((u_int8_t *)X) + O))
+
+#define TFE_BASIC_CFG "conf/tfe/tfe.conf"
+
+#define MAGIC_FRAME_LENGTH 24
+#define SET_FRAME_LENGTH 18
+
+struct event_timer_ctx
+{
+ Http2Plugin *plugin;
+ unsigned int thread_id;
+};
+
+void load_logging_conf(const char *config)
+{
+ RTLogInit2Data *logging_sc_lid = rt_log_data();
+
+ MESA_load_profile_int_def(config, (const char *)"http",(const char *)"loglevel",
+ &logging_sc_lid->run_log_level, 10);
+ MESA_load_profile_string_def(config, (const char *)"http",(const char *)"logfile",
+ logging_sc_lid->run_log_path, 128, "log/http2.log");
+
+ logging_sc_lid->run_log_handle = MESA_create_runtime_log_handle(logging_sc_lid->run_log_path, logging_sc_lid->run_log_level);
+ if(logging_sc_lid->run_log_handle == NULL){
+ TFE_LOG_ERROR(logging_sc_lid->run_log_handle, "Create log runtime_log_handle error, init failed!");
+ }
+ return;
+}
+
+static void http2_plugin_timer_gc_cb(evutil_socket_t fd, short what, void * arg)
+{
+ struct tfe_session_info_t *session_info = (struct tfe_session_info_t *)arg;
+ sess_data_ctx_fini(session_info, NULL, session_info->thread_id);
+}
+
+static int
+http2_plugin_init(struct tfe_proxy * proxy)
+{
+ Http2Plugin *plugin = http2_plugin();
+
+ unsigned int thread_nu = tfe_proxy_get_work_thread_count();
+
+ load_logging_conf(TFE_BASIC_CFG);
+
+ for (unsigned int thread_id = 0; thread_id < thread_nu; thread_id++){
+#if 0
+ struct tfe_session_info_t session_info = plugin->session_info[thread_id];
+ TAILQ_INIT(&(session_info.list));
+ session_info.thread_id = thread_id;
+ session_info.as_client = 0;
+
+ struct event_base * ev_base = tfe_proxy_get_work_thread_evbase(thread_id);
+
+ struct timeval timer = {0, 500 * 1000};
+ struct event * event = event_new(ev_base, -1, EV_PERSIST, http2_plugin_timer_gc_cb, &session_info);
+
+ if (unlikely(event == NULL)){
+ TFE_LOG_ERROR(rt_log_data()->run_log_handle, "Create timer error, init failed!");
+ }
+
+ evtimer_add(event, &timer);
+ plugin->event[thread_id] = event;
+#endif
+ }
+
+ return 0;
+}
+
+static void
+http2_plugin_deinit(struct tfe_proxy * proxy)
+{
+ return;
+}
+
+static int
+http2_stream_open(const struct tfe_stream *stream, unsigned int thread_id,
+ enum tfe_conn_dir dir, void ** pme)
+{
+ struct stream_tap_info_t *tapinfo = ALLOC(struct stream_tap_info_t, 1);
+ assert(tapinfo);
+
+ memset(tapinfo, 0, sizeof(struct stream_tap_info_t));
+ tapinfo->preempted = 0;
+ tapinfo->session_info = tfe_session_info_init();
+
+ *pme = (void *)tapinfo;
+
+ return 0;
+}
+
+static enum tfe_stream_action
+http2_stream_data(const struct tfe_stream * stream, unsigned int thread_id,
+ enum tfe_conn_dir dir, const unsigned char * data, size_t len, void ** pme)
+{
+ static unsigned int defer_bytes = 0;
+ struct stream_tap_info_t *tapinfo = (struct stream_tap_info_t *)(*pme);
+
+ if (tapinfo->preempted == 0){
+
+ if (dir == CONN_DIR_UPSTREAM){
+ if (len < SET_FRAME_LENGTH){
+ defer_bytes = SET_FRAME_LENGTH;
+ tfe_stream_action_set_opt(stream, ACTION_OPT_DEFER_BYTES, (void *) &defer_bytes, sizeof(defer_bytes));
+ return ACTION_DEFER_DATA;
+ }
+ /*setting frame: 00 00 12 04 00 00 00 00 00 00 03 00 00 00 80 00 04 7f ff ff ff 00 05 00 ff ff ff 00 00 04 08 00
+ 00 00 00 00 7f ff 00 00 ***/
+
+ if (get_u_int8_t(data, 3) == 0x4
+ && ((get_u_int8_t(data, 9) == 0x00 && get_u_int8_t(data, 10) == 0x03)
+ || (get_u_int8_t(data, 15) == 0x00 && get_u_int8_t(data, 16) == 0x04)
+ || (get_u_int8_t(data, 21) == 0x00 && get_u_int8_t(data, 22) == 0x05))){
+ }else{
+ goto finish;
+ }
+ }
+
+ if (dir == CONN_DIR_DOWNSTREAM){
+ /* Protocol Identification, we need 24 bytes at least to tell it is HTTP2 or not */
+ if (len < MAGIC_FRAME_LENGTH){
+ defer_bytes = MAGIC_FRAME_LENGTH;
+ tfe_stream_action_set_opt(stream, ACTION_OPT_DEFER_BYTES, (void *) &defer_bytes, sizeof(defer_bytes));
+ return ACTION_DEFER_DATA;
+ }
+ if (memcmp(data, kMagicHello, MAGIC_FRAME_LENGTH) != 0){
+ goto finish;
+ }
+ }
+ if (tfe_stream_preempt(stream) != 0)
+ goto detach;
+
+ tapinfo->preempted = 1;
+ }
+
+ return (dir == CONN_DIR_DOWNSTREAM) ? detect_down_stream_protocol(tapinfo->session_info, stream, thread_id,
+ data, len) : detect_up_stream_protocol(tapinfo->session_info, stream, thread_id, data, len);
+
+detach:
+ tfe_stream_detach(stream);
+finish:
+ return ACTION_FORWARD_DATA;
+}
+
+static void
+http2_stream_close(const struct tfe_stream * stream, unsigned int thread_id,
+ enum tfe_stream_close_reason reason, void ** pme)
+{
+ struct stream_tap_info_t *tapinfo = (struct stream_tap_info_t *)(*pme);
+
+ sess_data_ctx_fini(tapinfo->session_info, stream, thread_id);
+
+ free(tapinfo->session_info);
+ tapinfo->session_info = NULL;
+
+ free(tapinfo);
+ tapinfo = NULL;
+
+ *pme = NULL;
+
+ return;
+}
+
+static struct tfe_plugin __nghttp2_plugin_info =
+{
+ .symbol = "HTTP2",
+ .type = TFE_PLUGIN_TYPE_PROTOCOL,
+ .on_init = http2_plugin_init,
+ .on_deinit = http2_plugin_deinit,
+ .on_open = http2_stream_open,
+ .on_data = http2_stream_data,
+ .on_close = http2_stream_close
+};
+
+TFE_PLUGIN_REGISTER(HTTP2, __nghttp2_plugin_info)
+