• 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧

关于HTTP2.0 gzip和br解压缩

互联网 diligentman 1周前 (11-18) 8次浏览

关于gzip格式解码
使用zlib库解压GZIP格式数据,相关函数inflateInit2(),inflate(),inflateEnd().
zlib库安装这个比较简单不做过多描述
代码示例
直接加入#include <zlib.h>

static int vidpeek_uncompressGzip(unsigned char* pSrc, unsigned int srcSize,char*pOutDest, unsigned int* pOutBufSize)
{

    int ret = OK;
    char* pBuf = pSrc+ (srcSize - 1);
    unsigned int len =1000000;
    int uncompressResult;   
    z_stream d_stream;  
    int i = 0;
 
    printf("#############pSrc 0x%x 0x%x 0x%x 0x%x %d", pSrc[0], pSrc[1],*pSrc, *(pSrc+1),srcSize);
    if((*pSrc !=0x1f)||(*(pSrc+1) != 0x8b))
    {
        printf("nuncompressGzip non Gzipn");
        return ERR;
    }
 
	//初始化解压系统
    d_stream.zalloc =Z_NULL;
    d_stream.zfree =Z_NULL;
    d_stream.opaque = Z_NULL;
    d_stream.next_in =Z_NULL;
    d_stream.avail_in= 0;
    uncompressResult =inflateInit2(&d_stream,47);
    if(uncompressResult!=Z_OK)
    {
        printf("ninflateInit2 error:%dn",uncompressResult);
        return uncompressResult;
    }
 
    d_stream.next_in=pSrc;
    d_stream.avail_in=srcSize;
    d_stream.next_out=(char *)pOutDest;
    d_stream.avail_out=len;
    uncompressResult =inflate(&d_stream,Z_NO_FLUSH);
 
    switch(uncompressResult)
    {
        case Z_NEED_DICT:
            uncompressResult = Z_DATA_ERROR;
        case Z_DATA_ERROR:
        case Z_MEM_ERROR:
            (void)inflateEnd(&d_stream);
            return uncompressResult;		
    }
 
    printf("outlen= %d, total_in= %d, total_out= %d, avail_out= %d@@@@@@@@@@@n",len, d_stream.total_in, d_stream.total_out, d_stream.avail_out);           
 
    inflateEnd(&d_stream);	
	#if 0
	for (i = 0; i < 1000000; i++ )
	{
		printf("%c",*(pOutDest+i));	
	}
	#endif
	*pOutBufSize = strlen(pOutDest);
    return ret;
}

关于br解压缩
使用brotli库解压br,相关函数BrotliDecoderDecompress();(brotli-1.0.9cincludebrotlidecode.h)
如果需要解压所的数据比较完整 直接调用上面函数即可。

但是br数据解压 后面数据的解压依赖前面数据 故将BrotliDecoderDecompress()改造加入到decode.c .h 中 ,重新生成动态库调用即可。

BrotliDecoderResult BrotliDecoderDecompress_new(
	size_t encoded_size, const uint8_t* encoded_buffer, size_t* decoded_size,
	uint8_t* decoded_buffer, void **ctx) {

	
  BrotliDecoderState *s;
  if(!(*ctx))
  {
	  s = BrotliDecoderCreateInstance(NULL, NULL, NULL);
  }
  BrotliDecoderResult result;
  size_t total_out = 0;
  size_t available_in = encoded_size;
  const uint8_t* next_in = encoded_buffer;
  size_t available_out = *decoded_size;
  uint8_t* next_out = decoded_buffer;
  if(!(*ctx))
  {
	  if (!BrotliDecoderStateInit(s, 0, 0, 0)) {
		return BROTLI_DECODER_RESULT_ERROR;
	  }
	*ctx = s; 
  }
  else
  {
	s = *ctx;
  }

  result = BrotliDecoderDecompressStream(
	  s, &available_in, &next_in, &available_out, &next_out, &total_out);
  *decoded_size = total_out;
  
  // 判断是否解完
  if(BrotliDecoderIsFinished(s))
  {
	  BrotliDecoderStateCleanup(s);
	  // 销毁
	  BrotliDecoderDestroyInstance(s);
  }
  if (result != BROTLI_DECODER_RESULT_SUCCESS) {
	result = BROTLI_DECODER_RESULT_ERROR;
  }
  return result;
}

测试结果:

#include <stdio.h>
/* For "exit". */
#include <stdlib.h>
/* For "strerror". */
#include <string.h>
#include <decode.h>

//数据太大 不贴了  
static unsigned char in[]={};
static unsigned char in1[]={};
static unsigned char in2[]={};
static unsigned char out[100000]={0};
static unsigned char out1[100000]={0};
static unsigned char out2[100000]={0};
static unsigned char out3[100000]={0};

int main()
{
    int psize=0; 
	void *ctx=NULL;
	int ret=BrotliDecoderDecompress_new(sizeof(in),&in,&psize,&out, &ctx);
	printf("strlen =%d,ret=%dn",psize,ret);	
	printf("%sn",out);

	int ret1=BrotliDecoderDecompress_new(sizeof(in1),&in1,&psize,&out1, &ctx);
	printf("strlen =%d,ret=%dn",psize,ret1);	
	printf("%sn",out1);	
	int ret2=BrotliDecoderDecompress_new(sizeof(in2),&in2,&psize,&out2, &ctx);
	printf("strlen =%d,ret=%dn",psize,ret2);	
	printf("%sn",out2);
	int ret3=BrotliDecoderDecompress_new(sizeof(in3),&in3,&psize,&out3, &ctx);
	printf("strlen =%d,ret=%dn",psize,ret3);	
	printf("%sn",out3);
    return 0;
}

gcc unbr.c -I. -L. -lbrotlidec


喜欢 (0)