RD_BOOL rdpsnd_init(char *optarg) { struct audio_driver *pos; char *driver = NULL, *options = NULL; drivers = NULL; packet.data = (uint8 *) xmalloc(65536); packet.p = packet.end = packet.data; packet.size = 0; rdpsnd_channel = channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP, rdpsnd_process); rdpsnddbg_channel = channel_register("snddbg", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP, rdpsnddbg_process); if ((rdpsnd_channel == NULL) || (rdpsnddbg_channel == NULL)) { error("channel_register\n"); return False; } rdpsnd_queue_init(); if (optarg != NULL && strlen(optarg) > 0) { driver = options = optarg; while (*options != '\0' && *options != ':') options++; if (*options == ':') { *options = '\0'; options++; } if (*options == '\0') options = NULL; } rdpsnd_register_drivers(options); if (!driver) return True; pos = drivers; while (pos != NULL) { if (!strcmp(pos->name, driver)) { DEBUG(("selected %s\n", pos->name)); current_driver = pos; return True; } pos = pos->next; } return False; }
/* Initialize this module: Register the lspci channel */ BOOL lspci_init(void) { lspci_channel = channel_register("lspci", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP, lspci_process); return (lspci_channel != NULL); }
/* Initialize this module: Register the lspci channel */ BOOL lspci_init(RDPCLIENT * This) { lspci_channel = channel_register(This, "lspci", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP, lspci_process); return (lspci_channel != NULL); }
BOOL rdpsnd_init(void) { rdpsnd_channel = channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP, rdpsnd_process); return (rdpsnd_channel != NULL); }
BOOL cliprdr_init(void) { cliprdr_channel = channel_register("cliprdr", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP | CHANNEL_OPTION_COMPRESS_RDP | CHANNEL_OPTION_SHOW_PROTOCOL, cliprdr_process); return (cliprdr_channel != NULL); }
RD_BOOL rdpdr_init() { rdpdr_channel = channel_register("rdpdr", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_COMPRESS_RDP, rdpdr_process); return (rdpdr_channel != NULL); }
BOOL rdpdr_init(RDPCLIENT * This) { if (This->num_devices > 0) { This->rdpdr.channel = channel_register(This, "rdpdr", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_COMPRESS_RDP, rdpdr_process); } return (This->rdpdr.channel != NULL); }
RD_BOOL rdpusb_init(void) { bool fUseUsbfs; if (RT_SUCCESS(USBProxyLinuxChooseMethod(&fUseUsbfs, &g_pcszDevicesRoot))) { g_fUseSysfs = !fUseUsbfs; rdpusb_channel = channel_register("vrdpusb", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP, rdpusb_process); return (rdpusb_channel != NULL); } return false; }
/* * Request ads * The response is plain XML * */ int cmd_requestad (SESSION * session, unsigned char ad_type) { CHANNEL *ch; int ret; char buf[100]; struct buf* b = buf_new(); _snprintf(buf, sizeof(buf), "RequestAd-with-type-%d", ad_type); ch = channel_register (buf, dump_generic, NULL); DSFYDEBUG ("allocated channel %d, retrieving ads with type id %d\n", ch->channel_id, ad_type); buf_append_u16(b, ch->channel_id); buf_append_u8(b, ad_type); ret = packet_write (session, CMD_REQUESTAD, b->ptr, b->len); DSFYDEBUG ("packet_write() returned %d\n", ret); buf_free(b); return ret; }
static void test_channel_lifecycle_2(void *arg) { channel_t *ch = NULL; (void)arg; /* Mock these for the whole lifecycle test */ MOCK(scheduler_channel_doesnt_want_writes, scheduler_channel_doesnt_want_writes_mock); MOCK(scheduler_release_channel, scheduler_release_channel_mock); /* Accept cells to lower layer */ test_chan_accept_cells = 1; ch = new_fake_channel(); tt_assert(ch); /* Start it off in OPENING */ ch->state = CHANNEL_STATE_OPENING; /* Try to register it */ channel_register(ch); tt_assert(ch->registered); /* Try to close it */ channel_mark_for_close(ch); tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSING); /* Finish closing it */ chan_test_finish_close(ch); tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSED); channel_run_cleanup(); ch = NULL; /* Now try OPENING->OPEN->CLOSING->ERROR */ ch = new_fake_channel(); tt_assert(ch); ch->state = CHANNEL_STATE_OPENING; channel_register(ch); tt_assert(ch->registered); /* Finish opening it */ channel_change_state_open(ch); /* Error exit from lower layer */ chan_test_error(ch); tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSING); chan_test_finish_close(ch); tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_ERROR); channel_run_cleanup(); ch = NULL; /* OPENING->OPEN->MAINT->CLOSING->CLOSED close from maintenance state */ ch = new_fake_channel(); tt_assert(ch); ch->state = CHANNEL_STATE_OPENING; channel_register(ch); tt_assert(ch->registered); /* Finish opening it */ channel_change_state_open(ch); tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_OPEN); /* Go to maintenance state */ channel_change_state(ch, CHANNEL_STATE_MAINT); tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_MAINT); /* Lower layer close */ channel_mark_for_close(ch); tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSING); /* Finish */ chan_test_finish_close(ch); tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSED); channel_run_cleanup(); ch = NULL; /* * OPENING->OPEN->MAINT->CLOSING->CLOSED lower-layer close during * maintenance state */ ch = new_fake_channel(); tt_assert(ch); ch->state = CHANNEL_STATE_OPENING; channel_register(ch); tt_assert(ch->registered); /* Finish opening it */ channel_change_state_open(ch); tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_OPEN); /* Go to maintenance state */ channel_change_state(ch, CHANNEL_STATE_MAINT); tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_MAINT); /* Lower layer close */ channel_close_from_lower_layer(ch); tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSING); /* Finish */ chan_test_finish_close(ch); tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSED); channel_run_cleanup(); ch = NULL; /* OPENING->OPEN->MAINT->CLOSING->ERROR */ ch = new_fake_channel(); tt_assert(ch); ch->state = CHANNEL_STATE_OPENING; channel_register(ch); tt_assert(ch->registered); /* Finish opening it */ channel_change_state_open(ch); tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_OPEN); /* Go to maintenance state */ channel_change_state(ch, CHANNEL_STATE_MAINT); tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_MAINT); /* Lower layer close */ chan_test_error(ch); tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSING); /* Finish */ chan_test_finish_close(ch); tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_ERROR); channel_run_cleanup(); ch = NULL; /* Shut down channels */ channel_free_all(); done: tor_free(ch); UNMOCK(scheduler_channel_doesnt_want_writes); UNMOCK(scheduler_release_channel); return; }
static void test_channel_lifecycle(void *arg) { channel_t *ch1 = NULL, *ch2 = NULL; packed_cell_t *p_cell = NULL; int old_count, init_doesnt_want_writes_count; int init_releases_count; (void)arg; /* Mock these for the whole lifecycle test */ MOCK(scheduler_channel_doesnt_want_writes, scheduler_channel_doesnt_want_writes_mock); MOCK(scheduler_release_channel, scheduler_release_channel_mock); /* Cache some initial counter values */ init_doesnt_want_writes_count = test_doesnt_want_writes_count; init_releases_count = test_releases_count; /* Accept cells to lower layer */ test_chan_accept_cells = 1; ch1 = new_fake_channel(); tt_assert(ch1); /* Start it off in OPENING */ ch1->state = CHANNEL_STATE_OPENING; /* Try to register it */ channel_register(ch1); tt_assert(ch1->registered); /* Try to write a cell through (should queue) */ p_cell = packed_cell_new(); old_count = test_cells_written; channel_write_packed_cell(ch1, p_cell); tt_int_op(old_count, OP_EQ, test_cells_written); /* Move it to OPEN and flush */ channel_change_state_open(ch1); /* Get another one */ ch2 = new_fake_channel(); tt_assert(ch2); ch2->state = CHANNEL_STATE_OPENING; /* Register */ channel_register(ch2); tt_assert(ch2->registered); /* Check counters */ tt_int_op(test_doesnt_want_writes_count, OP_EQ, init_doesnt_want_writes_count); tt_int_op(test_releases_count, OP_EQ, init_releases_count); /* Move ch1 to MAINT */ channel_change_state(ch1, CHANNEL_STATE_MAINT); tt_int_op(test_doesnt_want_writes_count, OP_EQ, init_doesnt_want_writes_count + 1); tt_int_op(test_releases_count, OP_EQ, init_releases_count); /* Move ch2 to OPEN */ channel_change_state_open(ch2); tt_int_op(test_doesnt_want_writes_count, OP_EQ, init_doesnt_want_writes_count + 1); tt_int_op(test_releases_count, OP_EQ, init_releases_count); /* Move ch1 back to OPEN */ channel_change_state_open(ch1); tt_int_op(test_doesnt_want_writes_count, OP_EQ, init_doesnt_want_writes_count + 1); tt_int_op(test_releases_count, OP_EQ, init_releases_count); /* Mark ch2 for close */ channel_mark_for_close(ch2); tt_int_op(ch2->state, OP_EQ, CHANNEL_STATE_CLOSING); tt_int_op(test_doesnt_want_writes_count, OP_EQ, init_doesnt_want_writes_count + 1); tt_int_op(test_releases_count, OP_EQ, init_releases_count + 1); /* Shut down channels */ channel_free_all(); ch1 = ch2 = NULL; tt_int_op(test_doesnt_want_writes_count, OP_EQ, init_doesnt_want_writes_count + 1); /* channel_free() calls scheduler_release_channel() */ tt_int_op(test_releases_count, OP_EQ, init_releases_count + 4); done: free_fake_channel(ch1); free_fake_channel(ch2); UNMOCK(scheduler_channel_doesnt_want_writes); UNMOCK(scheduler_release_channel); }
/* Test inbound cell. The callstack is: * channel_process_cell() * -> chan->cell_handler() * * This test is about checking if we can process an inbound cell down to the * channel handler. */ static void test_channel_inbound_cell(void *arg) { channel_t *chan = NULL; cell_t *cell = NULL; int old_count; (void) arg; /* The channel will be freed so we need to hijack this so the scheduler * doesn't get confused. */ MOCK(scheduler_release_channel, scheduler_release_channel_mock); /* Accept cells to lower layer */ test_chan_accept_cells = 1; chan = new_fake_channel(); tt_assert(chan); /* Start it off in OPENING */ chan->state = CHANNEL_STATE_OPENING; /* Try to register it */ channel_register(chan); tt_int_op(chan->registered, OP_EQ, 1); /* Open it */ channel_change_state_open(chan); tt_int_op(chan->state, OP_EQ, CHANNEL_STATE_OPEN); tt_int_op(chan->has_been_open, OP_EQ, 1); /* Receive a cell now. */ cell = tor_malloc_zero(sizeof(*cell)); make_fake_cell(cell); old_count = test_chan_fixed_cells_recved; channel_process_cell(chan, cell); tt_int_op(test_chan_fixed_cells_recved, OP_EQ, old_count); tt_assert(monotime_coarse_is_zero(&chan->timestamp_xfer)); tt_u64_op(chan->timestamp_active, OP_EQ, 0); tt_u64_op(chan->timestamp_recv, OP_EQ, 0); /* Setup incoming cell handlers. We don't care about var cell, the channel * layers is not handling those. */ channel_set_cell_handlers(chan, chan_test_cell_handler, NULL); tt_ptr_op(chan->cell_handler, OP_EQ, chan_test_cell_handler); /* Now process the cell, we should see it. */ old_count = test_chan_fixed_cells_recved; channel_process_cell(chan, cell); tt_int_op(test_chan_fixed_cells_recved, OP_EQ, old_count + 1); /* We should have a series of timestamp set. */ tt_assert(!monotime_coarse_is_zero(&chan->timestamp_xfer)); tt_u64_op(chan->timestamp_active, OP_NE, 0); tt_u64_op(chan->timestamp_recv, OP_NE, 0); tt_assert(monotime_coarse_is_zero(&chan->next_padding_time)); tt_u64_op(chan->n_cells_recved, OP_EQ, 1); tt_u64_op(chan->n_bytes_recved, OP_EQ, get_cell_network_size(0)); /* Close it */ old_count = test_close_called; channel_mark_for_close(chan); tt_int_op(chan->state, OP_EQ, CHANNEL_STATE_CLOSING); tt_int_op(chan->reason_for_closing, OP_EQ, CHANNEL_CLOSE_REQUESTED); tt_int_op(test_close_called, OP_EQ, old_count + 1); /* This closes the channe so it calls in the scheduler, make sure of it. */ old_count = test_releases_count; chan_test_finish_close(chan); tt_int_op(test_releases_count, OP_EQ, old_count + 1); tt_int_op(chan->state, OP_EQ, CHANNEL_STATE_CLOSED); /* The channel will be free, lets make sure it is not accessible. */ uint64_t chan_id = chan->global_identifier; tt_ptr_op(channel_find_by_global_id(chan_id), OP_EQ, chan); channel_run_cleanup(); chan = channel_find_by_global_id(chan_id); tt_assert(chan == NULL); done: tor_free(cell); UNMOCK(scheduler_release_channel); }
/* Test outbound cell. The callstack is: * channel_flush_some_cells() * -> channel_flush_from_first_active_circuit() * -> channel_write_packed_cell() * -> write_packed_cell() * -> chan->write_packed_cell() fct ptr. * * This test goes from a cell in a circuit up to the channel write handler * that should put them on the connection outbuf. */ static void test_channel_outbound_cell(void *arg) { int old_count; channel_t *chan = NULL; packed_cell_t *p_cell = NULL, *p_cell2 = NULL; origin_circuit_t *circ = NULL; cell_queue_t *queue; (void) arg; /* Set the test time to be mocked, since this test assumes that no * time will pass, ewma values will not need to be re-scaled, and so on */ monotime_enable_test_mocking(); monotime_set_mock_time_nsec(U64_LITERAL(1000000000) * 12345); cmux_ewma_set_options(NULL,NULL); /* The channel will be freed so we need to hijack this so the scheduler * doesn't get confused. */ MOCK(scheduler_release_channel, scheduler_release_channel_mock); /* Accept cells to lower layer */ test_chan_accept_cells = 1; /* Setup a valid circuit to queue a cell. */ circ = origin_circuit_new(); tt_assert(circ); /* Circuit needs an origin purpose to be considered origin. */ TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_C_GENERAL; TO_CIRCUIT(circ)->n_circ_id = 42; /* This is the outbound test so use the next channel queue. */ queue = &TO_CIRCUIT(circ)->n_chan_cells; /* Setup packed cell to queue on the circuit. */ p_cell = packed_cell_new(); tt_assert(p_cell); p_cell2 = packed_cell_new(); tt_assert(p_cell2); /* Setup a channel to put the circuit on. */ chan = new_fake_channel(); tt_assert(chan); chan->state = CHANNEL_STATE_OPENING; channel_change_state_open(chan); /* Outbound channel. */ channel_mark_outgoing(chan); /* Try to register it so we can clean it through the channel cleanup * process. */ channel_register(chan); tt_int_op(chan->registered, OP_EQ, 1); /* Set EWMA policy so we can pick it when flushing. */ circuitmux_set_policy(chan->cmux, &ewma_policy); tt_ptr_op(circuitmux_get_policy(chan->cmux), OP_EQ, &ewma_policy); /* Register circuit to the channel circid map which will attach the circuit * to the channel's cmux as well. */ circuit_set_n_circid_chan(TO_CIRCUIT(circ), 42, chan); tt_int_op(channel_num_circuits(chan), OP_EQ, 1); /* Test the cmux state. */ tt_ptr_op(TO_CIRCUIT(circ)->n_mux, OP_EQ, chan->cmux); tt_int_op(circuitmux_is_circuit_attached(chan->cmux, TO_CIRCUIT(circ)), OP_EQ, 1); /* Flush the channel without any cell on it. */ old_count = test_cells_written; ssize_t flushed = channel_flush_some_cells(chan, 1); tt_i64_op(flushed, OP_EQ, 0); tt_int_op(test_cells_written, OP_EQ, old_count); tt_int_op(channel_more_to_flush(chan), OP_EQ, 0); tt_int_op(circuitmux_num_active_circuits(chan->cmux), OP_EQ, 0); tt_int_op(circuitmux_num_cells(chan->cmux), OP_EQ, 0); tt_int_op(circuitmux_is_circuit_active(chan->cmux, TO_CIRCUIT(circ)), OP_EQ, 0); tt_u64_op(chan->n_cells_xmitted, OP_EQ, 0); tt_u64_op(chan->n_bytes_xmitted, OP_EQ, 0); /* Queue cell onto the next queue that is the outbound direction. Than * update its cmux so the circuit can be picked when flushing cells. */ cell_queue_append(queue, p_cell); p_cell = NULL; tt_int_op(queue->n, OP_EQ, 1); cell_queue_append(queue, p_cell2); p_cell2 = NULL; tt_int_op(queue->n, OP_EQ, 2); update_circuit_on_cmux(TO_CIRCUIT(circ), CELL_DIRECTION_OUT); tt_int_op(circuitmux_num_active_circuits(chan->cmux), OP_EQ, 1); tt_int_op(circuitmux_num_cells(chan->cmux), OP_EQ, 2); tt_int_op(circuitmux_is_circuit_active(chan->cmux, TO_CIRCUIT(circ)), OP_EQ, 1); /* From this point on, we have a queued cell on an active circuit attached * to the channel's cmux. */ /* Flush the first cell. This is going to go down the call stack. */ old_count = test_cells_written; flushed = channel_flush_some_cells(chan, 1); tt_i64_op(flushed, OP_EQ, 1); tt_int_op(test_cells_written, OP_EQ, old_count + 1); tt_int_op(circuitmux_num_cells(chan->cmux), OP_EQ, 1); tt_int_op(channel_more_to_flush(chan), OP_EQ, 1); /* Circuit should remain active because there is a second cell queued. */ tt_int_op(circuitmux_is_circuit_active(chan->cmux, TO_CIRCUIT(circ)), OP_EQ, 1); /* Should still be attached. */ tt_int_op(circuitmux_is_circuit_attached(chan->cmux, TO_CIRCUIT(circ)), OP_EQ, 1); tt_u64_op(chan->n_cells_xmitted, OP_EQ, 1); tt_u64_op(chan->n_bytes_xmitted, OP_EQ, get_cell_network_size(0)); /* Flush second cell. This is going to go down the call stack. */ old_count = test_cells_written; flushed = channel_flush_some_cells(chan, 1); tt_i64_op(flushed, OP_EQ, 1); tt_int_op(test_cells_written, OP_EQ, old_count + 1); tt_int_op(circuitmux_num_cells(chan->cmux), OP_EQ, 0); tt_int_op(channel_more_to_flush(chan), OP_EQ, 0); /* No more cells should make the circuit inactive. */ tt_int_op(circuitmux_is_circuit_active(chan->cmux, TO_CIRCUIT(circ)), OP_EQ, 0); /* Should still be attached. */ tt_int_op(circuitmux_is_circuit_attached(chan->cmux, TO_CIRCUIT(circ)), OP_EQ, 1); tt_u64_op(chan->n_cells_xmitted, OP_EQ, 2); tt_u64_op(chan->n_bytes_xmitted, OP_EQ, get_cell_network_size(0) * 2); done: if (circ) { circuit_free_(TO_CIRCUIT(circ)); } tor_free(p_cell); channel_free_all(); UNMOCK(scheduler_release_channel); monotime_disable_test_mocking(); }
static void test_channel_dumpstats(void *arg) { channel_t *ch = NULL; cell_t *cell = NULL; packed_cell_t *p_cell = NULL; int old_count; (void)arg; /* Mock these for duration of the test */ MOCK(scheduler_channel_doesnt_want_writes, scheduler_channel_doesnt_want_writes_mock); MOCK(scheduler_release_channel, scheduler_release_channel_mock); /* Set up a new fake channel */ ch = new_fake_channel(); tt_assert(ch); /* Try to register it */ channel_register(ch); tt_assert(ch->registered); /* Set up mock */ dump_statistics_mock_target = ch; dump_statistics_mock_matches = 0; MOCK(channel_dump_statistics, chan_test_channel_dump_statistics_mock); /* Call channel_dumpstats() */ channel_dumpstats(LOG_DEBUG); /* Assert that we hit the mock */ tt_int_op(dump_statistics_mock_matches, OP_EQ, 1); /* Close the channel */ channel_mark_for_close(ch); tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSING); chan_test_finish_close(ch); tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSED); /* Try again and hit the finished channel */ channel_dumpstats(LOG_DEBUG); tt_int_op(dump_statistics_mock_matches, OP_EQ, 2); channel_run_cleanup(); ch = NULL; /* Now we should hit nothing */ channel_dumpstats(LOG_DEBUG); tt_int_op(dump_statistics_mock_matches, OP_EQ, 2); /* Unmock */ UNMOCK(channel_dump_statistics); dump_statistics_mock_target = NULL; dump_statistics_mock_matches = 0; /* Now make another channel */ ch = new_fake_channel(); tt_assert(ch); channel_register(ch); tt_int_op(ch->registered, OP_EQ, 1); /* Lie about its age so dumpstats gets coverage for rate calculations */ ch->timestamp_created = time(NULL) - 30; tt_int_op(ch->timestamp_created, OP_GT, 0); tt_int_op(time(NULL), OP_GT, ch->timestamp_created); /* Put cells through it both ways to make the counters non-zero */ p_cell = packed_cell_new(); test_chan_accept_cells = 1; old_count = test_cells_written; channel_write_packed_cell(ch, p_cell); tt_int_op(test_cells_written, OP_EQ, old_count + 1); tt_u64_op(ch->n_bytes_xmitted, OP_GT, 0); tt_u64_op(ch->n_cells_xmitted, OP_GT, 0); /* Receive path */ channel_set_cell_handlers(ch, chan_test_cell_handler, chan_test_var_cell_handler); tt_ptr_op(channel_get_cell_handler(ch), OP_EQ, chan_test_cell_handler); tt_ptr_op(channel_get_var_cell_handler(ch), OP_EQ, chan_test_var_cell_handler); cell = tor_malloc_zero(sizeof(*cell)); old_count = test_chan_fixed_cells_recved; channel_process_cell(ch, cell); tt_int_op(test_chan_fixed_cells_recved, OP_EQ, old_count + 1); tt_u64_op(ch->n_bytes_recved, OP_GT, 0); tt_u64_op(ch->n_cells_recved, OP_GT, 0); /* Test channel_dump_statistics */ ch->describe_transport = chan_test_describe_transport; ch->dumpstats = chan_test_dumpstats; test_chan_should_be_canonical = 1; ch->is_canonical = test_chan_is_canonical; old_count = test_dumpstats_calls; channel_dump_statistics(ch, LOG_DEBUG); tt_int_op(test_dumpstats_calls, OP_EQ, old_count + 1); /* Close the channel */ channel_mark_for_close(ch); tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSING); chan_test_finish_close(ch); tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSED); channel_run_cleanup(); ch = NULL; done: free_fake_channel(ch); tor_free(cell); UNMOCK(scheduler_channel_doesnt_want_writes); UNMOCK(scheduler_release_channel); return; }
static void test_channel_for_extend(void *arg) { channel_t *chan1 = NULL, *chan2 = NULL; channel_t *ret_chan = NULL; char digest[DIGEST_LEN]; ed25519_public_key_t ed_id; tor_addr_t addr; const char *msg; int launch; time_t now = time(NULL); (void) arg; memset(digest, 'A', sizeof(digest)); memset(&ed_id, 'B', sizeof(ed_id)); chan1 = new_fake_channel(); tt_assert(chan1); /* Need to be registered to get added to the id map. */ channel_register(chan1); tt_int_op(chan1->registered, OP_EQ, 1); /* We need those for the test. */ chan1->is_canonical = test_chan_is_canonical; chan1->matches_target = test_chan_matches_target; chan1->timestamp_created = now - 9; chan2 = new_fake_channel(); tt_assert(chan2); /* Need to be registered to get added to the id map. */ channel_register(chan2); tt_int_op(chan2->registered, OP_EQ, 1); /* We need those for the test. */ chan2->is_canonical = test_chan_is_canonical; chan2->matches_target = test_chan_matches_target; /* Make it older than chan1. */ chan2->timestamp_created = chan1->timestamp_created - 1; /* Set channel identities and add it to the channel map. The last one to be * added is made the first one in the list so the lookup will always return * that one first. */ channel_set_identity_digest(chan2, digest, &ed_id); channel_set_identity_digest(chan1, digest, &ed_id); tt_ptr_op(channel_find_by_remote_identity(digest, NULL), OP_EQ, chan1); tt_ptr_op(channel_find_by_remote_identity(digest, &ed_id), OP_EQ, chan1); /* The expected result is chan2 because it is older than chan1. */ ret_chan = channel_get_for_extend(digest, &ed_id, &addr, &msg, &launch); tt_assert(ret_chan); tt_ptr_op(ret_chan, OP_EQ, chan2); tt_int_op(launch, OP_EQ, 0); tt_str_op(msg, OP_EQ, "Connection is fine; using it."); /* Switch that around from previous test. */ chan2->timestamp_created = chan1->timestamp_created + 1; ret_chan = channel_get_for_extend(digest, &ed_id, &addr, &msg, &launch); tt_assert(ret_chan); tt_ptr_op(ret_chan, OP_EQ, chan1); tt_int_op(launch, OP_EQ, 0); tt_str_op(msg, OP_EQ, "Connection is fine; using it."); /* Same creation time, num circuits will be used and they both have 0 so the * channel 2 should be picked due to how channel_is_better() work. */ chan2->timestamp_created = chan1->timestamp_created; ret_chan = channel_get_for_extend(digest, &ed_id, &addr, &msg, &launch); tt_assert(ret_chan); tt_ptr_op(ret_chan, OP_EQ, chan1); tt_int_op(launch, OP_EQ, 0); tt_str_op(msg, OP_EQ, "Connection is fine; using it."); /* For the rest of the tests, we need channel 1 to be the older. */ chan2->timestamp_created = chan1->timestamp_created + 1; /* Condemned the older channel. */ chan1->state = CHANNEL_STATE_CLOSING; ret_chan = channel_get_for_extend(digest, &ed_id, &addr, &msg, &launch); tt_assert(ret_chan); tt_ptr_op(ret_chan, OP_EQ, chan2); tt_int_op(launch, OP_EQ, 0); tt_str_op(msg, OP_EQ, "Connection is fine; using it."); chan1->state = CHANNEL_STATE_OPEN; /* Make the older channel a client one. */ channel_mark_client(chan1); ret_chan = channel_get_for_extend(digest, &ed_id, &addr, &msg, &launch); tt_assert(ret_chan); tt_ptr_op(ret_chan, OP_EQ, chan2); tt_int_op(launch, OP_EQ, 0); tt_str_op(msg, OP_EQ, "Connection is fine; using it."); channel_clear_client(chan1); /* Non matching ed identity with valid digest. */ ed25519_public_key_t dumb_ed_id; memset(&dumb_ed_id, 0, sizeof(dumb_ed_id)); ret_chan = channel_get_for_extend(digest, &dumb_ed_id, &addr, &msg, &launch); tt_assert(!ret_chan); tt_str_op(msg, OP_EQ, "Not connected. Connecting."); tt_int_op(launch, OP_EQ, 1); /* Opening channel, we'll check if the target address matches. */ test_chan_should_match_target = 1; chan1->state = CHANNEL_STATE_OPENING; chan2->state = CHANNEL_STATE_OPENING; ret_chan = channel_get_for_extend(digest, &ed_id, &addr, &msg, &launch); tt_assert(!ret_chan); tt_str_op(msg, OP_EQ, "Connection in progress; waiting."); tt_int_op(launch, OP_EQ, 0); chan1->state = CHANNEL_STATE_OPEN; chan2->state = CHANNEL_STATE_OPEN; /* Mark channel 1 as bad for circuits. */ channel_mark_bad_for_new_circs(chan1); ret_chan = channel_get_for_extend(digest, &ed_id, &addr, &msg, &launch); tt_assert(ret_chan); tt_ptr_op(ret_chan, OP_EQ, chan2); tt_int_op(launch, OP_EQ, 0); tt_str_op(msg, OP_EQ, "Connection is fine; using it."); chan1->is_bad_for_new_circs = 0; /* Mark both channels as unusable. */ channel_mark_bad_for_new_circs(chan1); channel_mark_bad_for_new_circs(chan2); ret_chan = channel_get_for_extend(digest, &ed_id, &addr, &msg, &launch); tt_assert(!ret_chan); tt_str_op(msg, OP_EQ, "Connections all too old, or too non-canonical. " " Launching a new one."); tt_int_op(launch, OP_EQ, 1); chan1->is_bad_for_new_circs = 0; chan2->is_bad_for_new_circs = 0; /* Non canonical channels. */ test_chan_should_match_target = 0; test_chan_canonical_should_be_reliable = 1; ret_chan = channel_get_for_extend(digest, &ed_id, &addr, &msg, &launch); tt_assert(!ret_chan); tt_str_op(msg, OP_EQ, "Connections all too old, or too non-canonical. " " Launching a new one."); tt_int_op(launch, OP_EQ, 1); done: free_fake_channel(chan1); free_fake_channel(chan2); }
static void test_channel_id_map(void *arg) { (void)arg; #define N_CHAN 6 char rsa_id[N_CHAN][DIGEST_LEN]; ed25519_public_key_t *ed_id[N_CHAN]; channel_t *chan[N_CHAN]; int i; ed25519_public_key_t ed_zero; memset(&ed_zero, 0, sizeof(ed_zero)); tt_int_op(DIGEST_LEN, OP_EQ, sizeof(rsa_id[0])); // Do I remember C? for (i = 0; i < N_CHAN; ++i) { crypto_rand(rsa_id[i], DIGEST_LEN); ed_id[i] = tor_malloc_zero(sizeof(*ed_id[i])); crypto_rand((char*)ed_id[i]->pubkey, sizeof(ed_id[i]->pubkey)); } /* For channel 3, have no Ed identity. */ tor_free(ed_id[3]); /* Channel 2 and 4 have same ROSA identity */ memcpy(rsa_id[4], rsa_id[2], DIGEST_LEN); /* Channel 2 and 4 and 5 have same RSA identity */ memcpy(rsa_id[4], rsa_id[2], DIGEST_LEN); memcpy(rsa_id[5], rsa_id[2], DIGEST_LEN); /* Channels 2 and 5 have same Ed25519 identity */ memcpy(ed_id[5], ed_id[2], sizeof(*ed_id[2])); for (i = 0; i < N_CHAN; ++i) { chan[i] = new_fake_channel(); channel_register(chan[i]); channel_set_identity_digest(chan[i], rsa_id[i], ed_id[i]); } /* Lookup by RSA id only */ tt_ptr_op(chan[0], OP_EQ, channel_find_by_remote_identity(rsa_id[0], NULL)); tt_ptr_op(chan[1], OP_EQ, channel_find_by_remote_identity(rsa_id[1], NULL)); tt_ptr_op(chan[3], OP_EQ, channel_find_by_remote_identity(rsa_id[3], NULL)); channel_t *ch; ch = channel_find_by_remote_identity(rsa_id[2], NULL); tt_assert(ch == chan[2] || ch == chan[4] || ch == chan[5]); ch = channel_next_with_rsa_identity(ch); tt_assert(ch == chan[2] || ch == chan[4] || ch == chan[5]); ch = channel_next_with_rsa_identity(ch); tt_assert(ch == chan[2] || ch == chan[4] || ch == chan[5]); ch = channel_next_with_rsa_identity(ch); tt_ptr_op(ch, OP_EQ, NULL); /* As above, but with zero Ed25519 ID (meaning "any ID") */ tt_ptr_op(chan[0], OP_EQ, channel_find_by_remote_identity(rsa_id[0], &ed_zero)); tt_ptr_op(chan[1], OP_EQ, channel_find_by_remote_identity(rsa_id[1], &ed_zero)); tt_ptr_op(chan[3], OP_EQ, channel_find_by_remote_identity(rsa_id[3], &ed_zero)); ch = channel_find_by_remote_identity(rsa_id[2], &ed_zero); tt_assert(ch == chan[2] || ch == chan[4] || ch == chan[5]); ch = channel_next_with_rsa_identity(ch); tt_assert(ch == chan[2] || ch == chan[4] || ch == chan[5]); ch = channel_next_with_rsa_identity(ch); tt_assert(ch == chan[2] || ch == chan[4] || ch == chan[5]); ch = channel_next_with_rsa_identity(ch); tt_ptr_op(ch, OP_EQ, NULL); /* Lookup nonexistent RSA identity */ tt_ptr_op(NULL, OP_EQ, channel_find_by_remote_identity("!!!!!!!!!!!!!!!!!!!!", NULL)); /* Look up by full identity pair */ tt_ptr_op(chan[0], OP_EQ, channel_find_by_remote_identity(rsa_id[0], ed_id[0])); tt_ptr_op(chan[1], OP_EQ, channel_find_by_remote_identity(rsa_id[1], ed_id[1])); tt_ptr_op(chan[3], OP_EQ, channel_find_by_remote_identity(rsa_id[3], ed_id[3] /*NULL*/)); tt_ptr_op(chan[4], OP_EQ, channel_find_by_remote_identity(rsa_id[4], ed_id[4])); ch = channel_find_by_remote_identity(rsa_id[2], ed_id[2]); tt_assert(ch == chan[2] || ch == chan[5]); /* Look up RSA identity with wrong ed25519 identity */ tt_ptr_op(NULL, OP_EQ, channel_find_by_remote_identity(rsa_id[4], ed_id[0])); tt_ptr_op(NULL, OP_EQ, channel_find_by_remote_identity(rsa_id[2], ed_id[1])); tt_ptr_op(NULL, OP_EQ, channel_find_by_remote_identity(rsa_id[3], ed_id[1])); done: for (i = 0; i < N_CHAN; ++i) { channel_clear_identity_digest(chan[i]); channel_unregister(chan[i]); free_fake_channel(chan[i]); tor_free(ed_id[i]); } #undef N_CHAN }