tor  0.4.0.1-alpha
buffers_tls.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-2019, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
6 
12 #define BUFFERS_PRIVATE
13 #include "orconfig.h"
14 #include <stddef.h>
15 #include "lib/buf/buffers.h"
16 #include "lib/tls/buffers_tls.h"
17 #include "lib/cc/torint.h"
18 #include "lib/log/log.h"
19 #include "lib/log/util_bug.h"
20 #include "lib/tls/tortls.h"
21 
22 #ifdef HAVE_UNISTD_H
23 #include <unistd.h>
24 #endif
25 
28 static inline int
29 read_to_chunk_tls(buf_t *buf, chunk_t *chunk, tor_tls_t *tls,
30  size_t at_most)
31 {
32  int read_result;
33 
34  tor_assert(CHUNK_REMAINING_CAPACITY(chunk) >= at_most);
35  read_result = tor_tls_read(tls, CHUNK_WRITE_PTR(chunk), at_most);
36  if (read_result < 0)
37  return read_result;
38  buf->datalen += read_result;
39  chunk->datalen += read_result;
40  return read_result;
41 }
42 
63 int
64 buf_read_from_tls(buf_t *buf, tor_tls_t *tls, size_t at_most)
65 {
66  int r = 0;
67  size_t total_read = 0;
68 
69  check_no_tls_errors();
70 
71  if (BUG(buf->datalen >= INT_MAX))
72  return -1;
73  if (BUG(buf->datalen >= INT_MAX - at_most))
74  return -1;
75 
76  while (at_most > total_read) {
77  size_t readlen = at_most - total_read;
78  chunk_t *chunk;
79  if (!buf->tail || CHUNK_REMAINING_CAPACITY(buf->tail) < MIN_READ_LEN) {
80  chunk = buf_add_chunk_with_capacity(buf, at_most, 1);
81  if (readlen > chunk->memlen)
82  readlen = chunk->memlen;
83  } else {
84  size_t cap = CHUNK_REMAINING_CAPACITY(buf->tail);
85  chunk = buf->tail;
86  if (cap < readlen)
87  readlen = cap;
88  }
89 
90  r = read_to_chunk_tls(buf, chunk, tls, readlen);
91  if (r < 0)
92  return r; /* Error */
93  tor_assert(total_read+r < INT_MAX);
94  total_read += r;
95  if ((size_t)r < readlen) /* eof, block, or no more to read. */
96  break;
97  }
98  return (int)total_read;
99 }
100 
107 static inline int
108 flush_chunk_tls(tor_tls_t *tls, buf_t *buf, chunk_t *chunk,
109  size_t sz, size_t *buf_flushlen)
110 {
111  int r;
112  size_t forced;
113  char *data;
114 
115  forced = tor_tls_get_forced_write_size(tls);
116  if (forced > sz)
117  sz = forced;
118  if (chunk) {
119  data = chunk->data;
120  tor_assert(sz <= chunk->datalen);
121  } else {
122  data = NULL;
123  tor_assert(sz == 0);
124  }
125  r = tor_tls_write(tls, data, sz);
126  if (r < 0)
127  return r;
128  if (*buf_flushlen > (size_t)r)
129  *buf_flushlen -= r;
130  else
131  *buf_flushlen = 0;
132  buf_drain(buf, r);
133  log_debug(LD_NET,"flushed %d bytes, %d ready to flush, %d remain.",
134  r,(int)*buf_flushlen,(int)buf->datalen);
135  return r;
136 }
137 
141 int
142 buf_flush_to_tls(buf_t *buf, tor_tls_t *tls, size_t flushlen,
143  size_t *buf_flushlen)
144 {
145  int r;
146  size_t flushed = 0;
147  ssize_t sz;
148  tor_assert(buf_flushlen);
149  if (BUG(*buf_flushlen > buf->datalen)) {
150  *buf_flushlen = buf->datalen;
151  }
152  if (BUG(flushlen > *buf_flushlen)) {
153  flushlen = *buf_flushlen;
154  }
155  sz = (ssize_t) flushlen;
156 
157  /* we want to let tls write even if flushlen is zero, because it might
158  * have a partial record pending */
159  check_no_tls_errors();
160 
161  do {
162  size_t flushlen0;
163  if (buf->head) {
164  if ((ssize_t)buf->head->datalen >= sz)
165  flushlen0 = sz;
166  else
167  flushlen0 = buf->head->datalen;
168  } else {
169  flushlen0 = 0;
170  }
171 
172  r = flush_chunk_tls(tls, buf, buf->head, flushlen0, buf_flushlen);
173  if (r < 0)
174  return r;
175  flushed += r;
176  sz -= r;
177  if (r == 0) /* Can't flush any more now. */
178  break;
179  } while (sz > 0);
180  tor_assert(flushed < INT_MAX);
181  return (int)flushed;
182 }
Header for buffers_tls.c.
chunk_t * buf_add_chunk_with_capacity(buf_t *buf, size_t capacity, int capped)
Definition: buffers.c:473
Integer definitions used throughout Tor.
tor_assert(buffer)
static int read_to_chunk_tls(buf_t *buf, chunk_t *chunk, tor_tls_t *tls, size_t at_most)
Definition: buffers_tls.c:29
int buf_read_from_tls(buf_t *buf, tor_tls_t *tls, size_t at_most)
Definition: buffers_tls.c:64
void buf_drain(buf_t *buf, size_t n)
Definition: buffers.c:328
Headers for tortls.c.
size_t tor_tls_get_forced_write_size(tor_tls_t *tls)
Definition: tortls_nss.c:614
int tor_tls_write(tor_tls_t *tls, const char *cp, size_t n)
Definition: tortls_nss.c:530
int buf_flush_to_tls(buf_t *buf, tor_tls_t *tls, size_t flushlen, size_t *buf_flushlen)
Definition: buffers_tls.c:142
static int flush_chunk_tls(tor_tls_t *tls, buf_t *buf, chunk_t *chunk, size_t sz, size_t *buf_flushlen)
Definition: buffers_tls.c:108
Header file for buffers.c.
#define LD_NET
Definition: log.h:62
Headers for log.c.
Macros to manage assertions, fatal and non-fatal.