Tor 0.4.9.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. */
43static inline int
44read_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? */
90static int
91buf_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);
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 */
143static inline int
144flush_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 */
181static int
182buf_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;
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 */
223int
224buf_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 */
234int
235buf_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 */
248int
249buf_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 */
259int
260buf_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}
void buf_drain(buf_t *buf, size_t n)
Definition: buffers.c:330
chunk_t * buf_add_chunk_with_capacity(buf_t *buf, size_t capacity, int capped)
Definition: buffers.c:475
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:103