Merge branch 'maint-0.4.8' into release-0.4.8
[tor.git] / src / test / test_relaycell.c
blob05e2b2e347a31266ef6d72573e2cce7f13ed6c12
1 /* Copyright (c) 2014-2021, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 /* Unit tests for handling different kinds of relay cell */
6 #define RELAY_PRIVATE
7 #define CIRCUITLIST_PRIVATE
8 #define CONNECTION_EDGE_PRIVATE
9 #define CONNECTION_PRIVATE
11 #include "core/or/or.h"
12 #include "core/mainloop/mainloop.h"
13 #include "app/config/config.h"
14 #include "core/mainloop/connection.h"
15 #include "lib/crypt_ops/crypto_cipher.h"
16 #include "lib/crypt_ops/crypto_rand.h"
17 #include "core/or/circuitbuild.h"
18 #include "core/or/circuitlist.h"
19 #include "core/or/connection_edge.h"
20 #include "core/or/sendme.h"
21 #include "core/or/relay.h"
22 #include "test/test.h"
23 #include "test/log_test_helpers.h"
25 #include "core/or/cell_st.h"
26 #include "core/or/crypt_path_st.h"
27 #include "core/or/entry_connection_st.h"
28 #include "core/or/origin_circuit_st.h"
29 #include "core/or/socks_request_st.h"
30 #include "core/or/half_edge_st.h"
32 #include "feature/client/circpathbias.h"
34 static int srm_ncalls;
35 static entry_connection_t *srm_conn;
36 static int srm_atype;
37 static size_t srm_alen;
38 static int srm_answer_is_set;
39 static uint8_t srm_answer[512];
40 static int srm_ttl;
41 static time_t srm_expires;
43 /* Mock replacement for connection_ap_hannshake_socks_resolved() */
44 static void
45 socks_resolved_mock(entry_connection_t *conn,
46 int answer_type,
47 size_t answer_len,
48 const uint8_t *answer,
49 int ttl,
50 time_t expires)
52 srm_ncalls++;
53 srm_conn = conn;
54 srm_atype = answer_type;
55 srm_alen = answer_len;
56 if (answer) {
57 memset(srm_answer, 0, sizeof(srm_answer));
58 memcpy(srm_answer, answer, answer_len < 512 ? answer_len : 512);
59 srm_answer_is_set = 1;
60 } else {
61 srm_answer_is_set = 0;
63 srm_ttl = ttl;
64 srm_expires = expires;
67 static int mum_ncalls;
68 static entry_connection_t *mum_conn;
69 static int mum_endreason;
71 /* Mock replacement for connection_mark_unattached_ap_() */
72 static void
73 mark_unattached_mock(entry_connection_t *conn, int endreason,
74 int line, const char *file)
76 ++mum_ncalls;
77 mum_conn = conn;
78 mum_endreason = endreason;
79 (void) line;
80 (void) file;
83 /* Helper: Return a newly allocated and initialized origin circuit with
84 * purpose and flags. A default HS identifier is set to an ed25519
85 * authentication key for introduction point. */
86 static origin_circuit_t *
87 helper_create_origin_circuit(int purpose, int flags)
89 origin_circuit_t *circ = NULL;
91 circ = origin_circuit_init(purpose, flags);
92 tor_assert(circ);
93 circ->cpath = tor_malloc_zero(sizeof(crypt_path_t));
94 circ->cpath->magic = CRYPT_PATH_MAGIC;
95 circ->cpath->state = CPATH_STATE_OPEN;
96 circ->cpath->package_window = circuit_initial_package_window();
97 circ->cpath->deliver_window = CIRCWINDOW_START;
98 circ->cpath->prev = circ->cpath;
99 /* Create a default HS identifier. */
100 circ->hs_ident = tor_malloc_zero(sizeof(hs_ident_circuit_t));
102 return circ;
105 static void
106 mock_connection_mark_unattached_ap_(entry_connection_t *conn, int endreason,
107 int line, const char *file)
109 (void) line;
110 (void) file;
111 conn->edge_.end_reason = endreason;
114 static void
115 mock_mark_circ_for_close(circuit_t *circ, int reason, int line,
116 const char *file)
118 (void)reason; (void)line; (void)file;
120 circ->marked_for_close = 1;
121 return;
124 static void
125 mock_mark_for_close(connection_t *conn,
126 int line, const char *file)
128 (void)line;
129 (void)file;
131 conn->marked_for_close = 1;
132 return;
135 static void
136 mock_start_reading(connection_t *conn)
138 (void)conn;
139 return;
142 static int
143 mock_send_command(streamid_t stream_id, circuit_t *circ,
144 uint8_t relay_command, const char *payload,
145 size_t payload_len, crypt_path_t *cpath_layer,
146 const char *filename, int lineno)
148 (void)stream_id; (void)circ;
149 (void)relay_command; (void)payload;
150 (void)payload_len; (void)cpath_layer;
151 (void)filename; (void)lineno;
153 return 0;
156 static entry_connection_t *
157 fake_entry_conn(origin_circuit_t *oncirc, streamid_t id)
159 edge_connection_t *edgeconn;
160 entry_connection_t *entryconn;
162 entryconn = entry_connection_new(CONN_TYPE_AP, AF_INET);
163 edgeconn = ENTRY_TO_EDGE_CONN(entryconn);
164 edgeconn->base_.state = AP_CONN_STATE_CONNECT_WAIT;
165 edgeconn->deliver_window = STREAMWINDOW_START;
166 edgeconn->package_window = STREAMWINDOW_START;
168 edgeconn->stream_id = id;
169 edgeconn->on_circuit = TO_CIRCUIT(oncirc);
170 edgeconn->cpath_layer = oncirc->cpath;
172 return entryconn;
175 #define PACK_CELL(id, cmd, body_s) do { \
176 memset(&cell, 0, sizeof(cell)); \
177 memset(&rh, 0, sizeof(rh)); \
178 memcpy(cell.payload+RELAY_HEADER_SIZE, (body_s), sizeof((body_s))-1); \
179 rh.length = sizeof((body_s))-1; \
180 rh.command = (cmd); \
181 rh.stream_id = (id); \
182 relay_header_pack((uint8_t*)&cell.payload, &rh); \
183 } while (0)
184 #define ASSERT_COUNTED_BW() do { \
185 tt_int_op(circ->n_delivered_read_circ_bw, OP_EQ, delivered+rh.length); \
186 tt_int_op(circ->n_overhead_read_circ_bw, OP_EQ, \
187 overhead+RELAY_PAYLOAD_SIZE-rh.length); \
188 delivered = circ->n_delivered_read_circ_bw; \
189 overhead = circ->n_overhead_read_circ_bw; \
190 } while (0)
191 #define ASSERT_UNCOUNTED_BW() do { \
192 tt_int_op(circ->n_delivered_read_circ_bw, OP_EQ, delivered); \
193 tt_int_op(circ->n_overhead_read_circ_bw, OP_EQ, overhead); \
194 } while (0)
196 static int
197 subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id)
199 cell_t cell;
200 relay_header_t rh;
201 edge_connection_t *edgeconn;
202 entry_connection_t *entryconn2=NULL;
203 entry_connection_t *entryconn3=NULL;
204 entry_connection_t *entryconn4=NULL;
205 int delivered = circ->n_delivered_read_circ_bw;
206 int overhead = circ->n_overhead_read_circ_bw;
208 /* Make new entryconns */
209 entryconn2 = fake_entry_conn(circ, init_id);
210 entryconn2->socks_request->has_finished = 1;
211 entryconn3 = fake_entry_conn(circ, init_id+1);
212 entryconn3->socks_request->has_finished = 1;
213 entryconn4 = fake_entry_conn(circ, init_id+2);
214 entryconn4->socks_request->has_finished = 1;
215 edgeconn = ENTRY_TO_EDGE_CONN(entryconn2);
216 edgeconn->package_window = 23;
217 edgeconn->base_.state = AP_CONN_STATE_OPEN;
219 int data_cells = edgeconn->deliver_window;
220 int sendme_cells = (STREAMWINDOW_START-edgeconn->package_window)
221 /STREAMWINDOW_INCREMENT;
222 ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
223 connection_edge_reached_eof(edgeconn);
225 /* Data cell not in the half-opened list */
226 PACK_CELL(4000, RELAY_COMMAND_DATA, "Data1234");
227 if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
228 pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
229 else
230 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
231 circ->cpath);
232 ASSERT_UNCOUNTED_BW();
234 /* Sendme cell not in the half-opened list */
235 PACK_CELL(4000, RELAY_COMMAND_SENDME, "Data1234");
236 if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
237 pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
238 else
239 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
240 circ->cpath);
241 ASSERT_UNCOUNTED_BW();
243 /* Connected cell not in the half-opened list */
244 PACK_CELL(4000, RELAY_COMMAND_CONNECTED, "Data1234");
245 if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
246 pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
247 else
248 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
249 circ->cpath);
250 ASSERT_UNCOUNTED_BW();
252 /* Resolved cell not in the half-opened list */
253 PACK_CELL(4000, RELAY_COMMAND_RESOLVED, "Data1234");
254 if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
255 pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
256 else
257 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
258 circ->cpath);
259 ASSERT_UNCOUNTED_BW();
261 /* Connected cell: not counted -- we were open */
262 edgeconn = ENTRY_TO_EDGE_CONN(entryconn2);
263 PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_CONNECTED, "Data1234");
264 if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
265 pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
266 else
267 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
268 circ->cpath);
269 ASSERT_UNCOUNTED_BW();
271 /* DATA cells up to limit */
272 while (data_cells > 0) {
273 ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
274 PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234");
275 if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
276 pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
277 else
278 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
279 circ->cpath);
280 ASSERT_COUNTED_BW();
281 data_cells--;
283 ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
284 PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234");
285 if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
286 pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
287 else
288 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
289 circ->cpath);
290 ASSERT_UNCOUNTED_BW();
292 /* SENDME cells up to limit */
293 while (sendme_cells > 0) {
294 ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
295 PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234");
296 if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
297 pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
298 else
299 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
300 circ->cpath);
301 ASSERT_COUNTED_BW();
302 sendme_cells--;
304 ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
305 PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234");
306 if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
307 pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
308 else
309 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
310 circ->cpath);
311 ASSERT_UNCOUNTED_BW();
313 /* Only one END cell */
314 ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
315 PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234");
316 if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
317 pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
318 else
319 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
320 circ->cpath);
321 ASSERT_COUNTED_BW();
323 ENTRY_TO_CONN(entryconn2)->marked_for_close = 0;
324 PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234");
325 if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
326 pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
327 else
328 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
329 circ->cpath);
330 ASSERT_UNCOUNTED_BW();
332 edgeconn = ENTRY_TO_EDGE_CONN(entryconn3);
333 edgeconn->base_.state = AP_CONN_STATE_OPEN;
334 ENTRY_TO_CONN(entryconn3)->marked_for_close = 0;
335 /* sendme cell on open entryconn with full window */
336 PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234");
337 int ret =
338 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
339 circ->cpath);
340 tt_int_op(ret, OP_EQ, -END_CIRC_REASON_TORPROTOCOL);
341 ASSERT_UNCOUNTED_BW();
343 /* connected cell on a after EOF */
344 ENTRY_TO_CONN(entryconn3)->marked_for_close = 0;
345 edgeconn->base_.state = AP_CONN_STATE_CONNECT_WAIT;
346 connection_edge_reached_eof(edgeconn);
347 PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_CONNECTED, "Data1234");
348 if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
349 pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
350 else
351 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
352 circ->cpath);
353 ASSERT_COUNTED_BW();
355 ENTRY_TO_CONN(entryconn3)->marked_for_close = 0;
356 PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_CONNECTED, "Data1234");
357 if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
358 pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
359 else
360 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
361 circ->cpath);
362 ASSERT_UNCOUNTED_BW();
364 /* DATA and SENDME after END cell */
365 ENTRY_TO_CONN(entryconn3)->marked_for_close = 0;
366 PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234");
367 if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
368 pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
369 else
370 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
371 circ->cpath);
372 ASSERT_COUNTED_BW();
374 ENTRY_TO_CONN(entryconn3)->marked_for_close = 0;
375 PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234");
376 ret =
377 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
378 circ->cpath);
379 tt_int_op(ret, OP_NE, -END_CIRC_REASON_TORPROTOCOL);
380 ASSERT_UNCOUNTED_BW();
382 ENTRY_TO_CONN(entryconn3)->marked_for_close = 0;
383 PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234");
384 if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
385 pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
386 else
387 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
388 circ->cpath);
389 ASSERT_UNCOUNTED_BW();
391 /* Resolved: 1 counted, more not */
392 edgeconn = ENTRY_TO_EDGE_CONN(entryconn4);
393 entryconn4->socks_request->command = SOCKS_COMMAND_RESOLVE;
394 edgeconn->base_.state = AP_CONN_STATE_RESOLVE_WAIT;
395 edgeconn->on_circuit = TO_CIRCUIT(circ);
396 ENTRY_TO_CONN(entryconn4)->marked_for_close = 0;
397 connection_edge_reached_eof(edgeconn);
399 ENTRY_TO_CONN(entryconn4)->marked_for_close = 0;
400 PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_RESOLVED,
401 "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00");
402 if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
403 pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
404 else
405 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
406 circ->cpath);
407 ASSERT_COUNTED_BW();
409 ENTRY_TO_CONN(entryconn4)->marked_for_close = 0;
410 PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_RESOLVED,
411 "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00");
412 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
413 circ->cpath);
414 ASSERT_UNCOUNTED_BW();
416 /* Data not counted after resolved */
417 ENTRY_TO_CONN(entryconn4)->marked_for_close = 0;
418 PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234");
419 if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
420 pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
421 else
422 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
423 circ->cpath);
424 ASSERT_UNCOUNTED_BW();
426 /* End not counted after resolved */
427 ENTRY_TO_CONN(entryconn4)->marked_for_close = 0;
428 PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234");
429 if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
430 pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
431 else
432 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
433 circ->cpath);
434 ASSERT_UNCOUNTED_BW();
436 connection_free_minimal(ENTRY_TO_CONN(entryconn2));
437 connection_free_minimal(ENTRY_TO_CONN(entryconn3));
438 connection_free_minimal(ENTRY_TO_CONN(entryconn4));
439 return 1;
440 done:
441 connection_free_minimal(ENTRY_TO_CONN(entryconn2));
442 connection_free_minimal(ENTRY_TO_CONN(entryconn3));
443 connection_free_minimal(ENTRY_TO_CONN(entryconn4));
444 return 0;
447 static int
448 halfstream_insert(origin_circuit_t *circ, edge_connection_t *edgeconn,
449 streamid_t *streams, int num, int random)
451 int inserted = 0;
453 /* Insert num random elements */
454 while (inserted < num) {
455 streamid_t id;
457 if (random)
458 id = (streamid_t)crypto_rand_int(65535)+1;
459 else
460 id = get_unique_stream_id_by_circ(circ);
462 edgeconn->stream_id = id;
464 /* Ensure it isn't there */
465 if (connection_half_edge_find_stream_id(circ->half_streams, id)) {
466 continue;
469 connection_half_edge_add(edgeconn, circ);
470 if (streams)
471 streams[inserted] = id;
472 inserted++;
475 return inserted;
478 static void
479 subtest_halfstream_insertremove(int num)
481 origin_circuit_t *circ =
482 helper_create_origin_circuit(CIRCUIT_PURPOSE_C_GENERAL, 0);
483 edge_connection_t *edgeconn;
484 entry_connection_t *entryconn;
485 streamid_t *streams = tor_malloc_zero(num*sizeof(streamid_t));
486 int i = 0;
488 circ->cpath->state = CPATH_STATE_AWAITING_KEYS;
489 circ->cpath->deliver_window = CIRCWINDOW_START;
491 entryconn = fake_entry_conn(circ, 23);
492 edgeconn = ENTRY_TO_EDGE_CONN(entryconn);
494 /* Explicitly test all operations on an absent stream list */
495 tt_int_op(connection_half_edge_is_valid_data(circ->half_streams,
496 23), OP_EQ, 0);
497 tt_int_op(connection_half_edge_is_valid_connected(circ->half_streams,
498 23), OP_EQ, 0);
499 tt_int_op(connection_half_edge_is_valid_sendme(circ->half_streams,
500 23), OP_EQ, 0);
501 tt_int_op(connection_half_edge_is_valid_resolved(circ->half_streams,
502 23), OP_EQ, 0);
503 tt_int_op(connection_half_edge_is_valid_end(circ->half_streams,
504 23), OP_EQ, 0);
506 /* Insert a duplicate element; verify that other elements absent;
507 * ensure removing it once works */
508 edgeconn->stream_id = 23;
509 connection_half_edge_add(edgeconn, circ);
510 connection_half_edge_add(edgeconn, circ);
511 connection_half_edge_add(edgeconn, circ);
513 /* Verify that other elements absent */
514 tt_int_op(connection_half_edge_is_valid_data(circ->half_streams,
515 22), OP_EQ, 0);
516 tt_int_op(connection_half_edge_is_valid_connected(circ->half_streams,
517 22), OP_EQ, 0);
518 tt_int_op(connection_half_edge_is_valid_sendme(circ->half_streams,
519 22), OP_EQ, 0);
520 tt_int_op(connection_half_edge_is_valid_resolved(circ->half_streams,
521 22), OP_EQ, 0);
522 tt_int_op(connection_half_edge_is_valid_end(circ->half_streams,
523 22), OP_EQ, 0);
525 tt_int_op(connection_half_edge_is_valid_data(circ->half_streams,
526 24), OP_EQ, 0);
527 tt_int_op(connection_half_edge_is_valid_connected(circ->half_streams,
528 24), OP_EQ, 0);
529 tt_int_op(connection_half_edge_is_valid_sendme(circ->half_streams,
530 24), OP_EQ, 0);
531 tt_int_op(connection_half_edge_is_valid_resolved(circ->half_streams,
532 24), OP_EQ, 0);
533 tt_int_op(connection_half_edge_is_valid_end(circ->half_streams,
534 24), OP_EQ, 0);
536 /* Verify we only remove it once */
537 tt_int_op(connection_half_edge_is_valid_end(circ->half_streams,
538 23), OP_EQ, 1);
539 tt_int_op(connection_half_edge_is_valid_end(circ->half_streams,
540 23), OP_EQ, 0);
542 halfstream_insert(circ, edgeconn, streams, num, 1);
544 /* Remove half of them */
545 for (i = 0; i < num/2; i++) {
546 tt_int_op(connection_half_edge_is_valid_end(circ->half_streams,
547 streams[i]),
548 OP_EQ, 1);
551 /* Verify first half of list is gone */
552 for (i = 0; i < num/2; i++) {
553 tt_ptr_op(connection_half_edge_find_stream_id(circ->half_streams,
554 streams[i]),
555 OP_EQ, NULL);
558 /* Verify second half of list is present */
559 for (; i < num; i++) {
560 tt_ptr_op(connection_half_edge_find_stream_id(circ->half_streams,
561 streams[i]),
562 OP_NE, NULL);
565 /* Remove other half. Verify list is empty. */
566 for (i = num/2; i < num; i++) {
567 tt_int_op(connection_half_edge_is_valid_end(circ->half_streams,
568 streams[i]),
569 OP_EQ, 1);
571 tt_int_op(smartlist_len(circ->half_streams), OP_EQ, 0);
573 /* Explicitly test all operations on an empty stream list */
574 tt_int_op(connection_half_edge_is_valid_data(circ->half_streams,
575 23), OP_EQ, 0);
576 tt_int_op(connection_half_edge_is_valid_connected(circ->half_streams,
577 23), OP_EQ, 0);
578 tt_int_op(connection_half_edge_is_valid_sendme(circ->half_streams,
579 23), OP_EQ, 0);
580 tt_int_op(connection_half_edge_is_valid_resolved(circ->half_streams,
581 23), OP_EQ, 0);
582 tt_int_op(connection_half_edge_is_valid_end(circ->half_streams,
583 23), OP_EQ, 0);
585 /* For valgrind, leave some around then free the circ */
586 halfstream_insert(circ, edgeconn, NULL, 10, 0);
588 done:
589 tor_free(streams);
590 circuit_free_(TO_CIRCUIT(circ));
591 connection_free_minimal(ENTRY_TO_CONN(entryconn));
594 static void
595 test_halfstream_insertremove(void *arg)
597 (void)arg;
599 /* Suppress the WARN message we generate in this test */
600 setup_full_capture_of_logs(LOG_WARN);
602 /* Test insertion and removal with a few different sizes */
603 subtest_halfstream_insertremove(10);
604 subtest_halfstream_insertremove(100);
605 subtest_halfstream_insertremove(1000);
608 static void
609 test_halfstream_wrap(void *arg)
611 origin_circuit_t *circ =
612 helper_create_origin_circuit(CIRCUIT_PURPOSE_C_GENERAL, 0);
613 edge_connection_t *edgeconn;
614 entry_connection_t *entryconn;
616 circ->cpath->state = CPATH_STATE_AWAITING_KEYS;
617 circ->cpath->deliver_window = CIRCWINDOW_START;
619 entryconn = fake_entry_conn(circ, 23);
620 edgeconn = ENTRY_TO_EDGE_CONN(entryconn);
622 (void)arg;
624 /* Suppress the WARN message we generate in this test */
625 setup_full_capture_of_logs(LOG_WARN);
626 MOCK(connection_mark_for_close_internal_, mock_mark_for_close);
628 /* Verify that get_unique_stream_id_by_circ() can wrap uint16_t */
629 circ->next_stream_id = 65530;
630 halfstream_insert(circ, edgeconn, NULL, 7, 0);
631 tt_int_op(circ->next_stream_id, OP_EQ, 2);
632 tt_int_op(smartlist_len(circ->half_streams), OP_EQ, 7);
634 /* Insert full-1 */
635 halfstream_insert(circ, edgeconn, NULL,
636 65534-smartlist_len(circ->half_streams), 0);
637 tt_int_op(smartlist_len(circ->half_streams), OP_EQ, 65534);
639 /* Verify that we can get_unique_stream_id_by_circ() successfully */
640 edgeconn->stream_id = get_unique_stream_id_by_circ(circ);
641 tt_int_op(edgeconn->stream_id, OP_NE, 0); /* 0 is failure */
643 /* Insert an opened stream on the circ with that id */
644 ENTRY_TO_CONN(entryconn)->marked_for_close = 0;
645 edgeconn->base_.state = AP_CONN_STATE_CONNECT_WAIT;
646 circ->p_streams = edgeconn;
648 /* Verify that get_unique_stream_id_by_circ() fails */
649 tt_int_op(get_unique_stream_id_by_circ(circ), OP_EQ, 0); /* 0 is failure */
651 /* eof the one opened stream. Verify it is now in half-closed */
652 tt_int_op(smartlist_len(circ->half_streams), OP_EQ, 65534);
653 connection_edge_reached_eof(edgeconn);
654 tt_int_op(smartlist_len(circ->half_streams), OP_EQ, 65535);
656 /* Verify get_unique_stream_id_by_circ() fails due to full half-closed */
657 circ->p_streams = NULL;
658 tt_int_op(get_unique_stream_id_by_circ(circ), OP_EQ, 0); /* 0 is failure */
660 done:
661 circuit_free_(TO_CIRCUIT(circ));
662 connection_free_minimal(ENTRY_TO_CONN(entryconn));
663 UNMOCK(connection_mark_for_close_internal_);
666 static void
667 test_circbw_relay(void *arg)
669 cell_t cell;
670 relay_header_t rh;
671 tor_addr_t addr;
672 edge_connection_t *edgeconn;
673 entry_connection_t *entryconn1=NULL;
674 origin_circuit_t *circ;
675 int delivered = 0;
676 int overhead = 0;
678 (void)arg;
680 MOCK(connection_mark_unattached_ap_, mock_connection_mark_unattached_ap_);
681 MOCK(connection_start_reading, mock_start_reading);
682 MOCK(connection_mark_for_close_internal_, mock_mark_for_close);
683 MOCK(relay_send_command_from_edge_, mock_send_command);
684 MOCK(circuit_mark_for_close_, mock_mark_circ_for_close);
686 circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_C_GENERAL, 0);
687 circ->cpath->state = CPATH_STATE_AWAITING_KEYS;
688 circ->cpath->deliver_window = CIRCWINDOW_START;
690 entryconn1 = fake_entry_conn(circ, 1);
691 edgeconn = ENTRY_TO_EDGE_CONN(entryconn1);
693 /* Stream id 0: Not counted */
694 PACK_CELL(0, RELAY_COMMAND_END, "Data1234");
695 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
696 circ->cpath);
697 ASSERT_UNCOUNTED_BW();
699 /* Stream id 1: Counted */
700 PACK_CELL(1, RELAY_COMMAND_END, "Data1234");
701 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
702 circ->cpath);
703 ASSERT_COUNTED_BW();
705 /* Properly formatted connect cell: counted */
706 PACK_CELL(1, RELAY_COMMAND_CONNECTED, "Data1234");
707 tor_addr_parse(&addr, "30.40.50.60");
708 rh.length = connected_cell_format_payload(cell.payload+RELAY_HEADER_SIZE,
709 &addr, 1024);
710 relay_header_pack((uint8_t*)&cell.payload, &rh); \
711 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
712 circ->cpath);
713 ASSERT_COUNTED_BW();
715 /* Properly formatted resolved cell in correct state: counted */
716 edgeconn->base_.state = AP_CONN_STATE_RESOLVE_WAIT;
717 entryconn1->socks_request->command = SOCKS_COMMAND_RESOLVE;
718 edgeconn->on_circuit = TO_CIRCUIT(circ);
719 PACK_CELL(1, RELAY_COMMAND_RESOLVED,
720 "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00");
721 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
722 circ->cpath);
723 ASSERT_COUNTED_BW();
725 edgeconn->base_.state = AP_CONN_STATE_OPEN;
726 entryconn1->socks_request->has_finished = 1;
728 /* Connected cell after open: not counted */
729 PACK_CELL(1, RELAY_COMMAND_CONNECTED, "Data1234");
730 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
731 circ->cpath);
732 ASSERT_UNCOUNTED_BW();
734 /* Resolved cell after open: not counted */
735 PACK_CELL(1, RELAY_COMMAND_RESOLVED, "Data1234");
736 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
737 circ->cpath);
738 ASSERT_UNCOUNTED_BW();
740 /* Drop cell: not counted */
741 PACK_CELL(1, RELAY_COMMAND_DROP, "Data1234");
742 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
743 circ->cpath);
744 ASSERT_UNCOUNTED_BW();
746 /* Data cell on stream 0: not counted */
747 PACK_CELL(0, RELAY_COMMAND_DATA, "Data1234");
748 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
749 circ->cpath);
750 ASSERT_UNCOUNTED_BW();
752 /* Data cell on open connection: counted */
753 ENTRY_TO_CONN(entryconn1)->marked_for_close = 0;
754 PACK_CELL(1, RELAY_COMMAND_DATA, "Data1234");
755 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
756 circ->cpath);
757 ASSERT_COUNTED_BW();
759 /* Empty Data cell on open connection: not counted */
760 ENTRY_TO_CONN(entryconn1)->marked_for_close = 0;
761 PACK_CELL(1, RELAY_COMMAND_DATA, "");
762 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
763 circ->cpath);
764 ASSERT_UNCOUNTED_BW();
766 /* Sendme on valid stream: counted */
767 edgeconn->package_window -= STREAMWINDOW_INCREMENT;
768 PACK_CELL(1, RELAY_COMMAND_SENDME, "Data1234");
769 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
770 circ->cpath);
771 ASSERT_COUNTED_BW();
773 /* Sendme on valid stream with full window: not counted */
774 PACK_CELL(1, RELAY_COMMAND_SENDME, "Data1234");
775 edgeconn->package_window = STREAMWINDOW_START;
776 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
777 circ->cpath);
778 ASSERT_UNCOUNTED_BW();
780 /* Sendme on unknown stream: not counted */
781 PACK_CELL(1, RELAY_COMMAND_SENDME, "Data1234");
782 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
783 circ->cpath);
784 ASSERT_UNCOUNTED_BW();
786 /* Sendme on circuit with full window: not counted */
787 PACK_CELL(0, RELAY_COMMAND_SENDME, "Data1234");
788 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
789 circ->cpath);
790 ASSERT_UNCOUNTED_BW();
792 /* Sendme on circuit with non-full window: counted */
793 PACK_CELL(0, RELAY_COMMAND_SENDME, "");
794 /* Recording a cell, the window is updated after decryption so off by one in
795 * order to record and then we process it with the proper window. */
796 circ->cpath->package_window = 901;
797 sendme_record_cell_digest_on_circ(TO_CIRCUIT(circ), circ->cpath);
798 circ->cpath->package_window = 900;
799 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
800 circ->cpath);
801 ASSERT_COUNTED_BW();
803 /* Invalid extended cell: not counted */
804 PACK_CELL(1, RELAY_COMMAND_EXTENDED2, "Data1234");
805 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
806 circ->cpath);
807 ASSERT_UNCOUNTED_BW();
809 /* Invalid extended cell: not counted */
810 PACK_CELL(1, RELAY_COMMAND_EXTENDED, "Data1234");
811 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
812 circ->cpath);
813 ASSERT_UNCOUNTED_BW();
815 /* Invalid HS cell: not counted */
816 PACK_CELL(1, RELAY_COMMAND_ESTABLISH_INTRO, "Data1234");
817 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
818 circ->cpath);
819 ASSERT_UNCOUNTED_BW();
821 /* "Valid" HS cell in expected state: counted */
822 TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_C_ESTABLISH_REND;
823 PACK_CELL(1, RELAY_COMMAND_RENDEZVOUS_ESTABLISHED, "Data1234");
824 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
825 circ->cpath);
826 ASSERT_COUNTED_BW();
828 /* End cell on non-closed connection: counted */
829 PACK_CELL(1, RELAY_COMMAND_END, "Data1234");
830 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn,
831 circ->cpath);
832 ASSERT_COUNTED_BW();
834 /* End cell on connection that already got one: not counted */
835 PACK_CELL(1, RELAY_COMMAND_END, "Data1234");
836 connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL,
837 circ->cpath);
838 ASSERT_UNCOUNTED_BW();
840 /* Simulate closed stream on entryconn, then test: */
841 if (!subtest_circbw_halfclosed(circ, 2))
842 goto done;
844 circ->base_.purpose = CIRCUIT_PURPOSE_PATH_BIAS_TESTING;
845 if (!subtest_circbw_halfclosed(circ, 6))
846 goto done;
848 /* Path bias: truncated */
849 tt_int_op(circ->base_.marked_for_close, OP_EQ, 0);
850 PACK_CELL(0, RELAY_COMMAND_TRUNCATED, "Data1234");
851 pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell);
852 tt_int_op(circ->base_.marked_for_close, OP_EQ, 1);
854 done:
855 UNMOCK(connection_start_reading);
856 UNMOCK(connection_mark_unattached_ap_);
857 UNMOCK(connection_mark_for_close_internal_);
858 UNMOCK(relay_send_command_from_edge_);
859 UNMOCK(circuit_mark_for_close_);
860 circuit_free_(TO_CIRCUIT(circ));
861 connection_free_minimal(ENTRY_TO_CONN(entryconn1));
864 /* Tests for connection_edge_process_resolved_cell().
866 The point of ..process_resolved_cell() is to handle an incoming cell
867 on an entry connection, and call connection_mark_unattached_ap() and/or
868 connection_ap_handshake_socks_resolved().
870 static void
871 test_relaycell_resolved(void *arg)
873 entry_connection_t *entryconn;
874 edge_connection_t *edgeconn;
875 cell_t cell;
876 relay_header_t rh;
877 int r;
878 or_options_t *options = get_options_mutable();
880 #define SET_CELL(s) do { \
881 memset(&cell, 0, sizeof(cell)); \
882 memset(&rh, 0, sizeof(rh)); \
883 memcpy(cell.payload + RELAY_HEADER_SIZE, (s), sizeof((s))-1); \
884 rh.length = sizeof((s))-1; \
885 rh.command = RELAY_COMMAND_RESOLVED; \
886 } while (0)
887 #define MOCK_RESET() do { \
888 srm_ncalls = mum_ncalls = 0; \
889 } while (0)
890 #define ASSERT_MARK_CALLED(reason) do { \
891 tt_int_op(mum_ncalls, OP_EQ, 1); \
892 tt_ptr_op(mum_conn, OP_EQ, entryconn); \
893 tt_int_op(mum_endreason, OP_EQ, (reason)); \
894 } while (0)
895 #define ASSERT_RESOLVED_CALLED(atype, answer, ttl, expires) do { \
896 tt_int_op(srm_ncalls, OP_EQ, 1); \
897 tt_ptr_op(srm_conn, OP_EQ, entryconn); \
898 tt_int_op(srm_atype, OP_EQ, (atype)); \
899 if ((answer) != NULL) { \
900 tt_int_op(srm_alen, OP_EQ, sizeof(answer)-1); \
901 tt_int_op(srm_alen, OP_LT, 512); \
902 tt_int_op(srm_answer_is_set, OP_EQ, 1); \
903 tt_mem_op(srm_answer, OP_EQ, answer, sizeof(answer)-1); \
904 } else { \
905 tt_int_op(srm_answer_is_set, OP_EQ, 0); \
907 tt_int_op(srm_ttl, OP_EQ, ttl); \
908 tt_i64_op(srm_expires, OP_EQ, expires); \
909 } while (0)
911 (void)arg;
913 MOCK(connection_mark_unattached_ap_, mark_unattached_mock);
914 MOCK(connection_ap_handshake_socks_resolved, socks_resolved_mock);
916 options->ClientDNSRejectInternalAddresses = 0;
918 SET_CELL(/* IPv4: 127.0.1.2, ttl 256 */
919 "\x04\x04\x7f\x00\x01\x02\x00\x00\x01\x00"
920 /* IPv4: 18.0.0.1, ttl 512 */
921 "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00"
922 /* IPv6: 2003::3, ttl 1024 */
923 "\x06\x10"
924 "\x20\x02\x00\x00\x00\x00\x00\x00"
925 "\x00\x00\x00\x00\x00\x00\x00\x03"
926 "\x00\x00\x04\x00");
928 entryconn = entry_connection_new(CONN_TYPE_AP, AF_INET);
929 edgeconn = ENTRY_TO_EDGE_CONN(entryconn);
931 /* Try with connection in non-RESOLVE_WAIT state: cell gets ignored */
932 MOCK_RESET();
933 r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh);
934 tt_int_op(r, OP_EQ, 0);
935 tt_int_op(srm_ncalls, OP_EQ, 0);
936 tt_int_op(mum_ncalls, OP_EQ, 0);
938 /* Now put it in the right state. */
939 ENTRY_TO_CONN(entryconn)->state = AP_CONN_STATE_RESOLVE_WAIT;
940 entryconn->socks_request->command = SOCKS_COMMAND_RESOLVE;
941 entryconn->entry_cfg.ipv4_traffic = 1;
942 entryconn->entry_cfg.ipv6_traffic = 1;
943 entryconn->entry_cfg.prefer_ipv6 = 0;
945 /* We prefer ipv4, so we should get the first ipv4 answer */
946 MOCK_RESET();
947 r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh);
948 tt_int_op(r, OP_EQ, 0);
949 ASSERT_MARK_CALLED(END_STREAM_REASON_DONE|
950 END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
951 ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_IPV4, "\x7f\x00\x01\x02", 256, -1);
953 /* But we may be discarding private answers. */
954 MOCK_RESET();
955 options->ClientDNSRejectInternalAddresses = 1;
956 r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh);
957 tt_int_op(r, OP_EQ, 0);
958 ASSERT_MARK_CALLED(END_STREAM_REASON_DONE|
959 END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
960 ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_IPV4, "\x12\x00\x00\x01", 512, -1);
962 /* now prefer ipv6, and get the first ipv6 answer */
963 entryconn->entry_cfg.prefer_ipv6 = 1;
964 MOCK_RESET();
965 r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh);
966 tt_int_op(r, OP_EQ, 0);
967 ASSERT_MARK_CALLED(END_STREAM_REASON_DONE|
968 END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
969 ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_IPV6,
970 "\x20\x02\x00\x00\x00\x00\x00\x00"
971 "\x00\x00\x00\x00\x00\x00\x00\x03",
972 1024, -1);
974 /* With a cell that only has IPv4, we report IPv4 even if we prefer IPv6 */
975 MOCK_RESET();
976 SET_CELL("\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00");
977 r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh);
978 tt_int_op(r, OP_EQ, 0);
979 ASSERT_MARK_CALLED(END_STREAM_REASON_DONE|
980 END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
981 ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_IPV4, "\x12\x00\x00\x01", 512, -1);
983 /* But if we don't allow IPv4, we report nothing if the cell contains only
984 * ipv4 */
985 MOCK_RESET();
986 entryconn->entry_cfg.ipv4_traffic = 0;
987 r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh);
988 tt_int_op(r, OP_EQ, 0);
989 ASSERT_MARK_CALLED(END_STREAM_REASON_DONE|
990 END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
991 ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_ERROR, NULL, -1, -1);
993 /* If we wanted hostnames, we report nothing, since we only had IPs. */
994 MOCK_RESET();
995 entryconn->entry_cfg.ipv4_traffic = 1;
996 entryconn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR;
997 r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh);
998 tt_int_op(r, OP_EQ, 0);
999 ASSERT_MARK_CALLED(END_STREAM_REASON_DONE|
1000 END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
1001 ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_ERROR, NULL, -1, -1);
1003 /* A hostname cell is fine though. */
1004 MOCK_RESET();
1005 SET_CELL("\x00\x0fwww.example.com\x00\x01\x00\x00");
1006 r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh);
1007 tt_int_op(r, OP_EQ, 0);
1008 ASSERT_MARK_CALLED(END_STREAM_REASON_DONE|
1009 END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
1010 ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_HOSTNAME, "www.example.com", 65536, -1);
1012 /* error on malformed cell */
1013 MOCK_RESET();
1014 entryconn->socks_request->command = SOCKS_COMMAND_RESOLVE;
1015 SET_CELL("\x04\x04\x01\x02\x03\x04"); /* no ttl */
1016 r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh);
1017 tt_int_op(r, OP_EQ, 0);
1018 ASSERT_MARK_CALLED(END_STREAM_REASON_TORPROTOCOL);
1019 tt_int_op(srm_ncalls, OP_EQ, 0);
1021 /* error on all addresses private */
1022 MOCK_RESET();
1023 SET_CELL(/* IPv4: 127.0.1.2, ttl 256 */
1024 "\x04\x04\x7f\x00\x01\x02\x00\x00\x01\x00"
1025 /* IPv4: 192.168.1.1, ttl 256 */
1026 "\x04\x04\xc0\xa8\x01\x01\x00\x00\x01\x00");
1027 r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh);
1028 tt_int_op(r, OP_EQ, 0);
1029 ASSERT_MARK_CALLED(END_STREAM_REASON_TORPROTOCOL);
1030 ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_ERROR_TRANSIENT, NULL, 0, TIME_MAX);
1032 /* Legit error code */
1033 MOCK_RESET();
1034 SET_CELL("\xf0\x15" "quiet and meaningless" "\x00\x00\x0f\xff");
1035 r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh);
1036 tt_int_op(r, OP_EQ, 0);
1037 ASSERT_MARK_CALLED(END_STREAM_REASON_DONE|
1038 END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
1039 ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_ERROR_TRANSIENT, NULL, -1, -1);
1041 done:
1042 UNMOCK(connection_mark_unattached_ap_);
1043 UNMOCK(connection_ap_handshake_socks_resolved);
1046 struct testcase_t relaycell_tests[] = {
1047 { "resolved", test_relaycell_resolved, TT_FORK, NULL, NULL },
1048 { "circbw", test_circbw_relay, TT_FORK, NULL, NULL },
1049 { "halfstream", test_halfstream_insertremove, TT_FORK, NULL, NULL },
1050 { "streamwrap", test_halfstream_wrap, TT_FORK, NULL, NULL },
1051 END_OF_TESTCASES