/************************************************************************* > File Name: http2_common.cpp > Author: > Mail: > Created Time: 2018年09月21日 星期五 13时59分03秒 ************************************************************************/ #include #include #include #include #include #include #include #include #include RTLogInit2Data logging_sc_lid = { .run_log_level = 1, }; RTLogInit2Data *logger() { return &logging_sc_lid; }; Http2Plugin g_http2_plugin = { }; Http2Plugin *http2_plugin() { return &g_http2_plugin; } int http2_header_str_to_val(const char *str, size_t slen, const char * map[], unsigned int map_size) { size_t normlen = 0; for (unsigned int i = 2; i < map_size; i++) { normlen = strlen(map[i]); if ( (slen == normlen) && !strncasecmp(str, map[i], normlen)) { return i; } } // in http [TFE_HTTP_UNKNOWN_FIELD] = NULL; [TFE_HTTP_HOST] = "Host", // in http2 [TFE_HTTP_UNKNOWN_FIELD] = "unknown"; [TFE_HTTP_HOST] = ":authority" normlen = strlen(":authority"); if ( (slen == normlen) && !strncasecmp(str, ":authority", normlen)) { return TFE_HTTP_HOST; } else { return TFE_HTTP_UNKNOWN_FIELD; } } const char* http2_header_val_to_str(unsigned int val, const char * map[], unsigned int map_size) { const static char * host = ":authority"; const static char * unknown = "unknown"; if (val < map_size && val != TFE_HTTP_HOST && val != TFE_HTTP_UNKNOWN_FIELD) { return map[val]; } // in http [TFE_HTTP_UNKNOWN_FIELD] = NULL; [TFE_HTTP_HOST] = "Host", // in http2 [TFE_HTTP_UNKNOWN_FIELD] = "unknown"; [TFE_HTTP_HOST] = ":authority" if (val == TFE_HTTP_HOST) { return host; } else { return unknown; } } 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 0; } 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; // Z_OK stand for 0; Z_ERRNO stand for -1. int ret = Z_ERRNO; 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; } static 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; } static 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); switch (ret) { case Z_STREAM_ERROR: ret = Z_STREAM_ERROR; 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; // 0 stand for Z_OK *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; } static int deflate_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; } static 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 = deflate_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; goto finish; } (void)inflateEnd(&((*strm)->zst)); finish: free(*strm); *strm = NULL; } } void deflate_finished(struct z_stream_st **strm) { if (*strm != NULL) { if ((*strm)->brenc_state) { BrotliEncoderDestroyInstance((*strm)->brenc_state); (*strm)->brenc_state = NULL; goto finish; } (void) deflateEnd(&((*strm)->zst)); finish: free(*strm); *strm = NULL; } }