Update copyrights to 2021, using "make update-copyright"
[tor.git] / src / lib / compress / compress_buf.c
blob51cca0e7ae7d8790111428082b340177cda0d65e
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 */
6 /**
7 * \file compress_buf.c
9 * \brief Working with compressed data in buffers.
10 **/
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"
18 #ifdef PARANOIA
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
22 #else
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. */
30 int
31 buf_add_compress(buf_t *buf, tor_compress_state_t *state,
32 const char *data, size_t data_len,
33 const int done)
35 char *next;
36 size_t old_avail, avail;
37 int over = 0;
39 do {
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:
50 over = 1;
51 break;
52 case TOR_COMPRESS_ERROR:
53 return -1;
54 case TOR_COMPRESS_OK:
55 if (data_len == 0) {
56 tor_assert_nonfatal(!done);
57 over = 1;
59 break;
60 case TOR_COMPRESS_BUFFER_FULL:
61 if (avail) {
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. */
65 need_new_chunk = 1;
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. */
70 over = 1;
72 break;
74 buf->datalen += old_avail - avail;
75 buf->tail->datalen += old_avail - avail;
76 if (need_new_chunk) {
77 buf_add_chunk_with_capacity(buf, data_len/4, 1);
80 } while (!over);
81 check();
82 return 0;