36 #include "core/or/or_circuit_st.h"
46 worker_state_new(
void *arg)
55 #define worker_state_free(ws) \
56 FREE_AND_NULL(worker_state_t, worker_state_free_, (ws))
63 server_onion_keys_free(ws->onion_keys);
68 worker_state_free_void(
void *arg)
70 worker_state_free_(arg);
76 static int total_pending_tasks = 0;
77 static int max_pending_tasks = 128;
99 worker_state_free_void,
113 #define CPUWORKER_REQUEST_MAGIC 0xda4afeed
114 #define CPUWORKER_REPLY_MAGIC 0x5eedf00d
158 uint8_t
keys[CPATH_KEY_MATERIAL_LEN];
163 typedef struct cpuworker_job_u_t {
172 update_state_threadfn(
void *state_,
void *work_)
176 server_onion_keys_free(state->onion_keys);
177 state->onion_keys = update->onion_keys;
178 update->onion_keys = NULL;
179 worker_state_free(update);
198 update_state_threadfn,
199 worker_state_free_void,
201 log_warn(
LD_OR,
"Failed to queue key update for worker threads.");
220 #define MAX_BELIEVABLE_ONIONSKIN_DELAY (2*1000*1000)
228 if (onionskin_type > MAX_ONION_HANDSHAKE_TYPE)
246 if (onionskin_type > MAX_ONION_HANDSHAKE_TYPE)
247 return 1000 * (uint64_t)n_requests;
250 return 1000 * (uint64_t)n_requests;
266 uint16_t onionskin_type)
273 if (onionskin_type > MAX_ONION_HANDSHAKE_TYPE)
293 const char *onionskin_type_name)
296 double relative_overhead;
301 if (!overhead || r<0)
305 "%s onionskins have averaged %u usec overhead (%.2f%%) in "
307 onionskin_type_name, (
unsigned)overhead, relative_overhead*100);
319 --total_pending_tasks;
322 memcpy(&rpl, &job->u.reply,
sizeof(rpl));
330 struct timeval tv_end, tv_diff;
331 int64_t usec_roundtrip;
334 usec_roundtrip = ((int64_t)tv_diff.tv_sec)*1000000 + tv_diff.tv_usec;
335 if (usec_roundtrip >= 0 &&
353 "Unpacking cpuworker reply %p, circ=%p, success=%d",
360 log_debug(
LD_OR,
"Circuit died while reply was pending. Freeing memory.");
361 circ->base_.
magic = 0;
363 goto done_processing;
370 log_debug(
LD_OR,
"circuit is already marked.");
371 goto done_processing;
376 "decoding onionskin failed. "
377 "(Old key or bad software.) Closing.");
378 circuit_mark_for_close(
TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL);
379 goto done_processing;
384 (
const char*)rpl.
keys,
sizeof(rpl.
keys),
386 log_warn(
LD_OR,
"onionskin_answer failed. Closing.");
387 circuit_mark_for_close(
TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
388 goto done_processing;
390 log_debug(
LD_OR,
"onionskin_answer succeeded. Yay.");
411 memcpy(&req, &job->u.request,
sizeof(req));
414 memset(&rpl, 0,
sizeof(rpl));
418 struct timeval tv_start = {0,0}, tv_end;
429 rpl.
keys, CPATH_KEY_MATERIAL_LEN,
433 log_debug(
LD_OR,
"onion_skin_server_handshake failed.");
434 memset(&rpl, 0,
sizeof(rpl));
438 log_debug(
LD_OR,
"onion_skin_server_handshake succeeded.");
442 cell_out->
cell_type = CELL_CREATED;
break;
444 cell_out->
cell_type = CELL_CREATED2;
break;
445 case CELL_CREATE_FAST:
446 cell_out->
cell_type = CELL_CREATED_FAST;
break;
453 rpl.
magic = CPUWORKER_REPLY_MAGIC;
458 timersub(&tv_end, &tv_start, &tv_diff);
459 usec = ((int64_t)tv_diff.tv_sec)*1000000 + tv_diff.tv_usec;
463 rpl.
n_usec = (uint32_t) usec;
466 memcpy(&job->u.reply, &rpl,
sizeof(rpl));
480 while (total_pending_tasks < max_pending_tasks) {
487 log_info(
LD_OR,
"assign_to_cpuworker failed. Ignoring.");
495 void (*reply_fn)(
void *),
524 log_info(
LD_OR,
"circ->p_chan gone. Failing circ.");
529 if (total_pending_tasks >= max_pending_tasks) {
530 log_debug(
LD_OR,
"No idle cpuworkers. Queuing.");
542 memset(&req, 0,
sizeof(req));
544 req.
timed = should_time;
555 memcpy(&job->u.request, &req,
sizeof(req));
558 ++total_pending_tasks;
565 log_warn(
LD_BUG,
"Couldn't queue work on threadpool");
570 log_debug(
LD_OR,
"Queued task %p (qe=%p, circ=%p)",
571 job, queue_entry, job->circ);
590 memwipe(job, 0xe0,
sizeof(*job));
593 --total_pending_tasks;
int channel_is_client(const channel_t *chan)
Header file for channel.c.
#define DEAD_CIRCUIT_MAGIC
int onionskin_answer(struct or_circuit_t *circ, const created_cell_t *created_cell, const char *keys, size_t keys_len, const uint8_t *rend_circ_nonce)
Header for feature/relay/circuitbuild_relay.c.
Header file for circuitlist.c.
int get_num_cpus(const or_options_t *options)
const or_options_t * get_options(void)
Header file for config.c.
Header file for connection_or.c.
#define CPUWORKER_REQUEST_MAGIC
static void queue_pending_tasks(void)
void cpuworker_cancel_circ_handshake(or_circuit_t *circ)
#define MAX_BELIEVABLE_ONIONSKIN_DELAY
static uint64_t onionskins_usec_roundtrip[MAX_ONION_HANDSHAKE_TYPE+1]
int assign_onionskin_to_cpuworker(or_circuit_t *circ, create_cell_t *onionskin)
workqueue_entry_t * cpuworker_queue_work(workqueue_priority_t priority, workqueue_reply_t(*fn)(void *, void *), void(*reply_fn)(void *), void *arg)
static uint64_t onionskins_n_processed[MAX_ONION_HANDSHAKE_TYPE+1]
static int get_overhead_for_onionskins(uint32_t *usec_out, double *frac_out, uint16_t onionskin_type)
void cpuworker_log_onionskin_overhead(int severity, int onionskin_type, const char *onionskin_type_name)
static workqueue_reply_t cpuworker_onion_handshake_threadfn(void *state_, void *work_)
void cpuworkers_rotate_keyinfo(void)
static uint64_t onionskins_usec_internal[MAX_ONION_HANDSHAKE_TYPE+1]
static void cpuworker_onion_handshake_replyfn(void *work_)
uint64_t estimated_usec_for_onionskins(uint32_t n_requests, uint16_t onionskin_type)
static int should_time_request(uint16_t onionskin_type)
Header file for cpuworker.c.
Common functions for using (pseudo-)random number generators.
#define crypto_fast_rng_one_in_n(rng, n)
crypto_fast_rng_t * get_thread_fast_rng(void)
void memwipe(void *mem, uint8_t byte, size_t sz)
Common functions for cryptographic routines.
#define log_fn(severity, domain, args,...)
int onion_skin_server_handshake(int type, const uint8_t *onion_skin, size_t onionskin_len, const server_onion_keys_t *keys, uint8_t *reply_out, uint8_t *keys_out, size_t keys_out_len, uint8_t *rend_nonce_out)
server_onion_keys_t * server_onion_keys_new(void)
Header file for onion_crypto.c.
int onion_pending_add(or_circuit_t *circ, create_cell_t *onionskin)
or_circuit_t * onion_next_task(create_cell_t **onionskin_out)
Header file for onion_queue.c.
Master header file for Tor-specific functionality.
void rep_hist_note_circuit_handshake_assigned(uint16_t type)
Header file for rephist.c.
Header file for router.c.
struct timeval started_at
created_cell_t created_cell
uint8_t keys[CPATH_KEY_MATERIAL_LEN]
uint8_t rend_auth_material[DIGEST_LEN]
struct timeval started_at
create_cell_t create_cell
uint8_t onionskin[CELL_PAYLOAD_SIZE - 4]
uint8_t reply[CELL_PAYLOAD_SIZE - 2]
struct workqueue_entry_t * workqueue_entry
#define MOCK_IMPL(rv, funcname, arglist)
#define timersub(tv1, tv2, tvout)
void tor_gettimeofday(struct timeval *timeval)
threadpool_t * threadpool_new(int n_threads, replyqueue_t *replyqueue, void *(*new_thread_state_fn)(void *), void(*free_thread_state_fn)(void *), void *arg)
void * workqueue_entry_cancel(workqueue_entry_t *ent)
replyqueue_t * replyqueue_new(uint32_t alertsocks_flags)
workqueue_entry_t * threadpool_queue_work_priority(threadpool_t *pool, workqueue_priority_t prio, workqueue_reply_t(*fn)(void *, void *), void(*reply_fn)(void *), void *arg)
int threadpool_register_reply_event(threadpool_t *tp, void(*cb)(threadpool_t *tp))
int threadpool_queue_update(threadpool_t *pool, void *(*dup_fn)(void *), workqueue_reply_t(*fn)(void *, void *), void(*free_fn)(void *), void *arg)