1 /* Copyright (c) 2014-2017, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
8 #define TOR_CHANNEL_INTERNAL_
13 #include "channeltls.h"
14 #include "connection_or.h"
16 /* For init/free stuff */
17 #include "scheduler.h"
20 /* Test suite stuff */
22 #include "fakechans.h"
24 /* The channeltls unit tests */
25 static void test_channeltls_create(void *arg
);
26 static void test_channeltls_num_bytes_queued(void *arg
);
27 static void test_channeltls_overhead_estimate(void *arg
);
29 /* Mocks used by channeltls unit tests */
30 static size_t tlschan_buf_datalen_mock(const buf_t
*buf
);
31 static or_connection_t
* tlschan_connection_or_connect_mock(
32 const tor_addr_t
*addr
,
35 const ed25519_public_key_t
*ed_id
,
36 channel_tls_t
*tlschan
);
37 static int tlschan_is_local_addr_mock(const tor_addr_t
*addr
);
39 /* Fake close method */
40 static void tlschan_fake_close_method(channel_t
*chan
);
42 /* Flags controlling behavior of channeltls unit test mocks */
43 static int tlschan_local
= 0;
44 static const buf_t
* tlschan_buf_datalen_mock_target
= NULL
;
45 static size_t tlschan_buf_datalen_mock_size
= 0;
47 /* Thing to cast to fake tor_tls_t * to appease assert_connection_ok() */
48 static int fake_tortls
= 0; /* Bleh... */
51 test_channeltls_create(void *arg
)
55 const char test_digest
[DIGEST_LEN
] = {
56 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
57 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14 };
61 /* Set up a fake address to fake-connect to */
62 test_addr
.family
= AF_INET
;
63 test_addr
.addr
.in_addr
.s_addr
= htonl(0x01020304);
65 /* For this test we always want the address to be treated as non-local */
67 /* Install is_local_addr() mock */
68 MOCK(is_local_addr
, tlschan_is_local_addr_mock
);
70 /* Install mock for connection_or_connect() */
71 MOCK(connection_or_connect
, tlschan_connection_or_connect_mock
);
74 ch
= channel_tls_connect(&test_addr
, 567, test_digest
, NULL
);
75 tt_ptr_op(ch
, OP_NE
, NULL
);
79 MOCK(scheduler_release_channel
, scheduler_release_channel_mock
);
81 * Use fake close method that doesn't try to do too much to fake
84 ch
->close
= tlschan_fake_close_method
;
85 channel_mark_for_close(ch
);
86 free_fake_channel(ch
);
87 UNMOCK(scheduler_release_channel
);
90 UNMOCK(connection_or_connect
);
91 UNMOCK(is_local_addr
);
97 test_channeltls_num_bytes_queued(void *arg
)
100 channel_t
*ch
= NULL
;
101 const char test_digest
[DIGEST_LEN
] = {
102 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
103 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14 };
104 channel_tls_t
*tlschan
= NULL
;
106 int fake_outbuf
= 0, n
;
110 /* Set up a fake address to fake-connect to */
111 test_addr
.family
= AF_INET
;
112 test_addr
.addr
.in_addr
.s_addr
= htonl(0x01020304);
114 /* For this test we always want the address to be treated as non-local */
116 /* Install is_local_addr() mock */
117 MOCK(is_local_addr
, tlschan_is_local_addr_mock
);
119 /* Install mock for connection_or_connect() */
120 MOCK(connection_or_connect
, tlschan_connection_or_connect_mock
);
123 ch
= channel_tls_connect(&test_addr
, 567, test_digest
, NULL
);
124 tt_ptr_op(ch
, OP_NE
, NULL
);
127 * Next, we have to test ch->num_bytes_queued, which is
128 * channel_tls_num_bytes_queued_method. We can't mock
129 * connection_get_outbuf_len() directly because it's static inline
130 * in connection.h, but we can mock buf_datalen().
133 tt_assert(ch
->num_bytes_queued
!= NULL
);
134 tlschan
= BASE_CHAN_TO_TLS(ch
);
135 tt_ptr_op(tlschan
, OP_NE
, NULL
);
136 if (TO_CONN(tlschan
->conn
)->outbuf
== NULL
) {
137 /* We need an outbuf to make sure buf_datalen() gets called */
139 TO_CONN(tlschan
->conn
)->outbuf
= buf_new();
141 tlschan_buf_datalen_mock_target
= TO_CONN(tlschan
->conn
)->outbuf
;
142 tlschan_buf_datalen_mock_size
= 1024;
143 MOCK(buf_datalen
, tlschan_buf_datalen_mock
);
144 len
= ch
->num_bytes_queued(ch
);
145 tt_int_op(len
, OP_EQ
, tlschan_buf_datalen_mock_size
);
147 * We also cover num_cells_writeable here; since wide_circ_ids = 0 on
148 * the fake tlschans, cell_network_size returns 512, and so with
149 * tlschan_buf_datalen_mock_size == 1024, we should be able to write
150 * ceil((OR_CONN_HIGHWATER - 1024) / 512) = ceil(OR_CONN_HIGHWATER / 512)
153 n
= ch
->num_cells_writeable(ch
);
154 tt_int_op(n
, OP_EQ
, CEIL_DIV(OR_CONN_HIGHWATER
, 512) - 2);
156 tlschan_buf_datalen_mock_target
= NULL
;
157 tlschan_buf_datalen_mock_size
= 0;
159 buf_free(TO_CONN(tlschan
->conn
)->outbuf
);
160 TO_CONN(tlschan
->conn
)->outbuf
= NULL
;
165 MOCK(scheduler_release_channel
, scheduler_release_channel_mock
);
167 * Use fake close method that doesn't try to do too much to fake
170 ch
->close
= tlschan_fake_close_method
;
171 channel_mark_for_close(ch
);
172 free_fake_channel(ch
);
173 UNMOCK(scheduler_release_channel
);
176 UNMOCK(connection_or_connect
);
177 UNMOCK(is_local_addr
);
183 test_channeltls_overhead_estimate(void *arg
)
185 tor_addr_t test_addr
;
186 channel_t
*ch
= NULL
;
187 const char test_digest
[DIGEST_LEN
] = {
188 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
189 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14 };
191 channel_tls_t
*tlschan
= NULL
;
195 /* Set up a fake address to fake-connect to */
196 test_addr
.family
= AF_INET
;
197 test_addr
.addr
.in_addr
.s_addr
= htonl(0x01020304);
199 /* For this test we always want the address to be treated as non-local */
201 /* Install is_local_addr() mock */
202 MOCK(is_local_addr
, tlschan_is_local_addr_mock
);
204 /* Install mock for connection_or_connect() */
205 MOCK(connection_or_connect
, tlschan_connection_or_connect_mock
);
208 ch
= channel_tls_connect(&test_addr
, 567, test_digest
, NULL
);
209 tt_ptr_op(ch
, OP_NE
, NULL
);
211 /* First case: silly low ratios should get clamped to 1.0 */
212 tlschan
= BASE_CHAN_TO_TLS(ch
);
213 tt_ptr_op(tlschan
, OP_NE
, NULL
);
214 tlschan
->conn
->bytes_xmitted
= 128;
215 tlschan
->conn
->bytes_xmitted_by_tls
= 64;
216 r
= ch
->get_overhead_estimate(ch
);
217 tt_assert(fabs(r
- 1.0) < 1E-12);
219 tlschan
->conn
->bytes_xmitted_by_tls
= 127;
220 r
= ch
->get_overhead_estimate(ch
);
221 tt_assert(fabs(r
- 1.0) < 1E-12);
223 /* Now middle of the range */
224 tlschan
->conn
->bytes_xmitted_by_tls
= 192;
225 r
= ch
->get_overhead_estimate(ch
);
226 tt_assert(fabs(r
- 1.5) < 1E-12);
228 /* Now above the 2.0 clamp */
229 tlschan
->conn
->bytes_xmitted_by_tls
= 257;
230 r
= ch
->get_overhead_estimate(ch
);
231 tt_assert(fabs(r
- 2.0) < 1E-12);
233 tlschan
->conn
->bytes_xmitted_by_tls
= 512;
234 r
= ch
->get_overhead_estimate(ch
);
235 tt_assert(fabs(r
- 2.0) < 1E-12);
239 MOCK(scheduler_release_channel
, scheduler_release_channel_mock
);
241 * Use fake close method that doesn't try to do too much to fake
244 ch
->close
= tlschan_fake_close_method
;
245 channel_mark_for_close(ch
);
246 free_fake_channel(ch
);
247 UNMOCK(scheduler_release_channel
);
250 UNMOCK(connection_or_connect
);
251 UNMOCK(is_local_addr
);
257 tlschan_buf_datalen_mock(const buf_t
*buf
)
259 if (buf
!= NULL
&& buf
== tlschan_buf_datalen_mock_target
) {
260 return tlschan_buf_datalen_mock_size
;
262 return buf_datalen__real(buf
);
266 static or_connection_t
*
267 tlschan_connection_or_connect_mock(const tor_addr_t
*addr
,
270 const ed25519_public_key_t
*ed_id
,
271 channel_tls_t
*tlschan
)
273 or_connection_t
*result
= NULL
;
274 (void) ed_id
; // XXXX Not yet used.
276 tt_ptr_op(addr
, OP_NE
, NULL
);
277 tt_uint_op(port
, OP_NE
, 0);
278 tt_ptr_op(digest
, OP_NE
, NULL
);
279 tt_ptr_op(tlschan
, OP_NE
, NULL
);
281 /* Make a fake orconn */
282 result
= tor_malloc_zero(sizeof(*result
));
283 result
->base_
.magic
= OR_CONNECTION_MAGIC
;
284 result
->base_
.state
= OR_CONN_STATE_OPEN
;
285 result
->base_
.type
= CONN_TYPE_OR
;
286 result
->base_
.socket_family
= addr
->family
;
287 result
->base_
.address
= tor_strdup("<fake>");
288 memcpy(&(result
->base_
.addr
), addr
, sizeof(tor_addr_t
));
289 result
->base_
.port
= port
;
290 memcpy(result
->identity_digest
, digest
, DIGEST_LEN
);
291 result
->chan
= tlschan
;
292 memcpy(&(result
->real_addr
), addr
, sizeof(tor_addr_t
));
293 result
->tls
= (tor_tls_t
*)((void *)(&fake_tortls
));
300 tlschan_fake_close_method(channel_t
*chan
)
302 channel_tls_t
*tlschan
= NULL
;
304 tt_ptr_op(chan
, OP_NE
, NULL
);
305 tt_int_op(chan
->magic
, OP_EQ
, TLS_CHAN_MAGIC
);
307 tlschan
= BASE_CHAN_TO_TLS(chan
);
308 tt_ptr_op(tlschan
, OP_NE
, NULL
);
310 /* Just free the fake orconn */
311 tor_free(tlschan
->conn
->base_
.address
);
312 tor_free(tlschan
->conn
);
314 channel_closed(chan
);
321 tlschan_is_local_addr_mock(const tor_addr_t
*addr
)
323 tt_ptr_op(addr
, OP_NE
, NULL
);
326 return tlschan_local
;
329 struct testcase_t channeltls_tests
[] = {
330 { "create", test_channeltls_create
, TT_FORK
, NULL
, NULL
},
331 { "num_bytes_queued", test_channeltls_num_bytes_queued
,
332 TT_FORK
, NULL
, NULL
},
333 { "overhead_estimate", test_channeltls_overhead_estimate
,
334 TT_FORK
, NULL
, NULL
},