Tor  0.4.7.0-alpha-dev
compress_buf.c
Go to the documentation of this file.
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 */
5 
6 /**
7  * \file compress_buf.c
8  *
9  * \brief Working with compressed data in buffers.
10  **/
11 
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"
17 
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) */
25 
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
32  const char *data, size_t data_len,
33  const int done)
34 {
35  char *next;
36  size_t old_avail, avail;
37  int over = 0;
38 
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);
44  }
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;
58  }
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;
66  }
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;
71  }
72  break;
73  }
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);
78  }
79 
80  } while (!over);
81  check();
82  return 0;
83 }
chunk_t * buf_add_chunk_with_capacity(buf_t *buf, size_t capacity, int capped)
Definition: buffers.c:475
Header file for buffers.c.
Utility macros to handle different features and behavior in different compilers.
tor_compress_output_t tor_compress_process(tor_compress_state_t *state, char **out, size_t *out_len, const char **in, size_t *in_len, int finish)
Definition: compress.c:549
Headers for compress.c.
int buf_add_compress(buf_t *buf, tor_compress_state_t *state, const char *data, size_t data_len, const int done)
Definition: compress_buf.c:31
Macros to manage assertions, fatal and non-fatal.