tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

compress_buf.c (2541B)


      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
     31 buf_add_compress(buf_t *buf, tor_compress_state_t *state,
     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 }