diff options
| author | fengweihao <[email protected]> | 2019-02-22 15:42:20 +0800 |
|---|---|---|
| committer | zhengchao <[email protected]> | 2019-05-24 18:45:44 +0800 |
| commit | 10c0ef7b762799987eb713b66b4b694155f969fc (patch) | |
| tree | a753030e3e3ca1052675523725843ae9bc69c647 /plugin/protocol/http2/src/http2_common.cpp | |
| parent | fcb1581a1ccf931a41e880d921cbee2d5db99aa1 (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_common.cpp')
| -rw-r--r-- | plugin/protocol/http2/src/http2_common.cpp | 409 |
1 files changed, 409 insertions, 0 deletions
diff --git a/plugin/protocol/http2/src/http2_common.cpp b/plugin/protocol/http2/src/http2_common.cpp new file mode 100644 index 0000000..ee2cfd8 --- /dev/null +++ b/plugin/protocol/http2/src/http2_common.cpp @@ -0,0 +1,409 @@ +/************************************************************************* + > File Name: http2_common.cpp + > Author: + > Mail: + > Created Time: 2018年09月21日 星期五 13时59分03秒 + ************************************************************************/ + +#include <iostream> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> + +#include <tfe_utils.h> +#include <tfe_stream.h> +#include <event2/buffer.h> + +#include <http2_common.h> + +RTLogInit2Data logging_sc_lid = { + .run_log_level = 1, +}; + +RTLogInit2Data *rt_log_data() +{ + return &logging_sc_lid; +}; + +Http2Plugin g_http2_plugin = { + +}; + +Http2Plugin *http2_plugin() +{ + return &g_http2_plugin; +} + +const char * +try_val_to_str_idx(const unsigned int val, const struct value_string *vs, int *idx) +{ + int i = 0; + if (idx == NULL){ + goto finish; + } + + if(vs) { + while (vs[i].strptr) { + if (vs[i].value == val) { + *idx = i; + return(vs[i].strptr); + } + i++; + } + } + +finish: + *idx = -1; + return NULL; +} + +/* Find the index of a string in a value_string, or -1 when not present */ +int +str_to_val_idx(const char *val, const struct value_string *vs) +{ + int i = 0; + + if(vs) { + while (vs[i].strptr) { + if (strcmp(vs[i].strptr, val) == 0) { + return i; + } + i++; + } + } + return -1; +} + +const char* +val_to_str(unsigned int val, const struct value_string *vs) +{ + int ignore_me; + + return try_val_to_str_idx(val, vs, &ignore_me); +} + +int +str_to_val(const char *val, const struct value_string *vs) +{ + return str_to_val_idx(val, vs); +} + +int inflate_init(struct z_stream_st **strm, int gzip) +{ + if (*strm != NULL) + return Z_OK; + + *strm = ALLOC(struct z_stream_st, 1); + assert(*strm); + + /* ZSTREAM */ + (*strm)->zst.zalloc = NULL; + (*strm)->zst.zfree = NULL; + (*strm)->zst.opaque = NULL; + (*strm)->zst.avail_in = 0; + (*strm)->zst.next_in = Z_NULL; + + int ret = 0; + if (gzip == HTTP2_CONTENT_ENCODING_GZIP) + ret = inflateInit2(&((*strm)->zst), MAX_WBITS + 16); + else if (gzip == HTTP2_CONTENT_ENCODING_DEFLATE) + ret = inflateInit2(&((*strm)->zst), -MAX_WBITS); + else if (gzip == HTTP2_CONTENT_ENCODING_BR){ + (*strm)->brdec_state = BrotliDecoderCreateInstance(NULL, NULL, NULL); + if ((*strm)->brdec_state != NULL) + ret = Z_OK; + } + + if (ret != Z_OK) + FREE(strm); + + return ret; +} + +int inflate_br_read(struct z_stream_st **strm, const uint8_t *source, int len, + char **dest, int *outlen) +{ +#define CHUNK (1024 * 1024 * 4) + unsigned char out[CHUNK]; + int totalsize = 0 ,ret = -1; + size_t available_out; + unsigned char * next_out; + + size_t available_in = len; + const unsigned char * next_in = source; + + for ( ; ; ){ + available_out = CHUNK; + next_out = out; + + ret = BrotliDecoderDecompressStream((*strm)->brdec_state, &available_in, &next_in, + &available_out, &next_out, 0); + + size_t have = CHUNK - available_out; + if (have > 0){ + totalsize += have; + *dest = (char *)realloc(*dest,totalsize); + memcpy(*dest + totalsize - have, out, have); + *outlen = have; + } + + if (ret == BROTLI_DECODER_RESULT_SUCCESS || ret == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT){ + ret = 1; + goto finish; + } + + if (ret == BROTLI_DECODER_RESULT_ERROR){ + ret = -1; + goto finish; + } + assert(ret == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT); + } +finish: + return ret; +} + +int inflate_gzip_read(struct z_stream_st **strm, char **dest, int *outlen) +{ + #define CHUNK (1024 * 1024 * 4) + int ret = -1; + unsigned have; + unsigned char out[CHUNK]; + int totalsize = 0; + + /* run inflate() on input until output buffer not full */ + do { + (*strm)->zst.avail_out = CHUNK; + (*strm)->zst.next_out = out; + ret = inflate(&((*strm)->zst), Z_NO_FLUSH); + assert(ret != Z_STREAM_ERROR); /* state not clobbered */ + switch (ret) { + case Z_NEED_DICT: + ret = Z_DATA_ERROR; /* and fall through */ + case Z_DATA_ERROR: + case Z_MEM_ERROR: + inflateEnd(&((*strm)->zst)); + return ret; + } + have = CHUNK - (*strm)->zst.avail_out; + totalsize += have; + *dest = (char *)realloc(*dest,totalsize); + memcpy(*dest + totalsize - have,out,have); + *outlen = have; + } while ((*strm)->zst.avail_out == 0); + + return ret; +} + +int inflate_read(const uint8_t *source,int len,char **dest, int *outlen, + struct z_stream_st **strm, int encode) +{ + int ret = -1; + + ret = inflate_init(strm, encode); + if (ret != Z_OK){ + return ret; + } + + if (encode == HTTP2_CONTENT_ENCODING_GZIP || + encode == HTTP2_CONTENT_ENCODING_DEFLATE){ + (*strm)->zst.avail_in = len; + (*strm)->zst.next_in = (Bytef *)source; + ret = inflate_gzip_read(strm, dest, outlen); + } + if (encode == HTTP2_CONTENT_ENCODING_BR){ + ret = inflate_br_read(strm, source, len, dest, outlen); + } + return ret; +} + +int deflate_init(struct z_stream_st **strm, int gzip) +{ + if (*strm != NULL) + return Z_OK; + + int ret = 0; + + *strm = ALLOC(struct z_stream_st, 1); + assert(*strm); + + if (gzip == HTTP2_CONTENT_ENCODING_GZIP || + gzip == HTTP2_CONTENT_ENCODING_DEFLATE){ + (*strm)->zst.zalloc = (alloc_func)0; + (*strm)->zst.zfree = (free_func)0; + (*strm)->zst.opaque = (voidpf)0; + (*strm)->zst.avail_in = 0; + (*strm)->zst.next_in = Z_NULL; + + int wbits = 0; + if (gzip == HTTP2_CONTENT_ENCODING_GZIP){ + wbits = MAX_WBITS + 16; + } + if (gzip == HTTP2_CONTENT_ENCODING_DEFLATE){ + wbits = -MAX_WBITS; + } + ret = deflateInit2(&((*strm)->zst), Z_DEFAULT_COMPRESSION, + Z_DEFLATED, wbits, 8, Z_DEFAULT_STRATEGY); + + } + if (gzip == HTTP2_CONTENT_ENCODING_BR){ + (*strm)->brenc_state = BrotliEncoderCreateInstance(NULL, NULL, NULL); + if ( (*strm)->brenc_state == NULL) + ret = -1; + } + if (ret != Z_OK) + FREE(strm); + + return ret; +} + +int defalta_br_write(struct z_stream_st **strm, + const unsigned char * source, size_t slen, + struct evbuffer * evbuf, int end) +{ + struct evbuffer_iovec v[1]; + + size_t __sz_reserve_chunk = slen > 8192 ? slen : 8192; + int iov_count = evbuffer_reserve_space(evbuf, __sz_reserve_chunk, v, 1); + if (iov_count != 1) return -1; + + const unsigned char * next_in = source; + size_t avail_in = slen; + + unsigned char * next_out = (unsigned char *)v[0].iov_base; + size_t avail_out = v[0].iov_len; + + enum BrotliEncoderOperation op = end ? BROTLI_OPERATION_FINISH : BROTLI_OPERATION_PROCESS; + int ret = 0; + do + { + ret = BrotliEncoderCompressStream((*strm)->brenc_state, op, + &avail_in, &next_in, &avail_out, &next_out, NULL); + + if(unlikely(ret == BROTLI_FALSE)){ + return ret; + } + + if (avail_out == 0 || avail_in == 0) + { + v[0].iov_len = v[0].iov_len - avail_out; + ret = evbuffer_commit_space(evbuf, v, iov_count); + if(ret < 0) + return -2; + + if(avail_out == 0){ + iov_count = evbuffer_reserve_space(evbuf, __sz_reserve_chunk, v, 1); + if(unlikely(iov_count != 1)) + return -3; + + next_out = (unsigned char *) v[0].iov_base; + avail_out = (unsigned int) v[0].iov_len; + } + } + } + while (avail_in > 0); + return 0; + +} + +int defalta_gzip_write(struct z_stream_st **strm, const uint8_t *source, int slen, + struct evbuffer * evbuf, int end) +{ +#define SZ_IOVEC 2 + int ret = 0; + unsigned int i = 0; + struct evbuffer_iovec io[SZ_IOVEC]; + + size_t max = slen > 8192 ? slen : 8192; + int iov_count = evbuffer_reserve_space(evbuf, max, io, SZ_IOVEC); + if (iov_count < 1 || iov_count > SZ_IOVEC) + return -1; + + (*strm)->zst.next_in = (unsigned char *) source; + (*strm)->zst.avail_in = (unsigned int) slen; + (*strm)->zst.next_out = (unsigned char *) io[i].iov_base; + (*strm)->zst.avail_out = (unsigned int) io[i].iov_len; + + int flush = end ? Z_FINISH : Z_NO_FLUSH; + do + { + ret = deflate(&((*strm)->zst), flush); + assert(ret != Z_STREAM_ERROR); + assert(i < SZ_IOVEC); + + if ((*strm)->zst.avail_out == 0 || (*strm)->zst.avail_in == 0) + { + unsigned int len = (unsigned int) io[i].iov_len - (*strm)->zst.avail_out; + io[i].iov_len = (size_t) len; + + i++; + (*strm)->zst.next_out = (unsigned char *) io[i].iov_base; + (*strm)->zst.avail_out = (unsigned int) io[i].iov_len; + } + } while ((*strm)->zst.avail_in > 0); + + assert(end == 0 || ret == Z_STREAM_END); + + (void)ret; + return evbuffer_commit_space(evbuf, io, iov_count); +} + +int deflate_write(struct z_stream_st **strm, const uint8_t *source, + int slen, struct evbuffer * evbuf, int gzip, int end) +{ + int ret = 0; + + ret = deflate_init(strm, gzip); + if (ret != Z_OK){ + return ret; + } + + if (gzip == HTTP2_CONTENT_ENCODING_GZIP || + gzip == HTTP2_CONTENT_ENCODING_DEFLATE){ + ret = defalta_gzip_write(strm, source, slen, evbuf, end); + } + if (gzip == HTTP2_CONTENT_ENCODING_BR){ + ret = defalta_br_write(strm, source, slen, evbuf, end); + } + + return ret; +} + +void inflate_finished(struct z_stream_st **strm) +{ + if (*strm != NULL){ + if ((*strm)->brdec_state){ + BrotliDecoderDestroyInstance((*strm)->brdec_state); + (*strm)->brdec_state = NULL; + return; + } + (void)inflateEnd(&((*strm)->zst)); + free(*strm); + *strm = NULL; + } +} +void deflate_finished(struct z_stream_st **strm) +{ + if (*strm != NULL){ + (void) deflateEnd(&((*strm)->zst)); + free(*strm); + *strm = NULL; + } +} + +void frame_display(const uint8_t *payload, uint16_t payload_len) +{ + int i = 0; + + printf("context:(%d)\n", payload_len); + for(i=0; i < (int)payload_len; ++i){ + printf(" 0x%02x,", payload[i]); + if( (i + 1) % 16 == 0) + printf("\n"); + if ( i > 500) + break; + } + printf("\n\n"); +} + + |
