1 /*
2 * Copyright (c) 2023 - 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "lnn_compress.h"
17
18 #include <securec.h>
19 #include <zlib.h>
20
21 #include "softbus_adapter_file.h"
22 #include "softbus_errcode.h"
23 #include "softbus_feature_config.h"
24 #include "softbus_adapter_mem.h"
25 #include "lnn_log.h"
26
27 #define CHUNK 4096
28 #define GZIP_ENCODING 16
29 #define MAX_WBITS 15
30 #define Z_MEM_LEVEL 8
31
32 /* compress data by GZIP */
DataCompress(uint8_t * in,uint32_t inLen,uint8_t ** out,uint32_t * outLen)33 int32_t DataCompress(uint8_t *in, uint32_t inLen, uint8_t **out, uint32_t *outLen)
34 {
35 if ((in == NULL) || (inLen == 0) || (out == NULL) || (outLen == NULL)) {
36 LNN_LOGE(LNN_STATE, "param invalid");
37 return SOFTBUS_INVALID_PARAM;
38 }
39 z_stream strm;
40 int32_t ret = SOFTBUS_OK;
41 uint32_t tmpLen = compressBound(inLen);
42 *out = SoftBusCalloc(tmpLen);
43 if (*out == NULL) {
44 LNN_LOGE(LNN_STATE, "malloc fail.");
45 return SOFTBUS_MALLOC_ERR;
46 }
47
48 strm.zalloc = Z_NULL;
49 strm.zfree = Z_NULL;
50 strm.opaque = Z_NULL;
51 ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, MAX_WBITS | GZIP_ENCODING, Z_MEM_LEVEL,
52 Z_DEFAULT_STRATEGY);
53 if (ret != Z_OK) {
54 SoftBusFree(*out);
55 *out = NULL;
56 LNN_LOGE(LNN_STATE, "deflateInit2 fail, ret=%{public}d", ret);
57 return SOFTBUS_ERR;
58 }
59
60 strm.avail_in = inLen;
61 strm.next_in = in;
62 strm.avail_out = tmpLen;
63 strm.next_out = *out;
64 ret = deflate(&strm, Z_FINISH);
65 if (ret != Z_STREAM_END) {
66 deflateEnd(&strm);
67 SoftBusFree(*out);
68 *out = NULL;
69 LNN_LOGE(LNN_STATE, "deflate fail, ret=%{public}d", ret);
70 return SOFTBUS_ERR;
71 }
72 *outLen = strm.total_out;
73 deflateEnd(&strm);
74 return SOFTBUS_OK;
75 }
76
PerformInflate(z_stream * strm,uint8_t * in,uint32_t inLen,uint8_t ** out,uint32_t * outLen)77 static int32_t PerformInflate(z_stream *strm, uint8_t *in, uint32_t inLen, uint8_t **out, uint32_t *outLen)
78 {
79 int32_t ret = SOFTBUS_OK;
80 uint32_t chunk = CHUNK;
81 uint32_t bufferSize = chunk;
82 unsigned char *buffer = SoftBusCalloc(bufferSize);
83 if (buffer == NULL) {
84 LNN_LOGE(LNN_STATE, "malloc fail.");
85 return SOFTBUS_MALLOC_ERR;
86 }
87 strm->avail_in = inLen;
88 strm->next_in = in;
89 *outLen = 0;
90 do {
91 strm->avail_out = chunk;
92 if (*outLen + chunk > bufferSize) {
93 uint32_t newBufferSize = bufferSize * 2;
94 unsigned char *newBuffer = SoftBusCalloc(newBufferSize);
95 if (newBuffer == NULL) {
96 LNN_LOGE(LNN_STATE, "malloc fail.");
97 SoftBusFree(buffer);
98 return SOFTBUS_MALLOC_ERR;
99 }
100 if (memcpy_s(newBuffer, newBufferSize, buffer, *outLen) != EOK) {
101 LNN_LOGE(LNN_STATE, "memcpy fail.");
102 SoftBusFree(buffer);
103 SoftBusFree(newBuffer);
104 return SOFTBUS_MEM_ERR;
105 }
106 SoftBusFree(buffer);
107 buffer = newBuffer;
108 bufferSize = newBufferSize;
109 }
110 strm->next_out = buffer + *outLen;
111 ret = inflate(strm, Z_NO_FLUSH);
112 if (ret != Z_OK && ret != Z_STREAM_END) {
113 SoftBusFree(buffer);
114 LNN_LOGE(LNN_STATE, "inflate fail, ret=%{public}d", ret);
115 return SOFTBUS_ERR;
116 }
117 *outLen += chunk - strm->avail_out;
118 } while (strm->avail_out == 0);
119 if (ret != Z_STREAM_END) {
120 SoftBusFree(buffer);
121 LNN_LOGE(LNN_STATE, "performInflate fail, ret=%{public}d", ret);
122 return SOFTBUS_ERR;
123 }
124 *out = buffer;
125 return SOFTBUS_OK;
126 }
127
128 /* decompress data by GZIP */
DataDecompress(uint8_t * in,uint32_t inLen,uint8_t ** out,uint32_t * outLen)129 int32_t DataDecompress(uint8_t *in, uint32_t inLen, uint8_t **out, uint32_t *outLen)
130 {
131 if ((in == NULL) || (inLen == 0) || (out == NULL) || (outLen == NULL)) {
132 LNN_LOGE(LNN_STATE, "param invalid");
133 return SOFTBUS_INVALID_PARAM;
134 }
135 z_stream strm;
136 strm.zalloc = Z_NULL;
137 strm.zfree = Z_NULL;
138 strm.opaque = Z_NULL;
139 strm.avail_in = 0;
140 strm.next_in = Z_NULL;
141 int32_t ret = inflateInit2(&strm, MAX_WBITS | GZIP_ENCODING);
142 if (ret != Z_OK) {
143 LNN_LOGE(LNN_STATE, "inflateInit2 fail, ret=%{public}d", ret);
144 return SOFTBUS_ERR;
145 }
146 ret = PerformInflate(&strm, in, inLen, out, outLen);
147 if (ret != SOFTBUS_OK) {
148 LNN_LOGE(LNN_STATE, "performInflate fail, ret=%{public}d", ret);
149 }
150 inflateEnd(&strm);
151 return ret;
152 }