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