Tor  0.4.7.0-alpha-dev
buffers_net.c
Go to the documentation of this file.
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-2021, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
6 
7 /**
8  * \file buffers_net.c
9  * \brief Read and write data on a buf_t object.
10  **/
11 
12 #define BUFFERS_PRIVATE
13 #include "lib/net/buffers_net.h"
14 #include "lib/buf/buffers.h"
15 #include "lib/log/log.h"
16 #include "lib/log/util_bug.h"
17 #include "lib/net/nettypes.h"
18 
19 #ifdef _WIN32
20 #include <winsock2.h>
21 #endif
22 
23 #include <stdlib.h>
24 
25 #ifdef HAVE_UNISTD_H
26 #include <unistd.h>
27 #endif
28 
29 #ifdef PARANOIA
30 /** Helper: If PARANOIA is defined, assert that the buffer in local variable
31  * <b>buf</b> is well-formed. */
32 #define check() STMT_BEGIN buf_assert_ok(buf); STMT_END
33 #else
34 #define check() STMT_NIL
35 #endif /* defined(PARANOIA) */
36 
37 /** Read up to <b>at_most</b> bytes from the file descriptor <b>fd</b> into
38  * <b>chunk</b> (which must be on <b>buf</b>). If we get an EOF, set
39  * *<b>reached_eof</b> to 1. Uses <b>tor_socket_recv()</b> iff <b>is_socket</b>
40  * is true, otherwise it uses <b>read()</b>. Return -1 on error (and sets
41  * *<b>error</b> to errno), 0 on eof or blocking, and the number of bytes read
42  * otherwise. */
43 static inline int
44 read_to_chunk(buf_t *buf, chunk_t *chunk, tor_socket_t fd, size_t at_most,
45  int *reached_eof, int *error, bool is_socket)
46 {
47  ssize_t read_result;
48  if (at_most > CHUNK_REMAINING_CAPACITY(chunk))
49  at_most = CHUNK_REMAINING_CAPACITY(chunk);
50 
51  if (is_socket)
52  read_result = tor_socket_recv(fd, CHUNK_WRITE_PTR(chunk), at_most, 0);
53  else
54  read_result = read(fd, CHUNK_WRITE_PTR(chunk), at_most);
55 
56  if (read_result < 0) {
57  int e = is_socket ? tor_socket_errno(fd) : errno;
58 
59  if (!ERRNO_IS_EAGAIN(e)) { /* it's a real error */
60 #ifdef _WIN32
61  if (e == WSAENOBUFS)
62  log_warn(LD_NET, "%s() failed: WSAENOBUFS. Not enough ram?",
63  is_socket ? "recv" : "read");
64 #endif
65  if (error)
66  *error = e;
67  return -1;
68  }
69  return 0; /* would block. */
70  } else if (read_result == 0) {
71  log_debug(LD_NET,"Encountered eof on fd %d", (int)fd);
72  *reached_eof = 1;
73  return 0;
74  } else { /* actually got bytes. */
75  buf->datalen += read_result;
76  chunk->datalen += read_result;
77  log_debug(LD_NET,"Read %ld bytes. %d on inbuf.", (long)read_result,
78  (int)buf->datalen);
79  tor_assert(read_result <= BUF_MAX_LEN);
80  return (int)read_result;
81  }
82 }
83 
84 /** Read from file descriptor <b>fd</b>, writing onto end of <b>buf</b>. Read
85  * at most <b>at_most</b> bytes, growing the buffer as necessary. If recv()
86  * returns 0 (because of EOF), set *<b>reached_eof</b> to 1 and return 0.
87  * Return -1 on error; else return the number of bytes read.
88  */
89 /* XXXX indicate "read blocked" somehow? */
90 static int
91 buf_read_from_fd(buf_t *buf, int fd, size_t at_most,
92  int *reached_eof,
93  int *socket_error,
94  bool is_socket)
95 {
96  /* XXXX It's stupid to overload the return values for these functions:
97  * "error status" and "number of bytes read" are not mutually exclusive.
98  */
99  int r = 0;
100  size_t total_read = 0;
101 
102  check();
103  tor_assert(reached_eof);
104  tor_assert(SOCKET_OK(fd));
105 
106  if (BUG(buf->datalen > BUF_MAX_LEN))
107  return -1;
108  if (BUG(buf->datalen > BUF_MAX_LEN - at_most))
109  return -1;
110 
111  while (at_most > total_read) {
112  size_t readlen = at_most - total_read;
113  chunk_t *chunk;
114  if (!buf->tail || CHUNK_REMAINING_CAPACITY(buf->tail) < MIN_READ_LEN) {
115  chunk = buf_add_chunk_with_capacity(buf, at_most, 1);
116  if (readlen > chunk->memlen)
117  readlen = chunk->memlen;
118  } else {
119  size_t cap = CHUNK_REMAINING_CAPACITY(buf->tail);
120  chunk = buf->tail;
121  if (cap < readlen)
122  readlen = cap;
123  }
124 
125  r = read_to_chunk(buf, chunk, fd, readlen,
126  reached_eof, socket_error, is_socket);
127  check();
128  if (r < 0)
129  return r; /* Error */
130  tor_assert(total_read+r <= BUF_MAX_LEN);
131  total_read += r;
132  if ((size_t)r < readlen) { /* eof, block, or no more to read. */
133  break;
134  }
135  }
136  return (int)total_read;
137 }
138 
139 /** Helper for buf_flush_to_socket(): try to write <b>sz</b> bytes from chunk
140  * <b>chunk</b> of buffer <b>buf</b> onto file descriptor <b>fd</b>. Return
141  * the number of bytes written on success, 0 on blocking, -1 on failure.
142  */
143 static inline int
144 flush_chunk(tor_socket_t fd, buf_t *buf, chunk_t *chunk, size_t sz,
145  bool is_socket)
146 {
147  ssize_t write_result;
148 
149  if (sz > chunk->datalen)
150  sz = chunk->datalen;
151 
152  if (is_socket)
153  write_result = tor_socket_send(fd, chunk->data, sz, 0);
154  else
155  write_result = write(fd, chunk->data, sz);
156 
157  if (write_result < 0) {
158  int e = is_socket ? tor_socket_errno(fd) : errno;
159 
160  if (!ERRNO_IS_EAGAIN(e)) { /* it's a real error */
161 #ifdef _WIN32
162  if (e == WSAENOBUFS)
163  log_warn(LD_NET,"write() failed: WSAENOBUFS. Not enough ram?");
164 #endif
165  return -1;
166  }
167  log_debug(LD_NET,"write() would block, returning.");
168  return 0;
169  } else {
170  buf_drain(buf, write_result);
171  tor_assert(write_result <= BUF_MAX_LEN);
172  return (int)write_result;
173  }
174 }
175 
176 /** Write data from <b>buf</b> to the file descriptor <b>fd</b>. Write at most
177  * <b>sz</b> bytes, and remove the written bytes
178  * from the buffer. Return the number of bytes written on success,
179  * -1 on failure. Return 0 if write() would block.
180  */
181 static int
182 buf_flush_to_fd(buf_t *buf, int fd, size_t sz,
183  bool is_socket)
184 {
185  /* XXXX It's stupid to overload the return values for these functions:
186  * "error status" and "number of bytes flushed" are not mutually exclusive.
187  */
188  int r;
189  size_t flushed = 0;
190  tor_assert(SOCKET_OK(fd));
191  if (BUG(sz > buf->datalen)) {
192  sz = buf->datalen;
193  }
194 
195  check();
196  while (sz) {
197  size_t flushlen0;
198  tor_assert(buf->head);
199  if (buf->head->datalen >= sz)
200  flushlen0 = sz;
201  else
202  flushlen0 = buf->head->datalen;
203 
204  r = flush_chunk(fd, buf, buf->head, flushlen0, is_socket);
205  check();
206  if (r < 0)
207  return r;
208  flushed += r;
209  sz -= r;
210  if (r == 0 || (size_t)r < flushlen0) /* can't flush any more now. */
211  break;
212  }
213  tor_assert(flushed <= BUF_MAX_LEN);
214  return (int)flushed;
215 }
216 
217 /** Write data from <b>buf</b> to the socket <b>s</b>. Write at most
218  * <b>sz</b> bytes, decrement *<b>buf_flushlen</b> by
219  * the number of bytes actually written, and remove the written bytes
220  * from the buffer. Return the number of bytes written on success,
221  * -1 on failure. Return 0 if write() would block.
222  */
223 int
224 buf_flush_to_socket(buf_t *buf, tor_socket_t s, size_t sz)
225 {
226  return buf_flush_to_fd(buf, s, sz, true);
227 }
228 
229 /** Read from socket <b>s</b>, writing onto end of <b>buf</b>. Read at most
230  * <b>at_most</b> bytes, growing the buffer as necessary. If recv() returns 0
231  * (because of EOF), set *<b>reached_eof</b> to 1 and return 0. Return -1 on
232  * error; else return the number of bytes read.
233  */
234 int
235 buf_read_from_socket(buf_t *buf, tor_socket_t s, size_t at_most,
236  int *reached_eof,
237  int *socket_error)
238 {
239  return buf_read_from_fd(buf, s, at_most, reached_eof, socket_error, true);
240 }
241 
242 /** Write data from <b>buf</b> to the pipe <b>fd</b>. Write at most
243  * <b>sz</b> bytes, decrement *<b>buf_flushlen</b> by
244  * the number of bytes actually written, and remove the written bytes
245  * from the buffer. Return the number of bytes written on success,
246  * -1 on failure. Return 0 if write() would block.
247  */
248 int
249 buf_flush_to_pipe(buf_t *buf, int fd, size_t sz)
250 {
251  return buf_flush_to_fd(buf, fd, sz, false);
252 }
253 
254 /** Read from pipe <b>fd</b>, writing onto end of <b>buf</b>. Read at most
255  * <b>at_most</b> bytes, growing the buffer as necessary. If read() returns 0
256  * (because of EOF), set *<b>reached_eof</b> to 1 and return 0. Return -1 on
257  * error; else return the number of bytes read.
258  */
259 int
260 buf_read_from_pipe(buf_t *buf, int fd, size_t at_most,
261  int *reached_eof,
262  int *socket_error)
263 {
264  return buf_read_from_fd(buf, fd, at_most, reached_eof, socket_error, false);
265 }
chunk_t * buf_add_chunk_with_capacity(buf_t *buf, size_t capacity, int capped)
Definition: buffers.c:475
void buf_drain(buf_t *buf, size_t n)
Definition: buffers.c:330
Header file for buffers.c.
#define BUF_MAX_LEN
Definition: buffers.h:33
int buf_flush_to_socket(buf_t *buf, tor_socket_t s, size_t sz)
Definition: buffers_net.c:224
int buf_read_from_pipe(buf_t *buf, int fd, size_t at_most, int *reached_eof, int *socket_error)
Definition: buffers_net.c:260
static int read_to_chunk(buf_t *buf, chunk_t *chunk, tor_socket_t fd, size_t at_most, int *reached_eof, int *error, bool is_socket)
Definition: buffers_net.c:44
int buf_flush_to_pipe(buf_t *buf, int fd, size_t sz)
Definition: buffers_net.c:249
static int buf_flush_to_fd(buf_t *buf, int fd, size_t sz, bool is_socket)
Definition: buffers_net.c:182
static int flush_chunk(tor_socket_t fd, buf_t *buf, chunk_t *chunk, size_t sz, bool is_socket)
Definition: buffers_net.c:144
int buf_read_from_socket(buf_t *buf, tor_socket_t s, size_t at_most, int *reached_eof, int *socket_error)
Definition: buffers_net.c:235
static int buf_read_from_fd(buf_t *buf, int fd, size_t at_most, int *reached_eof, int *socket_error, bool is_socket)
Definition: buffers_net.c:91
Header file for buffers_net.c.
Headers for log.c.
#define LD_NET
Definition: log.h:66
Declarations for types used throughout the Tor networking system.
#define SOCKET_OK(s)
Definition: nettypes.h:39
#define tor_socket_t
Definition: nettypes.h:36
Macros to manage assertions, fatal and non-fatal.
#define tor_assert(expr)
Definition: util_bug.h:102