1 /* Copyright (c) 2003, Roger Dingledine
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2021, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
9 * \brief Working with compressed data in buffers.
12 #define BUFFERS_PRIVATE
13 #include "lib/cc/compat_compiler.h"
14 #include "lib/buf/buffers.h"
15 #include "lib/compress/compress.h"
16 #include "lib/log/util_bug.h"
19 /** Helper: If PARANOIA is defined, assert that the buffer in local variable
20 * <b>buf</b> is well-formed. */
21 #define check() STMT_BEGIN buf_assert_ok(buf); STMT_END
23 #define check() STMT_NIL
24 #endif /* defined(PARANOIA) */
26 /** Compress or uncompress the <b>data_len</b> bytes in <b>data</b> using the
27 * compression state <b>state</b>, appending the result to <b>buf</b>. If
28 * <b>done</b> is true, flush the data in the state and finish the
29 * compression/uncompression. Return -1 on failure, 0 on success. */
31 buf_add_compress(buf_t
*buf
, tor_compress_state_t
*state
,
32 const char *data
, size_t data_len
,
36 size_t old_avail
, avail
;
40 int need_new_chunk
= 0;
41 if (!buf
->tail
|| ! CHUNK_REMAINING_CAPACITY(buf
->tail
)) {
42 size_t cap
= data_len
/ 4;
43 buf_add_chunk_with_capacity(buf
, cap
, 1);
45 next
= CHUNK_WRITE_PTR(buf
->tail
);
46 avail
= old_avail
= CHUNK_REMAINING_CAPACITY(buf
->tail
);
47 switch (tor_compress_process(state
, &next
, &avail
,
48 &data
, &data_len
, done
)) {
49 case TOR_COMPRESS_DONE
:
52 case TOR_COMPRESS_ERROR
:
56 tor_assert_nonfatal(!done
);
60 case TOR_COMPRESS_BUFFER_FULL
:
62 /* The compression module says we need more room
63 * (TOR_COMPRESS_BUFFER_FULL). Start a new chunk automatically,
64 * whether were going to or not. */
67 if (data_len
== 0 && !done
) {
68 /* We've consumed all the input data, though, so there's no
69 * point in forging ahead right now. */
74 buf
->datalen
+= old_avail
- avail
;
75 buf
->tail
->datalen
+= old_avail
- avail
;
77 buf_add_chunk_with_capacity(buf
, data_len
/4, 1);