buffers_net.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /* Copyright (c) 2001 Matej Pfajfar.
  2. * Copyright (c) 2001-2004, Roger Dingledine.
  3. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  4. * Copyright (c) 2007-2018, The Tor Project, Inc. */
  5. /* See LICENSE for licensing information */
  6. /**
  7. * \file buffers_net.c
  8. * \brief Read and write data on a buf_t object.
  9. **/
  10. #define BUFFERS_PRIVATE
  11. #include "lib/net/buffers_net.h"
  12. #include "lib/container/buffers.h"
  13. #include "lib/log/torlog.h"
  14. #include "lib/log/util_bug.h"
  15. #include "lib/net/nettypes.h"
  16. #ifdef _WIN32
  17. #include <winsock2.h>
  18. #endif
  19. #include <stdlib.h>
  20. #ifdef PARANOIA
  21. /** Helper: If PARANOIA is defined, assert that the buffer in local variable
  22. * <b>buf</b> is well-formed. */
  23. #define check() STMT_BEGIN buf_assert_ok(buf); STMT_END
  24. #else
  25. #define check() STMT_NIL
  26. #endif /* defined(PARANOIA) */
  27. /** Read up to <b>at_most</b> bytes from the socket <b>fd</b> into
  28. * <b>chunk</b> (which must be on <b>buf</b>). If we get an EOF, set
  29. * *<b>reached_eof</b> to 1. Return -1 on error, 0 on eof or blocking,
  30. * and the number of bytes read otherwise. */
  31. static inline int
  32. read_to_chunk(buf_t *buf, chunk_t *chunk, tor_socket_t fd, size_t at_most,
  33. int *reached_eof, int *socket_error)
  34. {
  35. ssize_t read_result;
  36. if (at_most > CHUNK_REMAINING_CAPACITY(chunk))
  37. at_most = CHUNK_REMAINING_CAPACITY(chunk);
  38. read_result = tor_socket_recv(fd, CHUNK_WRITE_PTR(chunk), at_most, 0);
  39. if (read_result < 0) {
  40. int e = tor_socket_errno(fd);
  41. if (!ERRNO_IS_EAGAIN(e)) { /* it's a real error */
  42. #ifdef _WIN32
  43. if (e == WSAENOBUFS)
  44. log_warn(LD_NET,"recv() failed: WSAENOBUFS. Not enough ram?");
  45. #endif
  46. *socket_error = e;
  47. return -1;
  48. }
  49. return 0; /* would block. */
  50. } else if (read_result == 0) {
  51. log_debug(LD_NET,"Encountered eof on fd %d", (int)fd);
  52. *reached_eof = 1;
  53. return 0;
  54. } else { /* actually got bytes. */
  55. buf->datalen += read_result;
  56. chunk->datalen += read_result;
  57. log_debug(LD_NET,"Read %ld bytes. %d on inbuf.", (long)read_result,
  58. (int)buf->datalen);
  59. tor_assert(read_result < INT_MAX);
  60. return (int)read_result;
  61. }
  62. }
  63. /** Read from socket <b>s</b>, writing onto end of <b>buf</b>. Read at most
  64. * <b>at_most</b> bytes, growing the buffer as necessary. If recv() returns 0
  65. * (because of EOF), set *<b>reached_eof</b> to 1 and return 0. Return -1 on
  66. * error; else return the number of bytes read.
  67. */
  68. /* XXXX indicate "read blocked" somehow? */
  69. int
  70. buf_read_from_socket(buf_t *buf, tor_socket_t s, size_t at_most,
  71. int *reached_eof,
  72. int *socket_error)
  73. {
  74. /* XXXX It's stupid to overload the return values for these functions:
  75. * "error status" and "number of bytes read" are not mutually exclusive.
  76. */
  77. int r = 0;
  78. size_t total_read = 0;
  79. check();
  80. tor_assert(reached_eof);
  81. tor_assert(SOCKET_OK(s));
  82. if (BUG(buf->datalen >= INT_MAX))
  83. return -1;
  84. if (BUG(buf->datalen >= INT_MAX - at_most))
  85. return -1;
  86. while (at_most > total_read) {
  87. size_t readlen = at_most - total_read;
  88. chunk_t *chunk;
  89. if (!buf->tail || CHUNK_REMAINING_CAPACITY(buf->tail) < MIN_READ_LEN) {
  90. chunk = buf_add_chunk_with_capacity(buf, at_most, 1);
  91. if (readlen > chunk->memlen)
  92. readlen = chunk->memlen;
  93. } else {
  94. size_t cap = CHUNK_REMAINING_CAPACITY(buf->tail);
  95. chunk = buf->tail;
  96. if (cap < readlen)
  97. readlen = cap;
  98. }
  99. r = read_to_chunk(buf, chunk, s, readlen, reached_eof, socket_error);
  100. check();
  101. if (r < 0)
  102. return r; /* Error */
  103. tor_assert(total_read+r < INT_MAX);
  104. total_read += r;
  105. if ((size_t)r < readlen) { /* eof, block, or no more to read. */
  106. break;
  107. }
  108. }
  109. return (int)total_read;
  110. }
  111. /** Helper for buf_flush_to_socket(): try to write <b>sz</b> bytes from chunk
  112. * <b>chunk</b> of buffer <b>buf</b> onto socket <b>s</b>. On success, deduct
  113. * the bytes written from *<b>buf_flushlen</b>. Return the number of bytes
  114. * written on success, 0 on blocking, -1 on failure.
  115. */
  116. static inline int
  117. flush_chunk(tor_socket_t s, buf_t *buf, chunk_t *chunk, size_t sz,
  118. size_t *buf_flushlen)
  119. {
  120. ssize_t write_result;
  121. if (sz > chunk->datalen)
  122. sz = chunk->datalen;
  123. write_result = tor_socket_send(s, chunk->data, sz, 0);
  124. if (write_result < 0) {
  125. int e = tor_socket_errno(s);
  126. if (!ERRNO_IS_EAGAIN(e)) { /* it's a real error */
  127. #ifdef _WIN32
  128. if (e == WSAENOBUFS)
  129. log_warn(LD_NET,"write() failed: WSAENOBUFS. Not enough ram?");
  130. #endif
  131. return -1;
  132. }
  133. log_debug(LD_NET,"write() would block, returning.");
  134. return 0;
  135. } else {
  136. *buf_flushlen -= write_result;
  137. buf_drain(buf, write_result);
  138. tor_assert(write_result < INT_MAX);
  139. return (int)write_result;
  140. }
  141. }
  142. /** Write data from <b>buf</b> to the socket <b>s</b>. Write at most
  143. * <b>sz</b> bytes, decrement *<b>buf_flushlen</b> by
  144. * the number of bytes actually written, and remove the written bytes
  145. * from the buffer. Return the number of bytes written on success,
  146. * -1 on failure. Return 0 if write() would block.
  147. */
  148. int
  149. buf_flush_to_socket(buf_t *buf, tor_socket_t s, size_t sz,
  150. size_t *buf_flushlen)
  151. {
  152. /* XXXX It's stupid to overload the return values for these functions:
  153. * "error status" and "number of bytes flushed" are not mutually exclusive.
  154. */
  155. int r;
  156. size_t flushed = 0;
  157. tor_assert(buf_flushlen);
  158. tor_assert(SOCKET_OK(s));
  159. if (BUG(*buf_flushlen > buf->datalen)) {
  160. *buf_flushlen = buf->datalen;
  161. }
  162. if (BUG(sz > *buf_flushlen)) {
  163. sz = *buf_flushlen;
  164. }
  165. check();
  166. while (sz) {
  167. size_t flushlen0;
  168. tor_assert(buf->head);
  169. if (buf->head->datalen >= sz)
  170. flushlen0 = sz;
  171. else
  172. flushlen0 = buf->head->datalen;
  173. r = flush_chunk(s, buf, buf->head, flushlen0, buf_flushlen);
  174. check();
  175. if (r < 0)
  176. return r;
  177. flushed += r;
  178. sz -= r;
  179. if (r == 0 || (size_t)r < flushlen0) /* can't flush any more now. */
  180. break;
  181. }
  182. tor_assert(flushed < INT_MAX);
  183. return (int)flushed;
  184. }