Tor 0.4.9.1-alpha-dev
cpuworker.c
Go to the documentation of this file.
1/* Copyright (c) 2003-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2024, The Tor Project, Inc. */
4/* See LICENSE for licensing information */
5
6/**
7 * \file cpuworker.c
8 * \brief Uses the workqueue/threadpool code to farm CPU-intensive activities
9 * out to subprocesses.
10 *
11 * The multithreading backend for this module is in workqueue.c; this module
12 * specializes workqueue.c.
13 *
14 * Right now, we use this infrastructure
15 * <ul><li>for processing onionskins in onion.c
16 * <li>for compressing consensuses in consdiffmgr.c,
17 * <li>for calculating diffs and compressing them in consdiffmgr.c.
18 * <li>and for solving onion service PoW challenges in pow.c.
19 * </ul>
20 **/
21#include "core/or/or.h"
22#include "core/or/channel.h"
23#include "core/or/circuitlist.h"
27#include "app/config/config.h"
31#include "core/or/onion.h"
39
40#include "core/or/or_circuit_st.h"
41
42static void queue_pending_tasks(void);
43
44typedef struct worker_state_t {
45 int generation;
46 server_onion_keys_t *onion_keys;
48
49static void *
50worker_state_new(void *arg)
51{
53 (void)arg;
54 ws = tor_malloc_zero(sizeof(worker_state_t));
55 ws->onion_keys = server_onion_keys_new();
56 return ws;
57}
58
59#define worker_state_free(ws) \
60 FREE_AND_NULL(worker_state_t, worker_state_free_, (ws))
61
62static void
63worker_state_free_(worker_state_t *ws)
64{
65 if (!ws)
66 return;
67 server_onion_keys_free(ws->onion_keys);
68 tor_free(ws);
69}
70
71static void
72worker_state_free_void(void *arg)
73{
74 worker_state_free_(arg);
75}
76
77static threadpool_t *threadpool = NULL;
78
79static uint32_t total_pending_tasks = 0;
80static uint32_t max_pending_tasks = 128;
81
82/** Return the consensus parameter max pending tasks per CPU. */
83static uint32_t
85{
86/* Total voodoo. Can we make this more sensible? Maybe, that is why we made it
87 * a consensus parameter so our future self can figure out this magic. */
88#define MAX_PENDING_TASKS_PER_CPU_DEFAULT 64
89#define MAX_PENDING_TASKS_PER_CPU_MIN 1
90#define MAX_PENDING_TASKS_PER_CPU_MAX INT32_MAX
91
92 return networkstatus_get_param(ns, "max_pending_tasks_per_cpu",
93 MAX_PENDING_TASKS_PER_CPU_DEFAULT,
94 MAX_PENDING_TASKS_PER_CPU_MIN,
95 MAX_PENDING_TASKS_PER_CPU_MAX);
96}
97
98/** Set the max pending tasks per CPU worker. This uses the consensus to check
99 * for the allowed number per CPU. The ns parameter can be NULL as in that no
100 * consensus is available at the time of setting this value. */
101static void
103{
104 max_pending_tasks =
106}
107
108/** Called when the consensus has changed. */
109void
111{
112 tor_assert(ns);
114}
115
116/** Initialize the cpuworker subsystem. It is OK to call this more than once
117 * during Tor's lifetime.
118 */
119void
121{
122 /*
123 In our threadpool implementation, half the threads are permissive and
124 half are strict (when it comes to running lower-priority tasks). So we
125 always make sure we have at least two threads, so that there will be at
126 least one thread of each kind.
127 */
128 const int n_threads = MAX(get_num_cpus(get_options()), 2);
129 threadpool = threadpool_new(n_threads,
131 worker_state_new,
132 worker_state_free_void,
133 NULL);
134
135 int r = threadpool_register_reply_event(threadpool, NULL);
136
137 tor_assert(r == 0);
138
140}
141
142/** Free all resources allocated by cpuworker. */
143void
145{
146 threadpool_free(threadpool);
147}
148
149/** Return the number of threads configured for our CPU worker. */
150unsigned int
152{
153 if (!threadpool) {
154 return 0;
155 }
156 return threadpool_get_n_threads(threadpool);
157}
158
159/** Magic numbers to make sure our cpuworker_requests don't grow any
160 * mis-framing bugs. */
161#define CPUWORKER_REQUEST_MAGIC 0xda4afeed
162#define CPUWORKER_REPLY_MAGIC 0x5eedf00d
163
164/** A request sent to a cpuworker. */
165typedef struct cpuworker_request_t {
166 /** Magic number; must be CPUWORKER_REQUEST_MAGIC. */
167 uint32_t magic;
168
169 /** Flag: Are we timing this request? */
170 unsigned timed : 1;
171 /** If we're timing this request, when was it sent to the cpuworker? */
173
174 /** A create cell for the cpuworker to process. */
176
177 /**
178 * A copy of this relay's consensus params that are relevant to
179 * the circuit, for use in negotiation. */
181
182 /* Turn the above into a tagged union if needed. */
184
185/** A reply sent by a cpuworker. */
186typedef struct cpuworker_reply_t {
187 /** Magic number; must be CPUWORKER_REPLY_MAGIC. */
188 uint32_t magic;
189
190 /** True iff we got a successful request. */
191 uint8_t success;
192
193 /** Are we timing this request? */
194 unsigned int timed : 1;
195 /** What handshake type was the request? (Used for timing) */
197 /** When did we send the request to the cpuworker? */
199 /** Once the cpuworker received the request, how many microseconds did it
200 * take? (This shouldn't overflow; 4 billion micoseconds is over an hour,
201 * and we'll never have an onion handshake that takes so long.) */
202 uint32_t n_usec;
203
204 /** Output of processing a create cell
205 *
206 * @{
207 */
208 /** The created cell to send back. */
210 /** The keys to use on this circuit. */
211 uint8_t keys[CPATH_KEY_MATERIAL_LEN];
212 /** Input to use for authenticating introduce1 cells. */
214 /** Negotiated circuit parameters. */
217
218typedef struct cpuworker_job_u_t {
219 or_circuit_t *circ;
220 union {
221 cpuworker_request_t request;
222 cpuworker_reply_t reply;
223 } u;
225
227update_state_threadfn(void *state_, void *work_)
228{
229 worker_state_t *state = state_;
230 worker_state_t *update = work_;
231 server_onion_keys_free(state->onion_keys);
232 state->onion_keys = update->onion_keys;
233 update->onion_keys = NULL;
234 worker_state_free(update);
235 ++state->generation;
236 return WQ_RPL_REPLY;
237}
238
239/** Called when the onion key has changed so update all CPU worker(s) with
240 * new function pointers with which a new state will be generated.
241 */
242void
244{
245 if (!threadpool) {
246 /* If we're a client, then we won't have cpuworkers, and we won't need
247 * to tell them to rotate their state.
248 */
249 return;
250 }
251 if (threadpool_queue_update(threadpool,
252 worker_state_new,
253 update_state_threadfn,
254 worker_state_free_void,
255 NULL)) {
256 log_warn(LD_OR, "Failed to queue key update for worker threads.");
257 }
258}
259
260/** Indexed by handshake type: how many onionskins have we processed and
261 * counted of that type? */
262static uint64_t onionskins_n_processed[MAX_ONION_HANDSHAKE_TYPE+1];
263/** Indexed by handshake type, corresponding to the onionskins counted in
264 * onionskins_n_processed: how many microseconds have we spent in cpuworkers
265 * processing that kind of onionskin? */
266static uint64_t onionskins_usec_internal[MAX_ONION_HANDSHAKE_TYPE+1];
267/** Indexed by handshake type, corresponding to onionskins counted in
268 * onionskins_n_processed: how many microseconds have we spent waiting for
269 * cpuworkers to give us answers for that kind of onionskin?
270 */
271static uint64_t onionskins_usec_roundtrip[MAX_ONION_HANDSHAKE_TYPE+1];
272
273/** If any onionskin takes longer than this, we clip them to this
274 * time. (microseconds) */
275#define MAX_BELIEVABLE_ONIONSKIN_DELAY (2*1000*1000)
276
277/** Return true iff we'd like to measure a handshake of type
278 * <b>onionskin_type</b>. Call only from the main thread. */
279static int
280should_time_request(uint16_t onionskin_type)
281{
282 /* If we've never heard of this type, we shouldn't even be here. */
283 if (onionskin_type > MAX_ONION_HANDSHAKE_TYPE)
284 return 0;
285 /* Measure the first N handshakes of each type, to ensure we have a
286 * sample */
287 if (onionskins_n_processed[onionskin_type] < 4096)
288 return 1;
289
290 /** Otherwise, measure with P=1/128. We avoid doing this for every
291 * handshake, since the measurement itself can take a little time. */
293}
294
295/** Return an estimate of how many microseconds we will need for a single
296 * cpuworker to process <b>n_requests</b> onionskins of type
297 * <b>onionskin_type</b>. */
298uint64_t
299estimated_usec_for_onionskins(uint32_t n_requests, uint16_t onionskin_type)
300{
301 if (onionskin_type > MAX_ONION_HANDSHAKE_TYPE) /* should be impossible */
302 return 1000 * (uint64_t)n_requests;
303 if (PREDICT_UNLIKELY(onionskins_n_processed[onionskin_type] < 100)) {
304 /* Until we have 100 data points, just assume everything takes 1 msec. */
305 return 1000 * (uint64_t)n_requests;
306 } else {
307 /* This can't overflow: we'll never have more than 500000 onionskins
308 * measured in onionskin_usec_internal, and they won't take anything near
309 * 1 sec each, and we won't have anything like 1 million queued
310 * onionskins. But that's 5e5 * 1e6 * 1e6, which is still less than
311 * UINT64_MAX. */
312 return (onionskins_usec_internal[onionskin_type] * n_requests) /
313 onionskins_n_processed[onionskin_type];
314 }
315}
316
317/** Compute the absolute and relative overhead of using the cpuworker
318 * framework for onionskins of type <b>onionskin_type</b>.*/
319static int
320get_overhead_for_onionskins(uint32_t *usec_out, double *frac_out,
321 uint16_t onionskin_type)
322{
323 uint64_t overhead;
324
325 *usec_out = 0;
326 *frac_out = 0.0;
327
328 if (onionskin_type > MAX_ONION_HANDSHAKE_TYPE) /* should be impossible */
329 return -1;
330 if (onionskins_n_processed[onionskin_type] == 0 ||
331 onionskins_usec_internal[onionskin_type] == 0 ||
332 onionskins_usec_roundtrip[onionskin_type] == 0)
333 return -1;
334
335 overhead = onionskins_usec_roundtrip[onionskin_type] -
336 onionskins_usec_internal[onionskin_type];
337
338 *usec_out = (uint32_t)(overhead / onionskins_n_processed[onionskin_type]);
339 *frac_out = ((double)overhead) / onionskins_usec_internal[onionskin_type];
340
341 return 0;
342}
343
344/** If we've measured overhead for onionskins of type <b>onionskin_type</b>,
345 * log it. */
346void
347cpuworker_log_onionskin_overhead(int severity, int onionskin_type,
348 const char *onionskin_type_name)
349{
350 uint32_t overhead;
351 double relative_overhead;
352 int r;
353
354 r = get_overhead_for_onionskins(&overhead, &relative_overhead,
355 onionskin_type);
356 if (!overhead || r<0)
357 return;
358
359 log_fn(severity, LD_OR,
360 "%s onionskins have averaged %u usec overhead (%.2f%%) in "
361 "cpuworker code ",
362 onionskin_type_name, (unsigned)overhead, relative_overhead*100);
363}
364
365/** Handle a reply from the worker threads. */
366static void
368{
369 cpuworker_job_t *job = work_;
371 or_circuit_t *circ = NULL;
372
373 tor_assert(total_pending_tasks > 0);
374 --total_pending_tasks;
375
376 /* Could avoid this, but doesn't matter. */
377 memcpy(&rpl, &job->u.reply, sizeof(rpl));
378
379 tor_assert(rpl.magic == CPUWORKER_REPLY_MAGIC);
380
381 if (rpl.timed && rpl.success &&
382 rpl.handshake_type <= MAX_ONION_HANDSHAKE_TYPE) {
383 /* Time how long this request took. The handshake_type check should be
384 needless, but let's leave it in to be safe. */
385 struct timeval tv_end, tv_diff;
386 int64_t usec_roundtrip;
387 tor_gettimeofday(&tv_end);
388 timersub(&tv_end, &rpl.started_at, &tv_diff);
389 usec_roundtrip = ((int64_t)tv_diff.tv_sec)*1000000 + tv_diff.tv_usec;
390 if (usec_roundtrip >= 0 &&
391 usec_roundtrip < MAX_BELIEVABLE_ONIONSKIN_DELAY) {
394 onionskins_usec_roundtrip[rpl.handshake_type] += usec_roundtrip;
395 if (onionskins_n_processed[rpl.handshake_type] >= 500000) {
396 /* Scale down every 500000 handshakes. On a busy server, that's
397 * less impressive than it sounds. */
401 }
402 }
403 }
404
405 circ = job->circ;
406
407 log_debug(LD_OR,
408 "Unpacking cpuworker reply %p, circ=%p, success=%d",
409 job, circ, rpl.success);
410
411 if (circ->base_.magic == DEAD_CIRCUIT_MAGIC) {
412 /* The circuit was supposed to get freed while the reply was
413 * pending. Instead, it got left for us to free so that we wouldn't freak
414 * out when the job->circ field wound up pointing to nothing. */
415 log_debug(LD_OR, "Circuit died while reply was pending. Freeing memory.");
416 circ->base_.magic = 0;
417 tor_free(circ);
418 goto done_processing;
419 }
420
421 circ->workqueue_entry = NULL;
422
423 if (TO_CIRCUIT(circ)->marked_for_close) {
424 /* We already marked this circuit; we can't call it open. */
425 log_debug(LD_OR,"circuit is already marked.");
426 goto done_processing;
427 }
428
429 if (rpl.success == 0) {
430 log_debug(LD_OR,
431 "decoding onionskin failed. "
432 "(Old key or bad software.) Closing.");
433 circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL);
434 goto done_processing;
435 }
436
437 /* If the client asked for congestion control, if our consensus parameter
438 * allowed it to negotiate as enabled, allocate a congestion control obj. */
439 if (rpl.circ_params.cc_enabled) {
440 if (get_options()->SbwsExit) {
441 TO_CIRCUIT(circ)->ccontrol = congestion_control_new(&rpl.circ_params,
442 CC_PATH_SBWS);
443 } else {
444 TO_CIRCUIT(circ)->ccontrol = congestion_control_new(&rpl.circ_params,
445 CC_PATH_EXIT);
446 }
447 }
448
449 if (onionskin_answer(circ,
450 &rpl.created_cell,
451 (const char*)rpl.keys, sizeof(rpl.keys),
452 rpl.rend_auth_material) < 0) {
453 log_warn(LD_OR,"onionskin_answer failed. Closing.");
454 circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
455 goto done_processing;
456 }
457
458 log_debug(LD_OR,"onionskin_answer succeeded. Yay.");
459
460 done_processing:
461 memwipe(&rpl, 0, sizeof(rpl));
462 memwipe(job, 0, sizeof(*job));
463 tor_free(job);
465}
466
467/** Implementation function for onion handshake requests. */
469cpuworker_onion_handshake_threadfn(void *state_, void *work_)
470{
471 worker_state_t *state = state_;
472 cpuworker_job_t *job = work_;
473
474 /* variables for onion processing */
475 server_onion_keys_t *onion_keys = state->onion_keys;
478
479 memcpy(&req, &job->u.request, sizeof(req));
480
482 memset(&rpl, 0, sizeof(rpl));
483
484 const create_cell_t *cc = &req.create_cell;
485 created_cell_t *cell_out = &rpl.created_cell;
486 struct timeval tv_start = {0,0}, tv_end;
487 int n;
488 rpl.timed = req.timed;
489 rpl.started_at = req.started_at;
491 if (req.timed)
492 tor_gettimeofday(&tv_start);
494 cc->onionskin, cc->handshake_len,
495 onion_keys,
496 &req.circ_ns_params,
497 cell_out->reply,
498 sizeof(cell_out->reply),
499 rpl.keys, CPATH_KEY_MATERIAL_LEN,
501 &rpl.circ_params);
502 if (n < 0) {
503 /* failure */
504 log_debug(LD_OR,"onion_skin_server_handshake failed.");
505 memset(&rpl, 0, sizeof(rpl));
506 rpl.success = 0;
507 } else {
508 /* success */
509 log_debug(LD_OR,"onion_skin_server_handshake succeeded.");
510 cell_out->handshake_len = n;
511 switch (cc->cell_type) {
512 case CELL_CREATE:
513 cell_out->cell_type = CELL_CREATED; break;
514 case CELL_CREATE2:
515 cell_out->cell_type = CELL_CREATED2; break;
516 case CELL_CREATE_FAST:
517 cell_out->cell_type = CELL_CREATED_FAST; break;
518 default:
519 tor_assert(0);
520 return WQ_RPL_SHUTDOWN;
521 }
522 rpl.success = 1;
523 }
524
525 rpl.magic = CPUWORKER_REPLY_MAGIC;
526 if (req.timed) {
527 struct timeval tv_diff;
528 int64_t usec;
529 tor_gettimeofday(&tv_end);
530 timersub(&tv_end, &tv_start, &tv_diff);
531 usec = ((int64_t)tv_diff.tv_sec)*1000000 + tv_diff.tv_usec;
532 if (usec < 0 || usec > MAX_BELIEVABLE_ONIONSKIN_DELAY)
534 else
535 rpl.n_usec = (uint32_t) usec;
536 }
537
538 memcpy(&job->u.reply, &rpl, sizeof(rpl));
539
540 memwipe(&req, 0, sizeof(req));
541 memwipe(&rpl, 0, sizeof(req));
542 return WQ_RPL_REPLY;
543}
544
545/** Take pending tasks from the queue and assign them to cpuworkers. */
546static void
548{
549 or_circuit_t *circ;
550 create_cell_t *onionskin = NULL;
551
552 while (total_pending_tasks < max_pending_tasks) {
553 circ = onion_next_task(&onionskin);
554
555 if (!circ)
556 return;
557
558 if (assign_onionskin_to_cpuworker(circ, onionskin) < 0)
559 log_info(LD_OR,"assign_to_cpuworker failed. Ignoring.");
560 }
561}
562
563/** DOCDOC */
566 workqueue_reply_t (*fn)(void *, void *),
567 void (*reply_fn)(void *),
568 void *arg))
569{
570 tor_assert(threadpool);
571
572 return threadpool_queue_work_priority(threadpool,
573 priority,
574 fn,
575 reply_fn,
576 arg);
577}
578
579/** Try to tell a cpuworker to perform the public key operations necessary to
580 * respond to <b>onionskin</b> for the circuit <b>circ</b>.
581 *
582 * Return 0 if we successfully assign the task, or -1 on failure.
583 */
584int
586 create_cell_t *onionskin)
587{
588 workqueue_entry_t *queue_entry;
589 cpuworker_job_t *job;
591 int should_time;
592
593 tor_assert(threadpool);
594
595 if (!circ->p_chan) {
596 log_info(LD_OR,"circ->p_chan gone. Failing circ.");
597 tor_free(onionskin);
598 return -1;
599 }
600
601 if (total_pending_tasks >= max_pending_tasks) {
602 log_debug(LD_OR,"No idle cpuworkers. Queuing.");
603 if (onion_pending_add(circ, onionskin) < 0) {
604 tor_free(onionskin);
605 return -1;
606 }
607 return 0;
608 }
609
610 if (!channel_is_client(circ->p_chan))
612
613 should_time = should_time_request(onionskin->handshake_type);
614 memset(&req, 0, sizeof(req));
616 req.timed = should_time;
617
618 memcpy(&req.create_cell, onionskin, sizeof(create_cell_t));
619
620 tor_free(onionskin);
621
622 if (should_time)
624
625 /* Copy the current cached consensus params relevant to
626 * circuit negotiation into the CPU worker context */
629
630 job = tor_malloc_zero(sizeof(cpuworker_job_t));
631 job->circ = circ;
632 memcpy(&job->u.request, &req, sizeof(req));
633 memwipe(&req, 0, sizeof(req));
634
635 ++total_pending_tasks;
636 queue_entry = threadpool_queue_work_priority(threadpool,
637 WQ_PRI_HIGH,
640 job);
641 if (!queue_entry) {
642 log_warn(LD_BUG, "Couldn't queue work on threadpool");
643 tor_free(job);
644 return -1;
645 }
646
647 log_debug(LD_OR, "Queued task %p (qe=%p, circ=%p)",
648 job, queue_entry, job->circ);
649
650 circ->workqueue_entry = queue_entry;
651
652 return 0;
653}
654
655/** If <b>circ</b> has a pending handshake that hasn't been processed yet,
656 * remove it from the worker queue. */
657void
659{
660 cpuworker_job_t *job;
661 if (circ->workqueue_entry == NULL)
662 return;
663
665 if (job) {
666 /* It successfully cancelled. */
667 memwipe(job, 0xe0, sizeof(*job));
668 tor_free(job);
669 tor_assert(total_pending_tasks > 0);
670 --total_pending_tasks;
671 /* if (!job), this is done in cpuworker_onion_handshake_replyfn. */
672 circ->workqueue_entry = NULL;
673 }
674}
int channel_is_client(const channel_t *chan)
Definition: channel.c:2918
Header file for channel.c.
#define DEAD_CIRCUIT_MAGIC
Definition: circuit_st.h:37
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.
#define MAX(a, b)
Definition: cmp.h:22
int get_num_cpus(const or_options_t *options)
Definition: config.c:7089
const or_options_t * get_options(void)
Definition: config.c:944
Header file for config.c.
congestion_control_t * congestion_control_new(const circuit_params_t *params, cc_path_t path)
bool congestion_control_enabled(void)
Public APIs for congestion control.
static uint8_t congestion_control_sendme_inc(void)
APIs for stream flow control on congestion controlled circuits.
Header file for connection_or.c.
#define CPUWORKER_REQUEST_MAGIC
Definition: cpuworker.c:161
static void queue_pending_tasks(void)
Definition: cpuworker.c:547
void cpuworker_cancel_circ_handshake(or_circuit_t *circ)
Definition: cpuworker.c:658
#define MAX_BELIEVABLE_ONIONSKIN_DELAY
Definition: cpuworker.c:275
static uint64_t onionskins_usec_roundtrip[MAX_ONION_HANDSHAKE_TYPE+1]
Definition: cpuworker.c:271
static uint32_t get_max_pending_tasks_per_cpu(const networkstatus_t *ns)
Definition: cpuworker.c:84
int assign_onionskin_to_cpuworker(or_circuit_t *circ, create_cell_t *onionskin)
Definition: cpuworker.c:585
static void set_max_pending_tasks(const networkstatus_t *ns)
Definition: cpuworker.c:102
static uint64_t onionskins_n_processed[MAX_ONION_HANDSHAKE_TYPE+1]
Definition: cpuworker.c:262
workqueue_entry_t * cpuworker_queue_work(workqueue_priority_t priority, workqueue_reply_t(*fn)(void *, void *), void(*reply_fn)(void *), void *arg)
Definition: cpuworker.c:568
void cpuworker_free_all(void)
Definition: cpuworker.c:144
static int get_overhead_for_onionskins(uint32_t *usec_out, double *frac_out, uint16_t onionskin_type)
Definition: cpuworker.c:320
void cpuworker_init(void)
Definition: cpuworker.c:120
unsigned int cpuworker_get_n_threads(void)
Definition: cpuworker.c:151
void cpuworker_consensus_has_changed(const networkstatus_t *ns)
Definition: cpuworker.c:110
void cpuworker_log_onionskin_overhead(int severity, int onionskin_type, const char *onionskin_type_name)
Definition: cpuworker.c:347
static workqueue_reply_t cpuworker_onion_handshake_threadfn(void *state_, void *work_)
Definition: cpuworker.c:469
void cpuworkers_rotate_keyinfo(void)
Definition: cpuworker.c:243
static uint64_t onionskins_usec_internal[MAX_ONION_HANDSHAKE_TYPE+1]
Definition: cpuworker.c:266
static void cpuworker_onion_handshake_replyfn(void *work_)
Definition: cpuworker.c:367
uint64_t estimated_usec_for_onionskins(uint32_t n_requests, uint16_t onionskin_type)
Definition: cpuworker.c:299
static int should_time_request(uint16_t onionskin_type)
Definition: cpuworker.c:280
Header file for cpuworker.c.
Common functions for using (pseudo-)random number generators.
#define crypto_fast_rng_one_in_n(rng, n)
Definition: crypto_rand.h:80
crypto_fast_rng_t * get_thread_fast_rng(void)
void memwipe(void *mem, uint8_t byte, size_t sz)
Definition: crypto_util.c:55
Common functions for cryptographic routines.
#define DIGEST_LEN
Definition: digest_sizes.h:20
#define log_fn(severity, domain, args,...)
Definition: log.h:283
#define LD_OR
Definition: log.h:92
#define LD_BUG
Definition: log.h:86
#define tor_free(p)
Definition: malloc.h:56
int32_t networkstatus_get_param(const networkstatus_t *ns, const char *param_name, int32_t default_val, int32_t min_val, int32_t max_val)
Header file for networkstatus.c.
Header file for onion.c.
int onion_skin_server_handshake(int type, const uint8_t *onion_skin, size_t onionskin_len, const server_onion_keys_t *keys, const circuit_params_t *our_ns_params, uint8_t *reply_out, size_t reply_out_maxlen, uint8_t *keys_out, size_t keys_out_len, uint8_t *rend_nonce_out, circuit_params_t *params_out)
Definition: onion_crypto.c:262
server_onion_keys_t * server_onion_keys_new(void)
Definition: onion_crypto.c:64
Header file for onion_crypto.c.
int onion_pending_add(or_circuit_t *circ, create_cell_t *onionskin)
Definition: onion_queue.c:177
or_circuit_t * onion_next_task(create_cell_t **onionskin_out)
Definition: onion_queue.c:265
Header file for onion_queue.c.
Master header file for Tor-specific functionality.
#define TO_CIRCUIT(x)
Definition: or.h:848
void rep_hist_note_circuit_handshake_assigned(uint16_t type)
Definition: rephist.c:2384
Header file for rephist.c.
Header file for router.c.
uint8_t sendme_inc_cells
Definition: onion_crypto.h:36
uint32_t magic
Definition: circuit_st.h:63
struct timeval started_at
Definition: cpuworker.c:198
created_cell_t created_cell
Definition: cpuworker.c:209
unsigned int timed
Definition: cpuworker.c:194
uint32_t magic
Definition: cpuworker.c:188
uint8_t keys[CPATH_KEY_MATERIAL_LEN]
Definition: cpuworker.c:211
uint8_t rend_auth_material[DIGEST_LEN]
Definition: cpuworker.c:213
uint16_t handshake_type
Definition: cpuworker.c:196
circuit_params_t circ_params
Definition: cpuworker.c:215
uint32_t n_usec
Definition: cpuworker.c:202
struct timeval started_at
Definition: cpuworker.c:172
create_cell_t create_cell
Definition: cpuworker.c:175
circuit_params_t circ_ns_params
Definition: cpuworker.c:180
uint16_t handshake_len
Definition: onion.h:30
uint16_t handshake_type
Definition: onion.h:28
uint8_t onionskin[CELL_PAYLOAD_SIZE - 4]
Definition: onion.h:32
uint8_t cell_type
Definition: onion.h:26
uint16_t handshake_len
Definition: onion.h:40
uint8_t reply[CELL_PAYLOAD_SIZE - 2]
Definition: onion.h:42
uint8_t cell_type
Definition: onion.h:38
channel_t * p_chan
Definition: or_circuit_st.h:37
struct workqueue_entry_t * workqueue_entry
Definition: or_circuit_st.h:30
Definition: workqueue.c:98
#define MOCK_IMPL(rv, funcname, arglist)
Definition: testsupport.h:133
#define timersub(tv1, tv2, tvout)
Definition: timeval.h:61
void tor_gettimeofday(struct timeval *timeval)
#define tor_assert(expr)
Definition: util_bug.h:103
void * workqueue_entry_cancel(workqueue_entry_t *ent)
Definition: workqueue.c:200
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)
Definition: workqueue.c:404
replyqueue_t * replyqueue_new(uint32_t alertsocks_flags)
Definition: workqueue.c:637
int threadpool_register_reply_event(threadpool_t *tp, void(*cb)(threadpool_t *tp))
Definition: workqueue.c:694
int threadpool_queue_update(threadpool_t *pool, void *(*dup_fn)(void *), workqueue_reply_t(*fn)(void *, void *), void(*free_fn)(void *), void *arg)
Definition: workqueue.c:455
threadpool_t * threadpool_new(int n_threads, replyqueue_t *replyqueue, void *(*new_thread_state_fn)(void *), void(*free_thread_state_fn)(void *), void *arg)
Definition: workqueue.c:559
unsigned int threadpool_get_n_threads(threadpool_t *tp)
Definition: workqueue.c:749
Header for workqueue.c.
workqueue_reply_t
Definition: workqueue.h:24
@ WQ_RPL_SHUTDOWN
Definition: workqueue.h:27
workqueue_priority_t
Definition: workqueue.h:31