tor  0.4.2.1-alpha-dev
nss_countbytes.c
Go to the documentation of this file.
1 /* Copyright 2018-2019, The Tor Project Inc. */
2 /* See LICENSE for licensing information */
3 
10 #include "orconfig.h"
11 
12 #include "lib/log/util_bug.h"
13 #include "lib/malloc/malloc.h"
14 #include "lib/tls/nss_countbytes.h"
15 
16 #include <stdlib.h>
17 #include <string.h>
18 
19 #include <prio.h>
20 
22 static bool countbytes_initialized = false;
23 
25 static PRDescIdentity countbytes_layer_id = PR_INVALID_IO_LAYER;
26 
28 static PRIOMethods countbytes_methods;
29 
32 static PRStatus(*default_close_fn)(PRFileDesc *fd);
33 
34 static PRStatus countbytes_close_fn(PRFileDesc *fd);
35 static PRInt32 countbytes_read_fn(PRFileDesc *fd, void *buf, PRInt32 amount);
36 static PRInt32 countbytes_write_fn(PRFileDesc *fd, const void *buf,
37  PRInt32 amount);
38 static PRInt32 countbytes_writev_fn(PRFileDesc *fd, const PRIOVec *iov,
39  PRInt32 size, PRIntervalTime timeout);
40 static PRInt32 countbytes_send_fn(PRFileDesc *fd, const void *buf,
41  PRInt32 amount, PRIntn flags,
42  PRIntervalTime timeout);
43 static PRInt32 countbytes_recv_fn(PRFileDesc *fd, void *buf, PRInt32 amount,
44  PRIntn flags, PRIntervalTime timeout);
45 
48 typedef struct tor_nss_bytecounts_t {
49  uint64_t n_read;
50  uint64_t n_written;
52 
56 void
58 {
60  return;
61 
62  countbytes_layer_id = PR_GetUniqueIdentity("Tor byte-counting layer");
63  tor_assert(countbytes_layer_id != PR_INVALID_IO_LAYER);
64 
65  memcpy(&countbytes_methods, PR_GetDefaultIOMethods(), sizeof(PRIOMethods));
66 
74  /* NOTE: We aren't wrapping recvfrom, sendto, or sendfile, since I think
75  * NSS won't be using them for TLS connections. */
76 
78 }
79 
84 static tor_nss_bytecounts_t *
85 get_counts(PRFileDesc *fd)
86 {
87  tor_assert(fd->identity == countbytes_layer_id);
88  return (tor_nss_bytecounts_t*) fd->secret;
89 }
90 
92 #define INC_READ(fd, n) STMT_BEGIN \
93  get_counts(fd)->n_read += (n); \
94  STMT_END
95 
97 #define INC_WRITTEN(fd, n) STMT_BEGIN \
98  get_counts(fd)->n_written += (n); \
99  STMT_END
100 
103 static PRStatus
104 countbytes_close_fn(PRFileDesc *fd)
105 {
106  tor_assert(fd);
107 
108  tor_nss_bytecounts_t *counts = (tor_nss_bytecounts_t *)fd->secret;
109  tor_free(counts);
110  fd->secret = NULL;
111 
112  return default_close_fn(fd);
113 }
114 
117 static PRInt32
118 countbytes_read_fn(PRFileDesc *fd, void *buf, PRInt32 amount)
119 {
120  tor_assert(fd);
121  tor_assert(fd->lower);
122 
123  PRInt32 result = (fd->lower->methods->read)(fd->lower, buf, amount);
124  if (result > 0)
125  INC_READ(fd, result);
126  return result;
127 }
130 static PRInt32
131 countbytes_write_fn(PRFileDesc *fd, const void *buf, PRInt32 amount)
132 {
133  tor_assert(fd);
134  tor_assert(fd->lower);
135 
136  PRInt32 result = (fd->lower->methods->write)(fd->lower, buf, amount);
137  if (result > 0)
138  INC_WRITTEN(fd, result);
139  return result;
140 }
143 static PRInt32
144 countbytes_writev_fn(PRFileDesc *fd, const PRIOVec *iov,
145  PRInt32 size, PRIntervalTime timeout)
146 {
147  tor_assert(fd);
148  tor_assert(fd->lower);
149 
150  PRInt32 result = (fd->lower->methods->writev)(fd->lower, iov, size, timeout);
151  if (result > 0)
152  INC_WRITTEN(fd, result);
153  return result;
154 }
157 static PRInt32
158 countbytes_send_fn(PRFileDesc *fd, const void *buf,
159  PRInt32 amount, PRIntn flags, PRIntervalTime timeout)
160 {
161  tor_assert(fd);
162  tor_assert(fd->lower);
163 
164  PRInt32 result = (fd->lower->methods->send)(fd->lower, buf, amount, flags,
165  timeout);
166  if (result > 0)
167  INC_WRITTEN(fd, result);
168  return result;
169 }
172 static PRInt32
173 countbytes_recv_fn(PRFileDesc *fd, void *buf, PRInt32 amount,
174  PRIntn flags, PRIntervalTime timeout)
175 {
176  tor_assert(fd);
177  tor_assert(fd->lower);
178 
179  PRInt32 result = (fd->lower->methods->recv)(fd->lower, buf, amount, flags,
180  timeout);
181  if (result > 0)
182  INC_READ(fd, result);
183  return result;
184 }
185 
192 PRFileDesc *
194 {
195  if (BUG(! countbytes_initialized)) {
197  }
198 
199  tor_nss_bytecounts_t *bytecounts = tor_malloc_zero(sizeof(*bytecounts));
200 
201  PRFileDesc *newfd = PR_CreateIOLayerStub(countbytes_layer_id,
203  tor_assert(newfd);
204  newfd->secret = (PRFilePrivate *)bytecounts;
205 
206  /* This does some complicated messing around with the headers of these
207  objects; see the NSPR documentation for more. The upshot is that
208  after PushIOLayer, "stack" will be the head of the stack.
209  */
210  PRStatus status = PR_PushIOLayer(stack, PR_TOP_IO_LAYER, newfd);
211  tor_assert(status == PR_SUCCESS);
212 
213  return stack;
214 }
215 
224 int
226  uint64_t *n_read_out,
227  uint64_t *n_written_out)
228 {
229  if (BUG(! countbytes_initialized)) {
231  }
232 
233  tor_assert(fd);
234  PRFileDesc *bclayer = PR_GetIdentitiesLayer(fd, countbytes_layer_id);
235  if (BUG(bclayer == NULL))
236  return -1;
237 
238  tor_nss_bytecounts_t *counts = get_counts(bclayer);
239 
240  *n_read_out = counts->n_read;
241  *n_written_out = counts->n_written;
242 
243  return 0;
244 }
static PRInt32 countbytes_recv_fn(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout)
static PRInt32 countbytes_send_fn(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout)
#define INC_READ(fd, n)
static PRInt32 countbytes_writev_fn(PRFileDesc *fd, const PRIOVec *iov, PRInt32 size, PRIntervalTime timeout)
static PRIOMethods countbytes_methods
void tor_nss_countbytes_init(void)
#define tor_free(p)
Definition: malloc.h:52
Headers for util_malloc.c.
static PRInt32 countbytes_read_fn(PRFileDesc *fd, void *buf, PRInt32 amount)
static bool countbytes_initialized
PRFileDesc * tor_wrap_prfiledesc_with_byte_counter(PRFileDesc *stack)
Header for nss_countbytes.c, which lets us count the number of bytes actually written on a PRFileDesc...
tor_assert(buffer)
static PRStatus(* default_close_fn)(PRFileDesc *fd)
int tor_get_prfiledesc_byte_counts(PRFileDesc *fd, uint64_t *n_read_out, uint64_t *n_written_out)
static PRDescIdentity countbytes_layer_id
static PRInt32 countbytes_write_fn(PRFileDesc *fd, const void *buf, PRInt32 amount)
static PRStatus countbytes_close_fn(PRFileDesc *fd)
static tor_nss_bytecounts_t * get_counts(PRFileDesc *fd)
#define INC_WRITTEN(fd, n)
Macros to manage assertions, fatal and non-fatal.
struct tor_nss_bytecounts_t tor_nss_bytecounts_t