summaryrefslogtreecommitdiff
path: root/plugin/protocol/http2/src/http2_common.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_common.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_common.cpp')
-rw-r--r--plugin/protocol/http2/src/http2_common.cpp409
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");
+}
+
+