Skip to content
This repository was archived by the owner on Apr 22, 2019. It is now read-only.

Commit 0eaa1b5

Browse files
author
OlehKulykov
committed
Receive gzip and deflate encoded responce
1 parent eb77b76 commit 0eaa1b5

File tree

15 files changed

+205
-63
lines changed

15 files changed

+205
-63
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ set(CPACK_PACKAGE_VERSION_MINOR "3")
3333
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}")
3434
set(CPACK_PACKAGE_VENDOR "[email protected]")
3535
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PACKAGE} ${PACKAGE_VERSION}")
36-
set(SOVERSION "0.3.2")
36+
set(SOVERSION "0.3.3")
3737
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
3838
set(VERSION "${CPACK_PACKAGE_VERSION}")
3939

appveyor.yml

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version: 0.3.2.{build}
1+
version: 0.3.3.{build}
22

33

44
os: Visual Studio 2015
@@ -110,14 +110,14 @@ artifacts:
110110
- path: '*.7z'
111111

112112

113-
#deploy:
114-
# - provider: GitHub
115-
# release: $(appveyor_build_version)
116-
# description: 'Appveyor CI build artifacts. Compressed install path with binaries, libraries and configured headers'
117-
# auth_token:
118-
# secure: 9fCOXiEygRERkV9JN67Rqq6WFwdbSBIllYdZGYcSoFPj1oUAxk3aRi+bWv04l7M5
119-
# artifact: /.*\.7z/
120-
# draft: false
121-
# prerelease: true
122-
# on:
123-
# branch: master
113+
deploy:
114+
- provider: GitHub
115+
release: $(appveyor_build_version)
116+
description: 'Appveyor CI build artifacts. Compressed install path with binaries, libraries and configured headers'
117+
auth_token:
118+
secure: 9fCOXiEygRERkV9JN67Rqq6WFwdbSBIllYdZGYcSoFPj1oUAxk3aRi+bWv04l7M5
119+
artifact: /.*\.7z/
120+
draft: false
121+
prerelease: true
122+
on:
123+
branch: master

libnhr.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131
#define NHR_VERSION_MAJOR 0
3232
#define NHR_VERSION_MINOR 3
33-
#define NHR_VERSION_PATCH 2
33+
#define NHR_VERSION_PATCH 3
3434

3535

3636
// check windows
@@ -216,6 +216,14 @@ NHR_EXTERN const char * k_nhr_content_encoding;
216216
NHR_EXTERN const char * k_nhr_gzip_deflate;
217217

218218

219+
/// String constant "gzip"
220+
NHR_EXTERN const char * k_nhr_gzip;
221+
222+
223+
/// String constant "deflate"
224+
NHR_EXTERN const char * k_nhr_deflate;
225+
226+
219227
// request
220228

221229
/**

src/nhr_common.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ const char * k_nhr_application_x_www_form_urlencoded = "application/x-www-form-u
2929
const char * k_nhr_transfer_encoding = "Transfer-Encoding";
3030
const char * k_nhr_content_encoding = "Content-Encoding";
3131
const char * k_nhr_gzip_deflate = "gzip, deflate";
32+
const char * k_nhr_gzip = "gzip";
33+
const char * k_nhr_deflate = "deflate";
3234
const char * k_nhr_CRLF = "\r\n";
3335
const char * k_nhr_double_CRLF = "\r\n\r\n";
3436
const char * k_nhr_content_length = "Content-Length";

src/nhr_common.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,5 +100,8 @@ NHR_EXTERN const char * k_nhr_content_length; // "Content-Length";
100100
NHR_EXTERN const char * k_nhr_chunked; // "chunked"
101101
#define k_nhr_chunked_length 7
102102

103+
#define k_nhr_gzip_length 4
104+
#define k_nhr_deflate_length 7
105+
103106
#endif
104107

src/nhr_gz.c

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -83,18 +83,30 @@ void * nhr_gz_write_footer(void * buff,
8383
void * nhr_gz_compress(const void * buff,
8484
const size_t buff_size,
8585
size_t * compressed_size,
86-
const unsigned char have_header) {
86+
const unsigned char method) {
8787
if (!buff || buff_size == 0) return NULL;
8888

8989
z_stream zip;
9090
void * out_buff = NULL;
9191
size_t writed = 0, out_size = NHR_GZ_CHUNK_SIZE;
9292

9393
memset(&zip, 0, sizeof(z_stream));
94-
int result = deflateInit2(&zip, Z_BEST_COMPRESSION, Z_DEFLATED, NHR_GZ_WINDOWS_BITS, 8, Z_DEFAULT_STRATEGY);
94+
95+
int result = Z_ERRNO;
96+
switch (method) {
97+
case NHR_GZ_METHOD_GZIP:
98+
result = deflateInit2(&zip, Z_BEST_COMPRESSION, Z_DEFLATED, NHR_GZ_WINDOWS_BITS, 8, Z_DEFAULT_STRATEGY);
99+
break;
100+
case NHR_GZ_METHOD_DEFLATE:
101+
result = deflateInit(&zip, Z_BEST_COMPRESSION);
102+
break;
103+
default:
104+
break;
105+
}
106+
95107
if (result != Z_OK) return NULL;
96108

97-
if (have_header) {
109+
if (method == NHR_GZ_METHOD_GZIP) {
98110
out_size += NHR_GZ_HEADER_SIZE;
99111
out_buff = nhr_malloc(out_size);
100112
nhr_gz_write_header(out_buff);
@@ -140,7 +152,7 @@ void * nhr_gz_compress(const void * buff,
140152
}
141153

142154
writed = zip.total_out; // write total from zip stream
143-
if (have_header) {
155+
if (method == NHR_GZ_METHOD_GZIP) {
144156
writed += NHR_GZ_HEADER_SIZE;
145157
out_buff = nhr_gz_write_footer(out_buff, out_size, writed, buff, buff_size);
146158
writed += NHR_GZ_FOOTER_SIZE;
@@ -152,28 +164,50 @@ void * nhr_gz_compress(const void * buff,
152164
return out_buff;
153165
}
154166

167+
int nhr_gz_is_gzip_file(const unsigned char * buff, const size_t buff_size) {
168+
if (buff_size <= NHR_GZ_HEADER_SIZE + NHR_GZ_FOOTER_SIZE) return 0;
169+
return buff[0] == 0x1f && buff[1] == 0x8b;
170+
}
171+
155172
void * nhr_gz_decompress(const void * buff,
156173
const size_t buff_size,
157174
size_t * decompressed_size,
158-
const unsigned char have_header) {
175+
const unsigned char method) {
159176
//TODO: process gz header
160177
if (!buff || buff_size == 0) return NULL;
161178

162179
z_stream zip;
163180
memset(&zip, 0, sizeof(z_stream));
164-
void * out_buff = nhr_malloc(NHR_GZ_CHUNK_SIZE);
181+
void * out_buff = NULL;
165182
size_t out_size = NHR_GZ_CHUNK_SIZE;
166183
size_t writed = 0;
184+
167185
int available_size = 0;
168186

169-
int result = inflateInit2(&zip, NHR_GZ_WINDOWS_BITS);
170-
if (result != Z_OK) {
171-
nhr_free(out_buff);
172-
return NULL;
187+
// The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by the caller.
188+
189+
int result = Z_ERRNO;
190+
switch (method) {
191+
case NHR_GZ_METHOD_GZIP:
192+
if (nhr_gz_is_gzip_file(buff, buff_size)) {
193+
zip.avail_in = (uInt)buff_size - NHR_GZ_HEADER_SIZE - NHR_GZ_FOOTER_SIZE;
194+
zip.next_in = (Bytef *)buff + NHR_GZ_HEADER_SIZE;
195+
result = inflateInit2(&zip, NHR_GZ_WINDOWS_BITS);
196+
}
197+
break;
198+
case NHR_GZ_METHOD_DEFLATE:
199+
zip.avail_in = (uInt)buff_size;
200+
zip.next_in = (Bytef *)buff;
201+
result = inflateInit(&zip);
202+
break;
203+
default:
204+
break;
173205
}
174206

175-
zip.avail_in = (uInt)buff_size;
176-
zip.next_in = (Bytef *)buff;
207+
if (result != Z_OK) return NULL;
208+
209+
out_buff = nhr_malloc(NHR_GZ_CHUNK_SIZE);
210+
177211
zip.avail_out = NHR_GZ_CHUNK_SIZE;
178212

179213
do {

src/nhr_gz.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,20 @@
2828

2929
#if defined(NHR_GZIP)
3030

31+
// raw deflate
32+
33+
#define NHR_GZ_METHOD_DEFLATE 0
34+
#define NHR_GZ_METHOD_GZIP 1
35+
3136
void * nhr_gz_compress(const void * buff,
3237
const size_t buff_size,
3338
size_t * compressed_size,
34-
const unsigned char have_header);
39+
const unsigned char method);
3540

3641
void * nhr_gz_decompress(const void * buff,
3742
const size_t buff_size,
3843
size_t * decompressed_size,
39-
const unsigned char have_header);
44+
const unsigned char method);
4045

4146
#endif
4247
#endif

src/nhr_request_private.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,10 @@ nhr_bool nhr_request_recv(_nhr_request * r) {
9595
}
9696

9797
void nhr_request_wait_raw_responce(_nhr_request * r) {
98+
nhr_bool is_finished = nhr_false;
9899
if (nhr_request_recv(r)) {
99-
if (nhr_response_is_finished(r->responce)) nhr_request_set_command(r, NHR_COMMAND_INFORM_RESPONCE);
100+
is_finished = r->responce ? r->responce->is_finished : nhr_false;
101+
if (is_finished) nhr_request_set_command(r, NHR_COMMAND_INFORM_RESPONCE);
100102
if (!nhr_request_check_timeout(r)) return; // error already exists
101103
} else if (r) {
102104
nhr_request_set_command(r, NHR_COMMAND_INFORM_RESPONCE);

src/nhr_response.c

Lines changed: 85 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,31 @@
2424
#include "nhr_response.h"
2525
#include "nhr_memory.h"
2626
#include "nhr_string.h"
27+
#include "nhr_gz.h"
2728
#include <string.h>
2829
#include <ctype.h>
2930

31+
#if defined(NHR_GZIP)
32+
void nhr_response_ungzip(_nhr_response * r) {
33+
if (!r->body || r->body_len <= 0) return;
34+
35+
void * decompressed = NULL;
36+
size_t decompressed_size = 0;
37+
if (r->content_encoding & NHR_CONTENT_ENCODING_GZIP) {
38+
decompressed = nhr_gz_decompress(r->body, r->body_len, &decompressed_size, NHR_GZ_METHOD_GZIP);
39+
} else if (r->content_encoding & NHR_CONTENT_ENCODING_DEFLATE) {
40+
decompressed = nhr_gz_decompress(r->body, r->body_len, &decompressed_size, NHR_GZ_METHOD_DEFLATE);
41+
}
42+
if (decompressed && decompressed_size > 0) {
43+
nhr_free(r->body);
44+
r->body = decompressed;
45+
r->body_len = decompressed_size;
46+
} else {
47+
nhr_free(decompressed);
48+
}
49+
}
50+
#endif
51+
3052
void nhr_response_fix_body_len(_nhr_response * r) {
3153
if (r->content_length > 0 && r->body_len > r->content_length) {
3254
// some trash was copyed, ignore it.
@@ -64,7 +86,12 @@ void nhr_response_read_chunks(_nhr_response * r, char * str) {
6486
#endif
6587

6688
void nhr_response_parse_body(_nhr_response * r, char * received, const size_t received_len) {
67-
// printf("\n------HEADER---------\n%s\n---------------------\n", received);
89+
#if defined(NHR_DEBUG_LOG)
90+
size_t log_index = 0;
91+
printf("\n----[ RESPONCE HEADER ]----\n");
92+
for (log_index = 0; log_index < received_len; log_index++) printf("%c", received[log_index]);
93+
printf("\n---------------------------\n");
94+
#endif
6895
char * sub = strstr(received, k_nhr_double_CRLF);
6996
if (!sub) return;
7097

@@ -73,7 +100,7 @@ void nhr_response_parse_body(_nhr_response * r, char * received, const size_t re
73100
sub += k_nhr_double_CRLF_length;
74101
skiped -= k_nhr_double_CRLF_length;
75102

76-
if (r->transfer_encoding == NHR_TRANSFER_ENCODING_CHUNKED) {
103+
if (r->transfer_encoding & NHR_TRANSFER_ENCODING_CHUNKED) {
77104
#if !defined(NHR_NO_CHUNKED)
78105
nhr_response_read_chunks(r, sub);
79106
#endif
@@ -103,30 +130,74 @@ void nhr_response_parse_content_length(_nhr_response * r, char * received) {
103130
if (nhr_sscanf(value, "%lu", &length) == 1 && length > 0) r->content_length = (size_t)length;
104131
}
105132

133+
void nhr_response_log_unprocessed(const char * key, const char * value) {
134+
printf("\nWARNING: libnhr unprocessed \"%s\" : \"%s\".", key, value);
135+
}
136+
106137
void nhr_response_parse_transfer_encoding(_nhr_response * r, char * received) {
107-
char * sub = nhr_response_find_http_field_value(received, k_nhr_transfer_encoding);
108-
if (!sub) return;
138+
char * encoding = nhr_response_find_http_field_value(received, k_nhr_transfer_encoding);
139+
if (!encoding) return;
109140

110-
if (strncmp(sub, k_nhr_chunked, k_nhr_chunked_length) == 0) {
141+
if (strstr(encoding, k_nhr_chunked)) {
111142
#if defined(NHR_NO_CHUNKED)
112-
printf("WARNING: libnhr unprocessed chucked encoding.\n");
143+
nhr_response_log_unprocessed(k_nhr_transfer_encoding, encoding);
113144
#else
114-
r->transfer_encoding = NHR_TRANSFER_ENCODING_CHUNKED;
145+
r->transfer_encoding |= NHR_TRANSFER_ENCODING_CHUNKED;
115146
#endif
116147
}
117148
}
118149

150+
void nhr_response_parse_content_encoding(_nhr_response * r, char * received) {
151+
char * encoding = nhr_response_find_http_field_value(received, k_nhr_content_encoding);
152+
if (!encoding) return;
153+
154+
if (strstr(encoding, k_nhr_gzip)) {
155+
#if defined(NHR_GZIP)
156+
r->content_encoding |= NHR_CONTENT_ENCODING_GZIP;
157+
#else
158+
nhr_response_log_unprocessed(k_nhr_transfer_encoding, encoding);
159+
#endif
160+
}
161+
if (strstr(encoding, k_nhr_deflate)) {
162+
#if defined(NHR_GZIP)
163+
r->content_encoding |= NHR_CONTENT_ENCODING_DEFLATE;
164+
#else
165+
nhr_response_log_unprocessed(k_nhr_transfer_encoding, encoding);
166+
#endif
167+
}
168+
}
169+
170+
nhr_bool nhr_response_is_finished_receiving(_nhr_response * r) {
171+
#if !defined(NHR_NO_CHUNKED)
172+
if (r->transfer_encoding & NHR_TRANSFER_ENCODING_CHUNKED) return r->is_all_chunks_processed;
173+
#endif
174+
return (r->content_length > 0) ? r->content_length == r->body_len : nhr_false;
175+
}
176+
177+
void nhr_response_check_is_finished(_nhr_response * r) {
178+
if (!nhr_response_is_finished_receiving(r)) return;
179+
180+
if (r->content_encoding & NHR_CONTENT_ENCODING_GZIP ||
181+
r->content_encoding & NHR_CONTENT_ENCODING_DEFLATE) {
182+
#if defined(NHR_GZIP)
183+
nhr_response_ungzip(r);
184+
#endif
185+
}
186+
r->is_finished = nhr_true;
187+
}
188+
119189
_nhr_response * nhr_response_create(void * received, const size_t received_len) {
120190
_nhr_response * r = (_nhr_response *)nhr_malloc_zero(sizeof(struct _nhr_response_struct));
121191

122-
nhr_response_parse_status_code(r, (char *)received);
192+
nhr_response_parse_status_code(r, received);
123193

124194
if (r->status_code == 200) {
125-
nhr_response_parse_content_length(r, (char *)received);
126-
nhr_response_parse_transfer_encoding(r, (char *)received);
127-
nhr_response_parse_body(r, (char *)received, received_len);
195+
nhr_response_parse_content_length(r, received);
196+
nhr_response_parse_transfer_encoding(r, received);
197+
nhr_response_parse_content_encoding(r, received);
198+
nhr_response_parse_body(r, received, received_len);
128199
}
129-
200+
nhr_response_check_is_finished(r);
130201
return r;
131202
}
132203

@@ -149,13 +220,14 @@ void nhr_response_add_body_data(_nhr_response * r, void * data, const size_t dat
149220
}
150221

151222
void nhr_response_append(_nhr_response * r, void * received, const size_t received_len) {
152-
if (r->transfer_encoding == NHR_TRANSFER_ENCODING_CHUNKED) {
223+
if (r->transfer_encoding & NHR_TRANSFER_ENCODING_CHUNKED) {
153224
#if !defined(NHR_NO_CHUNKED)
154225
nhr_response_read_chunks(r, (char *)received);
155226
#endif
156227
} else {
157228
nhr_response_add_body_data(r, received, received_len);
158229
}
230+
nhr_response_check_is_finished(r);
159231
}
160232

161233
void nhr_response_delete(_nhr_response * r) {
@@ -180,15 +252,3 @@ unsigned int nhr_response_get_body_length(nhr_response responce) {
180252
_nhr_response * r = (_nhr_response *)responce;
181253
return r ? (unsigned int)r->body_len : 0;
182254
}
183-
184-
nhr_bool nhr_response_is_finished(_nhr_response * r) {
185-
if (!r) return nhr_false;
186-
187-
#if !defined(NHR_NO_CHUNKED)
188-
if (r->transfer_encoding == NHR_TRANSFER_ENCODING_CHUNKED) {
189-
return r->is_all_chunks_processed;
190-
}
191-
#endif
192-
193-
return (r->content_length > 0) ? r->content_length == r->body_len : nhr_false;
194-
}

0 commit comments

Comments
 (0)