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 }