compress_buf.c 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. /* Copyright (c) 2003, Roger Dingledine
  2. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  3. * Copyright (c) 2007-2018, The Tor Project, Inc. */
  4. /* See LICENSE for licensing information */
  5. #define BUFFERS_PRIVATE
  6. #include "lib/cc/compat_compiler.h"
  7. #include "lib/container/buffers.h"
  8. #include "lib/compress/compress.h"
  9. #include "lib/log/util_bug.h"
  10. #ifdef PARANOIA
  11. /** Helper: If PARANOIA is defined, assert that the buffer in local variable
  12. * <b>buf</b> is well-formed. */
  13. #define check() STMT_BEGIN buf_assert_ok(buf); STMT_END
  14. #else
  15. #define check() STMT_NIL
  16. #endif /* defined(PARANOIA) */
  17. /** Compress or uncompress the <b>data_len</b> bytes in <b>data</b> using the
  18. * compression state <b>state</b>, appending the result to <b>buf</b>. If
  19. * <b>done</b> is true, flush the data in the state and finish the
  20. * compression/uncompression. Return -1 on failure, 0 on success. */
  21. int
  22. buf_add_compress(buf_t *buf, tor_compress_state_t *state,
  23. const char *data, size_t data_len,
  24. const int done)
  25. {
  26. char *next;
  27. size_t old_avail, avail;
  28. int over = 0;
  29. do {
  30. int need_new_chunk = 0;
  31. if (!buf->tail || ! CHUNK_REMAINING_CAPACITY(buf->tail)) {
  32. size_t cap = data_len / 4;
  33. buf_add_chunk_with_capacity(buf, cap, 1);
  34. }
  35. next = CHUNK_WRITE_PTR(buf->tail);
  36. avail = old_avail = CHUNK_REMAINING_CAPACITY(buf->tail);
  37. switch (tor_compress_process(state, &next, &avail,
  38. &data, &data_len, done)) {
  39. case TOR_COMPRESS_DONE:
  40. over = 1;
  41. break;
  42. case TOR_COMPRESS_ERROR:
  43. return -1;
  44. case TOR_COMPRESS_OK:
  45. if (data_len == 0) {
  46. tor_assert_nonfatal(!done);
  47. over = 1;
  48. }
  49. break;
  50. case TOR_COMPRESS_BUFFER_FULL:
  51. if (avail) {
  52. /* The compression module says we need more room
  53. * (TOR_COMPRESS_BUFFER_FULL). Start a new chunk automatically,
  54. * whether were going to or not. */
  55. need_new_chunk = 1;
  56. }
  57. if (data_len == 0 && !done) {
  58. /* We've consumed all the input data, though, so there's no
  59. * point in forging ahead right now. */
  60. over = 1;
  61. }
  62. break;
  63. }
  64. buf->datalen += old_avail - avail;
  65. buf->tail->datalen += old_avail - avail;
  66. if (need_new_chunk) {
  67. buf_add_chunk_with_capacity(buf, data_len/4, 1);
  68. }
  69. } while (!over);
  70. check();
  71. return 0;
  72. }