关于HTTP2.0 gzip和br解压缩

关于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 Gzip\n");
        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:%d\n",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;
}

下面代码是处理gzip分片的数据

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

    int ret = OK;
    char* pBuf = pSrc+ (srcSize - 1);
    unsigned int len =1000000;
    int uncompressResult;   

	z_stream* d_stream=NULL;  
    int i = 0;

	if(!(*ctx))
	{
		d_stream=(z_stream*)malloc(sizeof(z_stream));
		//初始化解压系统
		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:%d\n",uncompressResult);
			return uncompressResult;
		}
	  *ctx = d_stream; 
	}
	else
	{
	  d_stream = *ctx;
	}

    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;		
    }
	         
	*pOutBufSize = strlen(pOutDest);
    return ret;
}

关于br解压缩
https://github.com/google/brotli 上下载,下面有编译方法
使用brotli库解压br,相关函数BrotliDecoderDecompress();(brotli-1.0.9\c\include\brotli\decode.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, size_t* total_out) {

	
  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, decoded_size, &next_out, total_out);
  //*decoded_size = total_out;
  
  // 判断是否解完
  if(BrotliDecoderIsFinished(s))
  {
	  BrotliDecoderStateCleanup(s);
	  // 销毁
	  BrotliDecoderDestroyInstance(s);
	  *ctx = NULL;
  }
  if (result != BROTLI_DECODER_RESULT_SUCCESS && result != BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT  ) {
	result = BROTLI_DECODER_RESULT_ERROR;
	BrotliDecoderStateCleanup(s);
	// 销毁
	BrotliDecoderDestroyInstance(s);
	*ctx = NULL;
  }
  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()
{
    size_t psize=100000; 
	size_t total_out = 0;
	void *ctx=NULL;
	printf("-------len : %d\n", sizeof(in));
	int ret=BrotliDecoderDecompress_new(500,in,&psize,&out, &ctx,&total_out);
	printf("strlen =%d,ret=%d total_out: %d\n", psize,ret, total_out);
	printf("strlen=%d\n",strlen(out));
	//printf("strlen=%s\n",out);
	
	ret=BrotliDecoderDecompress_new(sizeof(in)-500,in+500,&psize,&out, &ctx,&total_out);
	printf("strlen =%d,ret=%d total_out: %d\n", psize,ret, total_out);
	printf("strlen=%d\n",strlen(out));
	//printf("strlen=%s\n",out);
	psize=100000; 
	int ret1=BrotliDecoderDecompress_new(sizeof(in1),in1,&psize,&out1, &ctx,&total_out);
printf("strlen =%d,ret=%d total_out: %d\n",psize,ret, total_out);
	printf("strlen=%d\n",strlen(out1));
	printf("strlen=%s\n",out1);
	
	psize=100000; 
	int ret2=BrotliDecoderDecompress_new(sizeof(in2),in2,&psize,&out2, &ctx,&total_out);
	printf("strlen =%d,ret=%d total_out: %d\n",psize,ret, total_out);
	printf("strlen=%d\n",strlen(out2));
	printf("strlen=%s\n",out2);
	
	psize=100000; 
	int ret3=BrotliDecoderDecompress_new(sizeof(in3),in3,&psize,&out3, &ctx,&total_out);
	printf("strlen =%d,ret=%d total_out: %d\n",psize,ret, total_out);	
	printf("strlen=%d\n",strlen(out3));
	printf("strlen=%s\n",out3);


    return 0;
}

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

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值