diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ext/README | 4 | ||||
-rw-r--r-- | src/ext/tor_queue.h | 341 | ||||
-rw-r--r-- | src/or/channel.c | 70 | ||||
-rw-r--r-- | src/or/channel.h | 4 | ||||
-rw-r--r-- | src/or/config.c | 13 | ||||
-rw-r--r-- | src/or/nodelist.c | 152 | ||||
-rw-r--r-- | src/or/onion.c | 16 | ||||
-rw-r--r-- | src/or/or.h | 3 | ||||
-rw-r--r-- | src/or/routerlist.c | 90 | ||||
-rw-r--r-- | src/or/routerlist.h | 4 |
10 files changed, 415 insertions, 282 deletions
diff --git a/src/ext/README b/src/ext/README index cd23f29496..58ba7f699d 100644 --- a/src/ext/README +++ b/src/ext/README @@ -34,7 +34,9 @@ tor_queue.h A copy of sys/queue.h from OpenBSD. We keep our own copy rather than using sys/queue.h, since some platforms don't have a sys/queue.h, and the ones that do have diverged in incompatible - ways. (CIRCLEQ or no CIRCLEQ? SIMPLQ or STAILQ?) + ways. (CIRCLEQ or no CIRCLEQ? SIMPLQ or STAILQ?) We also rename + the identifiers with a TOR_ prefix to avoid conflicts with + the system headers. curve25519_donna/*.c diff --git a/src/ext/tor_queue.h b/src/ext/tor_queue.h index 595e4a3423..f05e48c18e 100644 --- a/src/ext/tor_queue.h +++ b/src/ext/tor_queue.h @@ -32,8 +32,8 @@ * @(#)queue.h 8.5 (Berkeley) 8/20/94 */ -#ifndef _SYS_QUEUE_H_ -#define _SYS_QUEUE_H_ +#ifndef TOR_QUEUE_H_ +#define TOR_QUEUE_H_ /* * This file defines five types of data structures: singly-linked lists, @@ -83,78 +83,73 @@ */ #if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC)) -#define _Q_INVALIDATE(a) (a) = ((void *)-1) +#define TOR_Q_INVALIDATE_(a) (a) = ((void *)-1) #else -#define _Q_INVALIDATE(a) +#define TOR_Q_INVALIDATE_(a) #endif /* * Singly-linked List definitions. */ -#define SLIST_HEAD(name, type) \ +#define TOR_SLIST_HEAD(name, type) \ struct name { \ struct type *slh_first; /* first element */ \ } -#define SLIST_HEAD_INITIALIZER(head) \ +#define TOR_SLIST_HEAD_INITIALIZER(head) \ { NULL } -/* XXXX This macro name conflicts with a typedef in winnt.h, so Tor - * has to redefine it. */ #define TOR_SLIST_ENTRY(type) \ struct { \ struct type *sle_next; /* next element */ \ } -#ifndef _WIN32 -#define SLIST_ENTRY(type) TOR_SLIST_ENTRY(type) -#endif /* * Singly-linked List access methods. */ -#define SLIST_FIRST(head) ((head)->slh_first) -#define SLIST_END(head) NULL -#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) -#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) - -#define SLIST_FOREACH(var, head, field) \ - for((var) = SLIST_FIRST(head); \ - (var) != SLIST_END(head); \ - (var) = SLIST_NEXT(var, field)) - -#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = SLIST_FIRST(head); \ - (var) && ((tvar) = SLIST_NEXT(var, field), 1); \ +#define TOR_SLIST_FIRST(head) ((head)->slh_first) +#define TOR_SLIST_END(head) NULL +#define TOR_SLIST_EMPTY(head) (SLIST_FIRST(head) == TOR_SLIST_END(head)) +#define TOR_SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define TOR_SLIST_FOREACH(var, head, field) \ + for((var) = TOR_SLIST_FIRST(head); \ + (var) != TOR_SLIST_END(head); \ + (var) = TOR_SLIST_NEXT(var, field)) + +#define TOR_SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TOR_SLIST_FIRST(head); \ + (var) && ((tvar) = TOR_SLIST_NEXT(var, field), 1); \ (var) = (tvar)) /* * Singly-linked List functions. */ -#define SLIST_INIT(head) { \ - SLIST_FIRST(head) = SLIST_END(head); \ +#define TOR_SLIST_INIT(head) { \ + TOR_SLIST_FIRST(head) = TOR_SLIST_END(head); \ } -#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ +#define TOR_SLIST_INSERT_AFTER(slistelm, elm, field) do { \ (elm)->field.sle_next = (slistelm)->field.sle_next; \ (slistelm)->field.sle_next = (elm); \ } while (0) -#define SLIST_INSERT_HEAD(head, elm, field) do { \ +#define TOR_SLIST_INSERT_HEAD(head, elm, field) do { \ (elm)->field.sle_next = (head)->slh_first; \ (head)->slh_first = (elm); \ } while (0) -#define SLIST_REMOVE_AFTER(elm, field) do { \ +#define TOR_SLIST_REMOVE_AFTER(elm, field) do { \ (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \ } while (0) -#define SLIST_REMOVE_HEAD(head, field) do { \ +#define TOR_SLIST_REMOVE_HEAD(head, field) do { \ (head)->slh_first = (head)->slh_first->field.sle_next; \ } while (0) -#define SLIST_REMOVE(head, elm, type, field) do { \ +#define TOR_SLIST_REMOVE(head, elm, type, field) do { \ if ((head)->slh_first == (elm)) { \ - SLIST_REMOVE_HEAD((head), field); \ + TOR_SLIST_REMOVE_HEAD((head), field); \ } else { \ struct type *curelm = (head)->slh_first; \ \ @@ -162,22 +157,22 @@ struct { \ curelm = curelm->field.sle_next; \ curelm->field.sle_next = \ curelm->field.sle_next->field.sle_next; \ - _Q_INVALIDATE((elm)->field.sle_next); \ + TOR_Q_INVALIDATE_((elm)->field.sle_next); \ } \ } while (0) /* * List definitions. */ -#define LIST_HEAD(name, type) \ +#define TOR_LIST_HEAD(name, type) \ struct name { \ struct type *lh_first; /* first element */ \ } -#define LIST_HEAD_INITIALIZER(head) \ +#define TOR_LIST_HEAD_INITIALIZER(head) \ { NULL } -#define LIST_ENTRY(type) \ +#define TOR_LIST_ENTRY(type) \ struct { \ struct type *le_next; /* next element */ \ struct type **le_prev; /* address of previous next element */ \ @@ -186,29 +181,29 @@ struct { \ /* * List access methods */ -#define LIST_FIRST(head) ((head)->lh_first) -#define LIST_END(head) NULL -#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head)) -#define LIST_NEXT(elm, field) ((elm)->field.le_next) - -#define LIST_FOREACH(var, head, field) \ - for((var) = LIST_FIRST(head); \ - (var)!= LIST_END(head); \ - (var) = LIST_NEXT(var, field)) - -#define LIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = LIST_FIRST(head); \ - (var) && ((tvar) = LIST_NEXT(var, field), 1); \ +#define TOR_LIST_FIRST(head) ((head)->lh_first) +#define TOR_LIST_END(head) NULL +#define TOR_LIST_EMPTY(head) (TOR_LIST_FIRST(head) == TOR_LIST_END(head)) +#define TOR_LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define TOR_LIST_FOREACH(var, head, field) \ + for((var) = TOR_LIST_FIRST(head); \ + (var)!= TOR_LIST_END(head); \ + (var) = TOR_LIST_NEXT(var, field)) + +#define TOR_LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TOR_LIST_FIRST(head); \ + (var) && ((tvar) = TOR_LIST_NEXT(var, field), 1); \ (var) = (tvar)) /* * List functions. */ -#define LIST_INIT(head) do { \ - LIST_FIRST(head) = LIST_END(head); \ +#define TOR_LIST_INIT(head) do { \ + TOR_LIST_FIRST(head) = TOR_LIST_END(head); \ } while (0) -#define LIST_INSERT_AFTER(listelm, elm, field) do { \ +#define TOR_LIST_INSERT_AFTER(listelm, elm, field) do { \ if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ (listelm)->field.le_next->field.le_prev = \ &(elm)->field.le_next; \ @@ -216,52 +211,52 @@ struct { \ (elm)->field.le_prev = &(listelm)->field.le_next; \ } while (0) -#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ +#define TOR_LIST_INSERT_BEFORE(listelm, elm, field) do { \ (elm)->field.le_prev = (listelm)->field.le_prev; \ (elm)->field.le_next = (listelm); \ *(listelm)->field.le_prev = (elm); \ (listelm)->field.le_prev = &(elm)->field.le_next; \ } while (0) -#define LIST_INSERT_HEAD(head, elm, field) do { \ +#define TOR_LIST_INSERT_HEAD(head, elm, field) do { \ if (((elm)->field.le_next = (head)->lh_first) != NULL) \ (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ (head)->lh_first = (elm); \ (elm)->field.le_prev = &(head)->lh_first; \ } while (0) -#define LIST_REMOVE(elm, field) do { \ +#define TOR_LIST_REMOVE(elm, field) do { \ if ((elm)->field.le_next != NULL) \ (elm)->field.le_next->field.le_prev = \ (elm)->field.le_prev; \ *(elm)->field.le_prev = (elm)->field.le_next; \ - _Q_INVALIDATE((elm)->field.le_prev); \ - _Q_INVALIDATE((elm)->field.le_next); \ + TOR_Q_INVALIDATE_((elm)->field.le_prev); \ + TOR_Q_INVALIDATE_((elm)->field.le_next); \ } while (0) -#define LIST_REPLACE(elm, elm2, field) do { \ +#define TOR_LIST_REPLACE(elm, elm2, field) do { \ if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ (elm2)->field.le_next->field.le_prev = \ &(elm2)->field.le_next; \ (elm2)->field.le_prev = (elm)->field.le_prev; \ *(elm2)->field.le_prev = (elm2); \ - _Q_INVALIDATE((elm)->field.le_prev); \ - _Q_INVALIDATE((elm)->field.le_next); \ + TOR_Q_INVALIDATE_((elm)->field.le_prev); \ + TOR_Q_INVALIDATE_((elm)->field.le_next); \ } while (0) /* * Simple queue definitions. */ -#define SIMPLEQ_HEAD(name, type) \ +#define TOR_SIMPLEQ_HEAD(name, type) \ struct name { \ struct type *sqh_first; /* first element */ \ struct type **sqh_last; /* addr of last next element */ \ } -#define SIMPLEQ_HEAD_INITIALIZER(head) \ +#define TOR_SIMPLEQ_HEAD_INITIALIZER(head) \ { NULL, &(head).sqh_first } -#define SIMPLEQ_ENTRY(type) \ +#define TOR_SIMPLEQ_ENTRY(type) \ struct { \ struct type *sqe_next; /* next element */ \ } @@ -269,53 +264,53 @@ struct { \ /* * Simple queue access methods. */ -#define SIMPLEQ_FIRST(head) ((head)->sqh_first) -#define SIMPLEQ_END(head) NULL -#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) -#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) - -#define SIMPLEQ_FOREACH(var, head, field) \ - for((var) = SIMPLEQ_FIRST(head); \ - (var) != SIMPLEQ_END(head); \ - (var) = SIMPLEQ_NEXT(var, field)) - -#define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = SIMPLEQ_FIRST(head); \ - (var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1); \ +#define TOR_SIMPLEQ_FIRST(head) ((head)->sqh_first) +#define TOR_SIMPLEQ_END(head) NULL +#define TOR_SIMPLEQ_EMPTY(head) (TOR_SIMPLEQ_FIRST(head) == TOR_SIMPLEQ_END(head)) +#define TOR_SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) + +#define TOR_SIMPLEQ_FOREACH(var, head, field) \ + for((var) = TOR_SIMPLEQ_FIRST(head); \ + (var) != TOR_SIMPLEQ_END(head); \ + (var) = TOR_SIMPLEQ_NEXT(var, field)) + +#define TOR_SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TOR_SIMPLEQ_FIRST(head); \ + (var) && ((tvar) = TOR_SIMPLEQ_NEXT(var, field), 1); \ (var) = (tvar)) /* * Simple queue functions. */ -#define SIMPLEQ_INIT(head) do { \ +#define TOR_SIMPLEQ_INIT(head) do { \ (head)->sqh_first = NULL; \ (head)->sqh_last = &(head)->sqh_first; \ } while (0) -#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ +#define TOR_SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ (head)->sqh_last = &(elm)->field.sqe_next; \ (head)->sqh_first = (elm); \ } while (0) -#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ +#define TOR_SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ (elm)->field.sqe_next = NULL; \ *(head)->sqh_last = (elm); \ (head)->sqh_last = &(elm)->field.sqe_next; \ } while (0) -#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ +#define TOR_SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ (head)->sqh_last = &(elm)->field.sqe_next; \ (listelm)->field.sqe_next = (elm); \ } while (0) -#define SIMPLEQ_REMOVE_HEAD(head, field) do { \ +#define TOR_SIMPLEQ_REMOVE_HEAD(head, field) do { \ if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ (head)->sqh_last = &(head)->sqh_first; \ } while (0) -#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ +#define TOR_SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \ == NULL) \ (head)->sqh_last = &(elm)->field.sqe_next; \ @@ -324,16 +319,16 @@ struct { \ /* * Tail queue definitions. */ -#define TAILQ_HEAD(name, type) \ +#define TOR_TAILQ_HEAD(name, type) \ struct name { \ struct type *tqh_first; /* first element */ \ struct type **tqh_last; /* addr of last next element */ \ } -#define TAILQ_HEAD_INITIALIZER(head) \ +#define TOR_TAILQ_HEAD_INITIALIZER(head) \ { NULL, &(head).tqh_first } -#define TAILQ_ENTRY(type) \ +#define TOR_TAILQ_ENTRY(type) \ struct { \ struct type *tqe_next; /* next element */ \ struct type **tqe_prev; /* address of previous next element */ \ @@ -342,49 +337,49 @@ struct { \ /* * tail queue access methods */ -#define TAILQ_FIRST(head) ((head)->tqh_first) -#define TAILQ_END(head) NULL -#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) -#define TAILQ_LAST(head, headname) \ +#define TOR_TAILQ_FIRST(head) ((head)->tqh_first) +#define TOR_TAILQ_END(head) NULL +#define TOR_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) +#define TOR_TAILQ_LAST(head, headname) \ (*(((struct headname *)((head)->tqh_last))->tqh_last)) /* XXX */ -#define TAILQ_PREV(elm, headname, field) \ +#define TOR_TAILQ_PREV(elm, headname, field) \ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) -#define TAILQ_EMPTY(head) \ - (TAILQ_FIRST(head) == TAILQ_END(head)) - -#define TAILQ_FOREACH(var, head, field) \ - for((var) = TAILQ_FIRST(head); \ - (var) != TAILQ_END(head); \ - (var) = TAILQ_NEXT(var, field)) - -#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = TAILQ_FIRST(head); \ - (var) != TAILQ_END(head) && \ - ((tvar) = TAILQ_NEXT(var, field), 1); \ +#define TOR_TAILQ_EMPTY(head) \ + (TOR_TAILQ_FIRST(head) == TOR_TAILQ_END(head)) + +#define TOR_TAILQ_FOREACH(var, head, field) \ + for((var) = TOR_TAILQ_FIRST(head); \ + (var) != TOR_TAILQ_END(head); \ + (var) = TOR_TAILQ_NEXT(var, field)) + +#define TOR_TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TOR_TAILQ_FIRST(head); \ + (var) != TOR_TAILQ_END(head) && \ + ((tvar) = TOR_TAILQ_NEXT(var, field), 1); \ (var) = (tvar)) -#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ - for((var) = TAILQ_LAST(head, headname); \ - (var) != TAILQ_END(head); \ - (var) = TAILQ_PREV(var, headname, field)) +#define TOR_TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for((var) = TOR_TAILQ_LAST(head, headname); \ + (var) != TOR_TAILQ_END(head); \ + (var) = TOR_TAILQ_PREV(var, headname, field)) -#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ - for ((var) = TAILQ_LAST(head, headname); \ - (var) != TAILQ_END(head) && \ - ((tvar) = TAILQ_PREV(var, headname, field), 1); \ +#define TOR_TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TOR_TAILQ_LAST(head, headname); \ + (var) != TOR_TAILQ_END(head) && \ + ((tvar) = TOR_TAILQ_PREV(var, headname, field), 1); \ (var) = (tvar)) /* * Tail queue functions. */ -#define TAILQ_INIT(head) do { \ +#define TOR_TAILQ_INIT(head) do { \ (head)->tqh_first = NULL; \ (head)->tqh_last = &(head)->tqh_first; \ } while (0) -#define TAILQ_INSERT_HEAD(head, elm, field) do { \ +#define TOR_TAILQ_INSERT_HEAD(head, elm, field) do { \ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ (head)->tqh_first->field.tqe_prev = \ &(elm)->field.tqe_next; \ @@ -394,14 +389,14 @@ struct { \ (elm)->field.tqe_prev = &(head)->tqh_first; \ } while (0) -#define TAILQ_INSERT_TAIL(head, elm, field) do { \ +#define TOR_TAILQ_INSERT_TAIL(head, elm, field) do { \ (elm)->field.tqe_next = NULL; \ (elm)->field.tqe_prev = (head)->tqh_last; \ *(head)->tqh_last = (elm); \ (head)->tqh_last = &(elm)->field.tqe_next; \ } while (0) -#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ +#define TOR_TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ (elm)->field.tqe_next->field.tqe_prev = \ &(elm)->field.tqe_next; \ @@ -411,25 +406,25 @@ struct { \ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ } while (0) -#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ +#define TOR_TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ (elm)->field.tqe_next = (listelm); \ *(listelm)->field.tqe_prev = (elm); \ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ } while (0) -#define TAILQ_REMOVE(head, elm, field) do { \ +#define TOR_TAILQ_REMOVE(head, elm, field) do { \ if (((elm)->field.tqe_next) != NULL) \ (elm)->field.tqe_next->field.tqe_prev = \ (elm)->field.tqe_prev; \ else \ (head)->tqh_last = (elm)->field.tqe_prev; \ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ - _Q_INVALIDATE((elm)->field.tqe_prev); \ - _Q_INVALIDATE((elm)->field.tqe_next); \ + TOR_Q_INVALIDATE_((elm)->field.tqe_prev); \ + TOR_Q_INVALIDATE_((elm)->field.tqe_next); \ } while (0) -#define TAILQ_REPLACE(head, elm, elm2, field) do { \ +#define TOR_TAILQ_REPLACE(head, elm, elm2, field) do { \ if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ (elm2)->field.tqe_next->field.tqe_prev = \ &(elm2)->field.tqe_next; \ @@ -437,23 +432,23 @@ struct { \ (head)->tqh_last = &(elm2)->field.tqe_next; \ (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ *(elm2)->field.tqe_prev = (elm2); \ - _Q_INVALIDATE((elm)->field.tqe_prev); \ - _Q_INVALIDATE((elm)->field.tqe_next); \ + TOR_Q_INVALIDATE_((elm)->field.tqe_prev); \ + TOR_Q_INVALIDATE_((elm)->field.tqe_next); \ } while (0) /* * Circular queue definitions. */ -#define CIRCLEQ_HEAD(name, type) \ +#define TOR_CIRCLEQ_HEAD(name, type) \ struct name { \ struct type *cqh_first; /* first element */ \ struct type *cqh_last; /* last element */ \ } -#define CIRCLEQ_HEAD_INITIALIZER(head) \ - { CIRCLEQ_END(&head), CIRCLEQ_END(&head) } +#define TOR_CIRCLEQ_HEAD_INITIALIZER(head) \ + { TOR_CIRCLEQ_END(&head), TOR_CIRCLEQ_END(&head) } -#define CIRCLEQ_ENTRY(type) \ +#define TOR_CIRCLEQ_ENTRY(type) \ struct { \ struct type *cqe_next; /* next element */ \ struct type *cqe_prev; /* previous element */ \ @@ -462,112 +457,112 @@ struct { \ /* * Circular queue access methods */ -#define CIRCLEQ_FIRST(head) ((head)->cqh_first) -#define CIRCLEQ_LAST(head) ((head)->cqh_last) -#define CIRCLEQ_END(head) ((void *)(head)) -#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) -#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) -#define CIRCLEQ_EMPTY(head) \ - (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head)) - -#define CIRCLEQ_FOREACH(var, head, field) \ - for((var) = CIRCLEQ_FIRST(head); \ - (var) != CIRCLEQ_END(head); \ - (var) = CIRCLEQ_NEXT(var, field)) - -#define CIRCLEQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = CIRCLEQ_FIRST(head); \ - (var) != CIRCLEQ_END(head) && \ - ((tvar) = CIRCLEQ_NEXT(var, field), 1); \ +#define TOR_CIRCLEQ_FIRST(head) ((head)->cqh_first) +#define TOR_CIRCLEQ_LAST(head) ((head)->cqh_last) +#define TOR_CIRCLEQ_END(head) ((void *)(head)) +#define TOR_CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) +#define TOR_CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) +#define TOR_CIRCLEQ_EMPTY(head) \ + (TOR_CIRCLEQ_FIRST(head) == TOR_CIRCLEQ_END(head)) + +#define TOR_CIRCLEQ_FOREACH(var, head, field) \ + for((var) = TOR_CIRCLEQ_FIRST(head); \ + (var) != TOR_CIRCLEQ_END(head); \ + (var) = TOR_CIRCLEQ_NEXT(var, field)) + +#define TOR_CIRCLEQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TOR_CIRCLEQ_FIRST(head); \ + (var) != TOR_CIRCLEQ_END(head) && \ + ((tvar) = TOR_CIRCLEQ_NEXT(var, field), 1); \ (var) = (tvar)) -#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ - for((var) = CIRCLEQ_LAST(head); \ - (var) != CIRCLEQ_END(head); \ - (var) = CIRCLEQ_PREV(var, field)) +#define TOR_CIRCLEQ_FOREACH_REVERSE(var, head, field) \ + for((var) = TOR_CIRCLEQ_LAST(head); \ + (var) != TOR_CIRCLEQ_END(head); \ + (var) = TOR_CIRCLEQ_PREV(var, field)) -#define CIRCLEQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ - for ((var) = CIRCLEQ_LAST(head, headname); \ - (var) != CIRCLEQ_END(head) && \ - ((tvar) = CIRCLEQ_PREV(var, headname, field), 1); \ +#define TOR_CIRCLEQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TOR_CIRCLEQ_LAST(head, headname); \ + (var) != TOR_CIRCLEQ_END(head) && \ + ((tvar) = TOR_CIRCLEQ_PREV(var, headname, field), 1); \ (var) = (tvar)) /* * Circular queue functions. */ -#define CIRCLEQ_INIT(head) do { \ - (head)->cqh_first = CIRCLEQ_END(head); \ - (head)->cqh_last = CIRCLEQ_END(head); \ +#define TOR_CIRCLEQ_INIT(head) do { \ + (head)->cqh_first = TOR_CIRCLEQ_END(head); \ + (head)->cqh_last = TOR_CIRCLEQ_END(head); \ } while (0) -#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ +#define TOR_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ (elm)->field.cqe_next = (listelm)->field.cqe_next; \ (elm)->field.cqe_prev = (listelm); \ - if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \ + if ((listelm)->field.cqe_next == TOR_CIRCLEQ_END(head)) \ (head)->cqh_last = (elm); \ else \ (listelm)->field.cqe_next->field.cqe_prev = (elm); \ (listelm)->field.cqe_next = (elm); \ } while (0) -#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ +#define TOR_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ (elm)->field.cqe_next = (listelm); \ (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ - if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \ + if ((listelm)->field.cqe_prev == TOR_CIRCLEQ_END(head)) \ (head)->cqh_first = (elm); \ else \ (listelm)->field.cqe_prev->field.cqe_next = (elm); \ (listelm)->field.cqe_prev = (elm); \ } while (0) -#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ +#define TOR_CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ (elm)->field.cqe_next = (head)->cqh_first; \ - (elm)->field.cqe_prev = CIRCLEQ_END(head); \ - if ((head)->cqh_last == CIRCLEQ_END(head)) \ + (elm)->field.cqe_prev = TOR_CIRCLEQ_END(head); \ + if ((head)->cqh_last == TOR_CIRCLEQ_END(head)) \ (head)->cqh_last = (elm); \ else \ (head)->cqh_first->field.cqe_prev = (elm); \ (head)->cqh_first = (elm); \ } while (0) -#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.cqe_next = CIRCLEQ_END(head); \ +#define TOR_CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.cqe_next = TOR_CIRCLEQ_END(head); \ (elm)->field.cqe_prev = (head)->cqh_last; \ - if ((head)->cqh_first == CIRCLEQ_END(head)) \ + if ((head)->cqh_first == TOR_CIRCLEQ_END(head)) \ (head)->cqh_first = (elm); \ else \ (head)->cqh_last->field.cqe_next = (elm); \ (head)->cqh_last = (elm); \ } while (0) -#define CIRCLEQ_REMOVE(head, elm, field) do { \ - if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \ +#define TOR_CIRCLEQ_REMOVE(head, elm, field) do { \ + if ((elm)->field.cqe_next == TOR_CIRCLEQ_END(head)) \ (head)->cqh_last = (elm)->field.cqe_prev; \ else \ (elm)->field.cqe_next->field.cqe_prev = \ (elm)->field.cqe_prev; \ - if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \ + if ((elm)->field.cqe_prev == TOR_CIRCLEQ_END(head)) \ (head)->cqh_first = (elm)->field.cqe_next; \ else \ (elm)->field.cqe_prev->field.cqe_next = \ (elm)->field.cqe_next; \ - _Q_INVALIDATE((elm)->field.cqe_prev); \ - _Q_INVALIDATE((elm)->field.cqe_next); \ + TOR_Q_INVALIDATE_((elm)->field.cqe_prev); \ + TOR_Q_INVALIDATE_((elm)->field.cqe_next); \ } while (0) -#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ +#define TOR_CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \ - CIRCLEQ_END(head)) \ + TOR_CIRCLEQ_END(head)) \ (head).cqh_last = (elm2); \ else \ (elm2)->field.cqe_next->field.cqe_prev = (elm2); \ if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \ - CIRCLEQ_END(head)) \ + TOR_CIRCLEQ_END(head)) \ (head).cqh_first = (elm2); \ else \ (elm2)->field.cqe_prev->field.cqe_next = (elm2); \ - _Q_INVALIDATE((elm)->field.cqe_prev); \ - _Q_INVALIDATE((elm)->field.cqe_next); \ + TOR_Q_INVALIDATE_((elm)->field.cqe_prev); \ + TOR_Q_INVALIDATE_((elm)->field.cqe_next); \ } while (0) #endif /* !_SYS_QUEUE_H_ */ diff --git a/src/or/channel.c b/src/or/channel.c index 7781622977..b30e5483cf 100644 --- a/src/or/channel.c +++ b/src/or/channel.c @@ -33,7 +33,7 @@ typedef struct cell_queue_entry_s cell_queue_entry_t; struct cell_queue_entry_s { - SIMPLEQ_ENTRY(cell_queue_entry_s) next; + TOR_SIMPLEQ_ENTRY(cell_queue_entry_s) next; enum { CELL_QUEUE_FIXED, CELL_QUEUE_VAR, @@ -89,7 +89,7 @@ HT_HEAD(channel_idmap, channel_idmap_entry_s) channel_identity_map = typedef struct channel_idmap_entry_s { HT_ENTRY(channel_idmap_entry_s) node; uint8_t digest[DIGEST_LEN]; - LIST_HEAD(channel_list_s, channel_s) channel_list; + TOR_LIST_HEAD(channel_list_s, channel_s) channel_list; } channel_idmap_entry_t; static INLINE unsigned @@ -554,10 +554,10 @@ channel_add_to_digest_map(channel_t *chan) if (! ent) { ent = tor_malloc(sizeof(channel_idmap_entry_t)); memcpy(ent->digest, chan->identity_digest, DIGEST_LEN); - LIST_INIT(&ent->channel_list); + TOR_LIST_INIT(&ent->channel_list); HT_INSERT(channel_idmap, &channel_identity_map, ent); } - LIST_INSERT_HEAD(&ent->channel_list, chan, next_with_same_id); + TOR_LIST_INSERT_HEAD(&ent->channel_list, chan, next_with_same_id); log_debug(LD_CHANNEL, "Added channel %p (global ID " U64_FORMAT ") " @@ -612,7 +612,7 @@ channel_remove_from_digest_map(channel_t *chan) #endif /* Pull it out of its list, wherever that list is */ - LIST_REMOVE(chan, next_with_same_id); + TOR_LIST_REMOVE(chan, next_with_same_id); memcpy(search.digest, chan->identity_digest, DIGEST_LEN); ent = HT_FIND(channel_idmap, &channel_identity_map, &search); @@ -621,7 +621,7 @@ channel_remove_from_digest_map(channel_t *chan) if (ent) { /* Okay, it's here */ - if (LIST_EMPTY(&ent->channel_list)) { + if (TOR_LIST_EMPTY(&ent->channel_list)) { HT_REMOVE(channel_idmap, &channel_identity_map, ent); tor_free(ent); } @@ -691,7 +691,7 @@ channel_find_by_remote_digest(const char *identity_digest) memcpy(search.digest, identity_digest, DIGEST_LEN); ent = HT_FIND(channel_idmap, &channel_identity_map, &search); if (ent) { - rv = LIST_FIRST(&ent->channel_list); + rv = TOR_LIST_FIRST(&ent->channel_list); } return rv; @@ -709,7 +709,7 @@ channel_next_with_digest(channel_t *chan) { tor_assert(chan); - return LIST_NEXT(chan, next_with_same_id); + return TOR_LIST_NEXT(chan, next_with_same_id); } /** @@ -735,8 +735,8 @@ channel_init(channel_t *chan) chan->next_circ_id = crypto_rand_int(1 << 15); /* Initialize queues. */ - SIMPLEQ_INIT(&chan->incoming_queue); - SIMPLEQ_INIT(&chan->outgoing_queue); + TOR_SIMPLEQ_INIT(&chan->incoming_queue); + TOR_SIMPLEQ_INIT(&chan->outgoing_queue); /* Initialize list entries. */ memset(&chan->next_with_same_id, 0, sizeof(chan->next_with_same_id)); @@ -879,16 +879,16 @@ channel_force_free(channel_t *chan) } /* We might still have a cell queue; kill it */ - SIMPLEQ_FOREACH_SAFE(cell, &chan->incoming_queue, next, cell_tmp) { + TOR_SIMPLEQ_FOREACH_SAFE(cell, &chan->incoming_queue, next, cell_tmp) { cell_queue_entry_free(cell, 0); } - SIMPLEQ_INIT(&chan->incoming_queue); + TOR_SIMPLEQ_INIT(&chan->incoming_queue); /* Outgoing cell queue is similar, but we can have to free packed cells */ - SIMPLEQ_FOREACH_SAFE(cell, &chan->outgoing_queue, next, cell_tmp) { + TOR_SIMPLEQ_FOREACH_SAFE(cell, &chan->outgoing_queue, next, cell_tmp) { cell_queue_entry_free(cell, 0); } - SIMPLEQ_INIT(&chan->outgoing_queue); + TOR_SIMPLEQ_INIT(&chan->outgoing_queue); tor_free(chan); } @@ -1051,7 +1051,7 @@ channel_set_cell_handlers(channel_t *chan, chan->var_cell_handler = var_cell_handler; /* Re-run the queue if we have one and there's any reason to */ - if (! SIMPLEQ_EMPTY(&chan->incoming_queue) && + if (! TOR_SIMPLEQ_EMPTY(&chan->incoming_queue) && try_again && (chan->cell_handler || chan->var_cell_handler)) channel_process_cells(chan); @@ -1686,7 +1686,7 @@ channel_write_cell_queue_entry(channel_t *chan, cell_queue_entry_t *q) } /* Can we send it right out? If so, try */ - if (SIMPLEQ_EMPTY(&chan->outgoing_queue) && + if (TOR_SIMPLEQ_EMPTY(&chan->outgoing_queue) && chan->state == CHANNEL_STATE_OPEN) { /* Pick the right write function for this cell type and save the result */ switch (q->type) { @@ -1728,7 +1728,7 @@ channel_write_cell_queue_entry(channel_t *chan, cell_queue_entry_t *q) * used the stack. */ tmp = cell_queue_entry_dup(q); - SIMPLEQ_INSERT_TAIL(&chan->outgoing_queue, tmp, next); + TOR_SIMPLEQ_INSERT_TAIL(&chan->outgoing_queue, tmp, next); /* Try to process the queue? */ if (chan->state == CHANNEL_STATE_OPEN) channel_flush_cells(chan); } @@ -1914,15 +1914,15 @@ channel_change_state(channel_t *chan, channel_state_t to_state) channel_do_open_actions(chan); /* Check for queued cells to process */ - if (! SIMPLEQ_EMPTY(&chan->incoming_queue)) + if (! TOR_SIMPLEQ_EMPTY(&chan->incoming_queue)) channel_process_cells(chan); - if (! SIMPLEQ_EMPTY(&chan->outgoing_queue)) + if (! TOR_SIMPLEQ_EMPTY(&chan->outgoing_queue)) channel_flush_cells(chan); } else if (to_state == CHANNEL_STATE_CLOSED || to_state == CHANNEL_STATE_ERROR) { /* Assert that all queues are empty */ - tor_assert(SIMPLEQ_EMPTY(&chan->incoming_queue)); - tor_assert(SIMPLEQ_EMPTY(&chan->outgoing_queue)); + tor_assert(TOR_SIMPLEQ_EMPTY(&chan->incoming_queue)); + tor_assert(TOR_SIMPLEQ_EMPTY(&chan->outgoing_queue)); } } @@ -2096,7 +2096,7 @@ channel_flush_some_cells_from_outgoing_queue(channel_t *chan, /* If we aren't in CHANNEL_STATE_OPEN, nothing goes through */ if (chan->state == CHANNEL_STATE_OPEN) { while ((unlimited || num_cells > flushed) && - NULL != (q = SIMPLEQ_FIRST(&chan->outgoing_queue))) { + NULL != (q = TOR_SIMPLEQ_FIRST(&chan->outgoing_queue))) { if (1) { /* @@ -2185,7 +2185,7 @@ channel_flush_some_cells_from_outgoing_queue(channel_t *chan, } /* if q got NULLed out, we used it and should remove the queue entry */ - if (!q) SIMPLEQ_REMOVE_HEAD(&chan->outgoing_queue, next); + if (!q) TOR_SIMPLEQ_REMOVE_HEAD(&chan->outgoing_queue, next); /* No cell removed from list, so we can't go on any further */ else break; } @@ -2193,7 +2193,7 @@ channel_flush_some_cells_from_outgoing_queue(channel_t *chan, } /* Did we drain the queue? */ - if (SIMPLEQ_EMPTY(&chan->outgoing_queue)) { + if (TOR_SIMPLEQ_EMPTY(&chan->outgoing_queue)) { channel_timestamp_drained(chan); } @@ -2227,7 +2227,7 @@ channel_more_to_flush(channel_t *chan) tor_assert(chan); /* Check if we have any queued */ - if (! SIMPLEQ_EMPTY(&chan->incoming_queue)) + if (! TOR_SIMPLEQ_EMPTY(&chan->incoming_queue)) return 1; /* Check if any circuits would like to queue some */ @@ -2435,13 +2435,13 @@ channel_process_cells(channel_t *chan) if (!(chan->cell_handler || chan->var_cell_handler)) return; /* Nothing we can do if we have no cells */ - if (SIMPLEQ_EMPTY(&chan->incoming_queue)) return; + if (TOR_SIMPLEQ_EMPTY(&chan->incoming_queue)) return; /* * Process cells until we're done or find one we have no current handler * for. */ - while (NULL != (q = SIMPLEQ_FIRST(&chan->incoming_queue))) { + while (NULL != (q = TOR_SIMPLEQ_FIRST(&chan->incoming_queue))) { tor_assert(q); tor_assert(q->type == CELL_QUEUE_FIXED || q->type == CELL_QUEUE_VAR); @@ -2449,7 +2449,7 @@ channel_process_cells(channel_t *chan) if (q->type == CELL_QUEUE_FIXED && chan->cell_handler) { /* Handle a fixed-length cell */ - SIMPLEQ_REMOVE_HEAD(&chan->incoming_queue, next); + TOR_SIMPLEQ_REMOVE_HEAD(&chan->incoming_queue, next); tor_assert(q->u.fixed.cell); log_debug(LD_CHANNEL, "Processing incoming cell_t %p for channel %p (global ID " @@ -2461,7 +2461,7 @@ channel_process_cells(channel_t *chan) } else if (q->type == CELL_QUEUE_VAR && chan->var_cell_handler) { /* Handle a variable-length cell */ - SIMPLEQ_REMOVE_HEAD(&chan->incoming_queue, next); + TOR_SIMPLEQ_REMOVE_HEAD(&chan->incoming_queue, next); tor_assert(q->u.var.var_cell); log_debug(LD_CHANNEL, "Processing incoming var_cell_t %p for channel %p (global ID " @@ -2496,7 +2496,7 @@ channel_queue_cell(channel_t *chan, cell_t *cell) /* Do we need to queue it, or can we just call the handler right away? */ if (!(chan->cell_handler)) need_to_queue = 1; - if (! SIMPLEQ_EMPTY(&chan->incoming_queue)) + if (! TOR_SIMPLEQ_EMPTY(&chan->incoming_queue)) need_to_queue = 1; /* Timestamp for receiving */ @@ -2522,7 +2522,7 @@ channel_queue_cell(channel_t *chan, cell_t *cell) "(global ID " U64_FORMAT ")", cell, chan, U64_PRINTF_ARG(chan->global_identifier)); - SIMPLEQ_INSERT_TAIL(&chan->incoming_queue, q, next); + TOR_SIMPLEQ_INSERT_TAIL(&chan->incoming_queue, q, next); if (chan->cell_handler || chan->var_cell_handler) { channel_process_cells(chan); @@ -2549,7 +2549,7 @@ channel_queue_var_cell(channel_t *chan, var_cell_t *var_cell) /* Do we need to queue it, or can we just call the handler right away? */ if (!(chan->var_cell_handler)) need_to_queue = 1; - if (! SIMPLEQ_EMPTY(&chan->incoming_queue)) + if (! TOR_SIMPLEQ_EMPTY(&chan->incoming_queue)) need_to_queue = 1; /* Timestamp for receiving */ @@ -2575,7 +2575,7 @@ channel_queue_var_cell(channel_t *chan, var_cell_t *var_cell) "(global ID " U64_FORMAT ")", var_cell, chan, U64_PRINTF_ARG(chan->global_identifier)); - SIMPLEQ_INSERT_TAIL(&chan->incoming_queue, q, next); + TOR_SIMPLEQ_INSERT_TAIL(&chan->incoming_queue, q, next); if (chan->cell_handler || chan->var_cell_handler) { channel_process_cells(chan); @@ -3115,7 +3115,7 @@ chan_cell_queue_len(const chan_cell_queue_t *queue) { int r = 0; cell_queue_entry_t *cell; - SIMPLEQ_FOREACH(cell, queue, next) + TOR_SIMPLEQ_FOREACH(cell, queue, next) ++r; return r; } @@ -3504,7 +3504,7 @@ channel_has_queued_writes(channel_t *chan) tor_assert(chan); tor_assert(chan->has_queued_writes); - if (! SIMPLEQ_EMPTY(&chan->outgoing_queue)) { + if (! TOR_SIMPLEQ_EMPTY(&chan->outgoing_queue)) { has_writes = 1; } else { /* Check with the lower layer */ diff --git a/src/or/channel.h b/src/or/channel.h index 31bd519474..ec79888063 100644 --- a/src/or/channel.h +++ b/src/or/channel.h @@ -19,7 +19,7 @@ typedef void (*channel_cell_handler_fn_ptr)(channel_t *, cell_t *); typedef void (*channel_var_cell_handler_fn_ptr)(channel_t *, var_cell_t *); struct cell_queue_entry_s; -SIMPLEQ_HEAD(chan_cell_queue, cell_queue_entry_s) incoming_queue; +TOR_SIMPLEQ_HEAD(chan_cell_queue, cell_queue_entry_s) incoming_queue; typedef struct chan_cell_queue chan_cell_queue_t; /* @@ -125,7 +125,7 @@ struct channel_s { * Linked list of channels with the same identity digest, for the * digest->channel map */ - LIST_ENTRY(channel_s) next_with_same_id; + TOR_LIST_ENTRY(channel_s) next_with_same_id; /* List of incoming cells to handle */ chan_cell_queue_t incoming_queue; diff --git a/src/or/config.c b/src/or/config.c index 0e9c0fd6f1..dcd053ff62 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -331,6 +331,7 @@ static config_var_t option_vars_[] = { V(PathBiasExtremeUseRate, DOUBLE, "-1"), V(PathBiasScaleUseThreshold, INT, "-1"), + V(PathsNeededToBuildCircuits, DOUBLE, "-1"), OBSOLETE("PathlenCoinWeight"), V(PerConnBWBurst, MEMUNIT, "0"), V(PerConnBWRate, MEMUNIT, "0"), @@ -2392,6 +2393,18 @@ options_validate(or_options_t *old_options, or_options_t *options, return -1; } + if (options->PathsNeededToBuildCircuits >= 0.0) { + if (options->PathsNeededToBuildCircuits < 0.25) { + log_warn(LD_CONFIG, "PathsNeededToBuildCircuits is too low. Increasing " + "to 0.25"); + options->PathsNeededToBuildCircuits = 0.25; + } else if (options->PathsNeededToBuildCircuits < 0.95) { + log_warn(LD_CONFIG, "PathsNeededToBuildCircuits is too high. Decreasing " + "to 0.95"); + options->PathsNeededToBuildCircuits = 0.95; + } + } + if (options->MaxClientCircuitsPending <= 0 || options->MaxClientCircuitsPending > MAX_MAX_CLIENT_CIRCUITS_PENDING) { tor_asprintf(msg, diff --git a/src/or/nodelist.c b/src/or/nodelist.c index e444c73247..c2eb670e4d 100644 --- a/src/or/nodelist.c +++ b/src/or/nodelist.c @@ -1213,7 +1213,7 @@ static int have_min_dir_info = 0; static int need_to_update_have_min_dir_info = 1; /** String describing what we're missing before we have enough directory * info. */ -static char dir_info_status[128] = ""; +static char dir_info_status[256] = ""; /** Return true iff we have enough networkstatus and router information to * start building circuits. Right now, this means "more than half the @@ -1253,10 +1253,12 @@ get_dir_info_status_string(void) * descriptors for. Store the former in *<b>num_usable</b> and the latter in * *<b>num_present</b>. If <b>in_set</b> is non-NULL, only consider those * routers in <b>in_set</b>. If <b>exit_only</b> is true, only consider nodes - * with the Exit flag. + * with the Exit flag. If *descs_out is present, add a node_t for each + * usable descriptor to it. */ static void count_usable_descriptors(int *num_present, int *num_usable, + smartlist_t *descs_out, const networkstatus_t *consensus, const or_options_t *options, time_t now, routerset_t *in_set, int exit_only) @@ -1266,6 +1268,10 @@ count_usable_descriptors(int *num_present, int *num_usable, SMARTLIST_FOREACH_BEGIN(consensus->routerstatus_list, routerstatus_t *, rs) { + const node_t *node = node_get_by_id(rs->identity_digest); + if (!node) + continue; /* This would be a bug: every entry in the consensus is + * supposed to have a node. */ if (exit_only && ! rs->is_exit) continue; if (in_set && ! routerset_contains_routerstatus(in_set, rs, -1)) @@ -1282,6 +1288,8 @@ count_usable_descriptors(int *num_present, int *num_usable, /* we have the descriptor listed in the consensus. */ ++*num_present; } + if (descs_out) + smartlist_add(descs_out, (node_t*)node); } } SMARTLIST_FOREACH_END(rs); @@ -1291,6 +1299,66 @@ count_usable_descriptors(int *num_present, int *num_usable, md ? "microdesc" : "desc", exit_only ? " exits" : "s"); } +/** Return an extimate of which fraction of usable paths through the Tor + * network we have available for use. */ +static double +compute_frac_paths_available(const networkstatus_t *consensus, + const or_options_t *options, time_t now, + int *num_present_out, int *num_usable_out, + char **status_out) +{ + smartlist_t *guards = smartlist_new(); + smartlist_t *mid = smartlist_new(); + smartlist_t *exits = smartlist_new(); + smartlist_t *myexits= smartlist_new(); + double f_guard, f_mid, f_exit, f_myexit; + int np, nu; /* Ignored */ + + count_usable_descriptors(num_present_out, num_usable_out, + mid, consensus, options, now, NULL, 0); + if (options->EntryNodes) { + count_usable_descriptors(&np, &nu, guards, consensus, options, now, + options->EntryNodes, 0); + } else { + SMARTLIST_FOREACH(mid, const node_t *, node, { + if (node->is_possible_guard) + smartlist_add(guards, (node_t*)node); + }); + } + + count_usable_descriptors(&np, &nu, exits, consensus, options, now, + NULL, 1); + count_usable_descriptors(&np, &nu, myexits, consensus, options, now, + options->ExitNodes, 1); + + f_guard = frac_nodes_with_descriptors(guards, WEIGHT_FOR_GUARD); + f_mid = frac_nodes_with_descriptors(mid, WEIGHT_FOR_MID); + f_exit = frac_nodes_with_descriptors(exits, WEIGHT_FOR_EXIT); + f_myexit= frac_nodes_with_descriptors(myexits,WEIGHT_FOR_EXIT); + + smartlist_free(guards); + smartlist_free(mid); + smartlist_free(exits); + smartlist_free(myexits); + + /* This is a tricky point here: we don't want to make it easy for a + * directory to trickle exits to us until it learns which exits we have + * configured, so require that we have a threshold both of total exits + * and usable exits. */ + if (f_myexit < f_exit) + f_exit = f_myexit; + + tor_asprintf(status_out, + "%d%% of guards bw, " + "%d%% of midpoint bw, and " + "%d%% of exit bw", + (int)(f_guard*100), + (int)(f_mid*100), + (int)(f_exit*100)); + + return f_guard * f_mid * f_exit; +} + /** We just fetched a new set of descriptors. Compute how far through * the "loading descriptors" bootstrapping phase we are, so we can inform * the controller of our progress. */ @@ -1306,7 +1374,7 @@ count_loading_descriptors_progress(void) if (!consensus) return 0; /* can't count descriptors if we have no list of them */ - count_usable_descriptors(&num_present, &num_usable, + count_usable_descriptors(&num_present, &num_usable, NULL, consensus, get_options(), now, NULL, 0); if (num_usable == 0) @@ -1319,14 +1387,28 @@ count_loading_descriptors_progress(void) BOOTSTRAP_STATUS_LOADING_DESCRIPTORS)); } +/** Return the fraction of paths needed before we're willing to build + * circuits, as configured in <b>options</b>, or in the consensus <b>ns</b>. */ +static double +get_frac_paths_needed_for_circs(const or_options_t *options, + const networkstatus_t *ns) +{ +#define DFLT_PCT_USABLE_NEEDED 60 + if (options->PathsNeededToBuildCircuits >= 1.0) { + return options->PathsNeededToBuildCircuits; + } else { + return networkstatus_get_param(ns, "min_paths_for_circs_pct", + DFLT_PCT_USABLE_NEEDED, + 25, 95)/100.0; + } +} + /** Change the value of have_min_dir_info, setting it true iff we have enough * network and router information to build circuits. Clear the value of * need_to_update_have_min_dir_info. */ static void update_router_have_minimum_dir_info(void) { - int num_present = 0, num_usable=0; - int num_exit_present = 0, num_exit_usable = 0; time_t now = time(NULL); int res; const or_options_t *options = get_options(); @@ -1355,55 +1437,29 @@ update_router_have_minimum_dir_info(void) using_md = consensus->flavor == FLAV_MICRODESC; - count_usable_descriptors(&num_present, &num_usable, consensus, options, now, - NULL, 0); - count_usable_descriptors(&num_exit_present, &num_exit_usable, - consensus, options, now, options->ExitNodes, 1); - -/* What fraction of desired server descriptors do we need before we will - * build circuits? */ -#define FRAC_USABLE_NEEDED .75 -/* What fraction of desired _exit_ server descriptors do we need before we - * will build circuits? */ -#define FRAC_EXIT_USABLE_NEEDED .5 - - if (num_present < num_usable * FRAC_USABLE_NEEDED) { - tor_snprintf(dir_info_status, sizeof(dir_info_status), - "We have only %d/%d usable %sdescriptors.", - num_present, num_usable, using_md ? "micro" : ""); - res = 0; - control_event_bootstrap(BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS, 0); - goto done; - } else if (num_present < 2) { - tor_snprintf(dir_info_status, sizeof(dir_info_status), - "Only %d %sdescriptor%s here and believed reachable!", - num_present, using_md ? "micro" : "", num_present ? "" : "s"); - res = 0; - goto done; - } else if (num_exit_present < num_exit_usable * FRAC_EXIT_USABLE_NEEDED) { - tor_snprintf(dir_info_status, sizeof(dir_info_status), - "We have only %d/%d usable exit node descriptors.", - num_exit_present, num_exit_usable); - res = 0; - control_event_bootstrap(BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS, 0); - goto done; - } - - /* Check for entry nodes. */ - if (options->EntryNodes) { - count_usable_descriptors(&num_present, &num_usable, consensus, options, - now, options->EntryNodes, 0); + { + char *status = NULL; + int num_present=0, num_usable=0; + double paths = compute_frac_paths_available(consensus, options, now, + &num_present, &num_usable, + &status); - if (!num_usable || !num_present) { + if (paths < get_frac_paths_needed_for_circs(options,consensus)) { tor_snprintf(dir_info_status, sizeof(dir_info_status), - "We have only %d/%d usable entry node %sdescriptors.", - num_present, num_usable, using_md?"micro":""); + "We need more %sdescriptors: we have %d/%d, and " + "can only build %d%% of likely paths. (We have %s.)", + using_md?"micro":"", num_present, num_usable, + (int)(paths*100), status); + /* log_notice(LD_NET, "%s", dir_info_status); */ + tor_free(status); res = 0; + control_event_bootstrap(BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS, 0); goto done; } - } - res = 1; + tor_free(status); + res = 1; + } done: if (res && !have_min_dir_info) { diff --git a/src/or/onion.c b/src/or/onion.c index e4cdea6bb0..b9f5aa6c7d 100644 --- a/src/or/onion.c +++ b/src/or/onion.c @@ -26,7 +26,7 @@ /** Type for a linked list of circuits that are waiting for a free CPU worker * to process a waiting onion handshake. */ typedef struct onion_queue_t { - TAILQ_ENTRY(onion_queue_t) next; + TOR_TAILQ_ENTRY(onion_queue_t) next; or_circuit_t *circ; create_cell_t *onionskin; time_t when_added; @@ -36,8 +36,8 @@ typedef struct onion_queue_t { #define ONIONQUEUE_WAIT_CUTOFF 5 /** Queue of circuits waiting for CPU workers, or NULL if the list is empty.*/ -TAILQ_HEAD(onion_queue_head_t, onion_queue_t) ol_list = - TAILQ_HEAD_INITIALIZER(ol_list); +TOR_TAILQ_HEAD(onion_queue_head_t, onion_queue_t) ol_list = + TOR_TAILQ_HEAD_INITIALIZER(ol_list); /** Number of entries of each type currently in ol_list. */ static int ol_entries[MAX_ONION_HANDSHAKE_TYPE+1]; @@ -120,11 +120,11 @@ onion_pending_add(or_circuit_t *circ, create_cell_t *onionskin) ++ol_entries[onionskin->handshake_type]; circ->onionqueue_entry = tmp; - TAILQ_INSERT_TAIL(&ol_list, tmp, next); + TOR_TAILQ_INSERT_TAIL(&ol_list, tmp, next); /* cull elderly requests. */ while (1) { - onion_queue_t *head = TAILQ_FIRST(&ol_list); + onion_queue_t *head = TOR_TAILQ_FIRST(&ol_list); if (now - head->when_added < (time_t)ONIONQUEUE_WAIT_CUTOFF) break; @@ -145,7 +145,7 @@ or_circuit_t * onion_next_task(create_cell_t **onionskin_out) { or_circuit_t *circ; - onion_queue_t *head = TAILQ_FIRST(&ol_list); + onion_queue_t *head = TOR_TAILQ_FIRST(&ol_list); if (!head) return NULL; /* no onions pending, we're done */ @@ -184,7 +184,7 @@ onion_pending_remove(or_circuit_t *circ) static void onion_queue_entry_remove(onion_queue_t *victim) { - TAILQ_REMOVE(&ol_list, victim, next); + TOR_TAILQ_REMOVE(&ol_list, victim, next); if (victim->circ) victim->circ->onionqueue_entry = NULL; @@ -202,7 +202,7 @@ void clear_pending_onions(void) { onion_queue_t *victim; - while ((victim = TAILQ_FIRST(&ol_list))) { + while ((victim = TOR_TAILQ_FIRST(&ol_list))) { onion_queue_entry_remove(victim); } memset(ol_entries, 0, sizeof(ol_entries)); diff --git a/src/or/or.h b/src/or/or.h index cfcddba3b2..df933c353a 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -3946,6 +3946,9 @@ typedef struct { /** Autobool: should we use the ntor handshake if we can? */ int UseNTorHandshake; + + /** Fraction: */ + double PathsNeededToBuildCircuits; } or_options_t; /** Persistent state for an onion router, as saved to disk. */ diff --git a/src/or/routerlist.c b/src/or/routerlist.c index b294bfa080..5dd1a55dc5 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -42,6 +42,9 @@ /****************************************************************************/ /* static function prototypes */ +static int compute_weighted_bandwidths(const smartlist_t *sl, + bandwidth_weight_rule_t rule, + u64_dbl_t **bandwidths_out); static const routerstatus_t *router_pick_directory_server_impl( dirinfo_type_t auth, int flags); static const routerstatus_t *router_pick_trusteddirserver_impl( @@ -1681,9 +1684,35 @@ kb_to_bytes(uint32_t bw) * guards proportionally less. */ static const node_t * -smartlist_choose_node_by_bandwidth_weights(smartlist_t *sl, +smartlist_choose_node_by_bandwidth_weights(const smartlist_t *sl, bandwidth_weight_rule_t rule) { + u64_dbl_t *bandwidths=NULL; + + if (compute_weighted_bandwidths(sl, rule, &bandwidths) < 0) + return NULL; + + scale_array_elements_to_u64(bandwidths, smartlist_len(sl), + &sl_last_total_weighted_bw); + + { + int idx = choose_array_element_by_weight(bandwidths, + smartlist_len(sl)); + tor_free(bandwidths); + return idx < 0 ? NULL : smartlist_get(sl, idx); + } +} + +/** Given a list of routers and a weighting rule as in + * smartlist_choose_node_by_bandwidth_weights, compute weighted bandwidth + * values for each node and store them in a freshly allocated + * *<b>bandwidths_out</b> of the same length as <b>sl</b>, and holding results + * as doubles. Return 0 on success, -1 on failure. */ +static int +compute_weighted_bandwidths(const smartlist_t *sl, + bandwidth_weight_rule_t rule, + u64_dbl_t **bandwidths_out) +{ int64_t weight_scale; double Wg = -1, Wm = -1, We = -1, Wd = -1; double Wgb = -1, Wmb = -1, Web = -1, Wdb = -1; @@ -1702,7 +1731,7 @@ smartlist_choose_node_by_bandwidth_weights(smartlist_t *sl, "Empty routerlist passed in to consensus weight node " "selection for rule %s", bandwidth_weight_rule_to_string(rule)); - return NULL; + return -1; } weight_scale = circuit_build_times_get_bw_scale(NULL); @@ -1756,7 +1785,7 @@ smartlist_choose_node_by_bandwidth_weights(smartlist_t *sl, log_debug(LD_CIRC, "Got negative bandwidth weights. Defaulting to old selection" " algorithm."); - return NULL; // Use old algorithm. + return -1; // Use old algorithm. } Wg /= weight_scale; @@ -1786,7 +1815,7 @@ smartlist_choose_node_by_bandwidth_weights(smartlist_t *sl, log_warn(LD_BUG, "Consensus is not listing bandwidths. Defaulting back to " "old router selection algorithm."); - return NULL; + return -1; } this_bw = kb_to_bytes(node->rs->bandwidth); } else if (node->ri) { @@ -1819,20 +1848,53 @@ smartlist_choose_node_by_bandwidth_weights(smartlist_t *sl, sl_last_weighted_bw_of_me = (uint64_t) bandwidths[node_sl_idx].dbl; } SMARTLIST_FOREACH_END(node); - log_debug(LD_CIRC, "Choosing node for rule %s based on weights " + log_debug(LD_CIRC, "Generated weighted bandwidths for rule %s based " + "on weights " "Wg=%f Wm=%f We=%f Wd=%f with total bw "U64_FORMAT, bandwidth_weight_rule_to_string(rule), Wg, Wm, We, Wd, U64_PRINTF_ARG(weighted_bw)); - scale_array_elements_to_u64(bandwidths, smartlist_len(sl), - &sl_last_total_weighted_bw); + *bandwidths_out = bandwidths; - { - int idx = choose_array_element_by_weight(bandwidths, - smartlist_len(sl)); - tor_free(bandwidths); - return idx < 0 ? NULL : smartlist_get(sl, idx); + return 0; +} + +/** For all nodes in <b>sl</b>, return the fraction of those nodes, weighted + * by their weighted bandwidths with rule <b>rule</b>, for which we have + * descriptors. */ +double +frac_nodes_with_descriptors(const smartlist_t *sl, + bandwidth_weight_rule_t rule) +{ + u64_dbl_t *bandwidths = NULL; + double total, present; + + if (smartlist_len(sl) == 0) + return 0.0; + + if (compute_weighted_bandwidths(sl, rule, &bandwidths) < 0) { + int n_with_descs = 0; + SMARTLIST_FOREACH(sl, const node_t *, node, { + if (node_has_descriptor(node)) + n_with_descs++; + }); + return ((double)n_with_descs) / (double)smartlist_len(sl); } + + total = present = 0.0; + SMARTLIST_FOREACH_BEGIN(sl, const node_t *, node) { + const double bw = bandwidths[node_sl_idx].dbl; + total += bw; + if (node_has_descriptor(node)) + present += bw; + } SMARTLIST_FOREACH_END(node); + + tor_free(bandwidths); + + if (total < 1.0) + return 0; + + return present / total; } /** Helper function: @@ -1849,7 +1911,7 @@ smartlist_choose_node_by_bandwidth_weights(smartlist_t *sl, * guards proportionally less. */ static const node_t * -smartlist_choose_node_by_bandwidth(smartlist_t *sl, +smartlist_choose_node_by_bandwidth(const smartlist_t *sl, bandwidth_weight_rule_t rule) { unsigned int i; @@ -2055,7 +2117,7 @@ smartlist_choose_node_by_bandwidth(smartlist_t *sl, /** Choose a random element of status list <b>sl</b>, weighted by * the advertised bandwidth of each node */ const node_t * -node_sl_choose_by_bandwidth(smartlist_t *sl, +node_sl_choose_by_bandwidth(const smartlist_t *sl, bandwidth_weight_rule_t rule) { /*XXXX MOVE */ const node_t *ret; diff --git a/src/or/routerlist.h b/src/or/routerlist.h index 798cebc58e..1849fff31c 100644 --- a/src/or/routerlist.h +++ b/src/or/routerlist.h @@ -47,8 +47,10 @@ const routerinfo_t *routerlist_find_my_routerinfo(void); uint32_t router_get_advertised_bandwidth(const routerinfo_t *router); uint32_t router_get_advertised_bandwidth_capped(const routerinfo_t *router); -const node_t *node_sl_choose_by_bandwidth(smartlist_t *sl, +const node_t *node_sl_choose_by_bandwidth(const smartlist_t *sl, bandwidth_weight_rule_t rule); +double frac_nodes_with_descriptors(const smartlist_t *sl, + bandwidth_weight_rule_t rule); const node_t *router_choose_random_node(smartlist_t *excludedsmartlist, struct routerset_t *excludedset, |