summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Dingledine <arma@torproject.org>2003-12-13 01:42:44 +0000
committerRoger Dingledine <arma@torproject.org>2003-12-13 01:42:44 +0000
commit1ae84fcbc1d7ae02a00c749eeaa22d5b5f1fa722 (patch)
tree595b1c933eea06e76900a286bdf88a2c8005a65d
parent9c66e2bf9a9ced671a18c967d08f8a2320105bbe (diff)
downloadtor-1ae84fcbc1d7ae02a00c749eeaa22d5b5f1fa722.tar.gz
tor-1ae84fcbc1d7ae02a00c749eeaa22d5b5f1fa722.zip
add a 'smartlist' building block that picks random elements from a list
svn:r897
-rw-r--r--src/common/crypto.c1
-rw-r--r--src/common/util.c58
-rw-r--r--src/common/util.h12
3 files changed, 62 insertions, 9 deletions
diff --git a/src/common/crypto.c b/src/common/crypto.c
index 070a2a0cbc..17d9be19d2 100644
--- a/src/common/crypto.c
+++ b/src/common/crypto.c
@@ -1009,6 +1009,7 @@ void crypto_pseudo_rand(unsigned int n, unsigned char *to)
}
}
+/* return a pseudo random number between 0 and max-1 */
int crypto_pseudo_rand_int(unsigned int max) {
unsigned int val;
unsigned int cutoff;
diff --git a/src/common/util.c b/src/common/util.c
index c8ec2de230..11609e256a 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -33,7 +33,7 @@ void *tor_malloc_zero(size_t size) {
void *tor_realloc(void *ptr, size_t size) {
void *result;
-
+
result = realloc(ptr, size);
if (!result) {
log_fn(LOG_ERR, "Out of memory. Dying.");
@@ -64,6 +64,46 @@ char *tor_strndup(const char *s, size_t n) {
}
/*
+ * A simple smartlist interface to make an unordered list of acceptable
+ * nodes and then choose a random one.
+ * smartlist_create() mallocs the list, _free() frees the list,
+ * _add() adds an element, _remove() removes an element if it's there,
+ * _choose() returns a random element.
+ */
+
+smartlist_t *smartlist_create(int max_elements) {
+ smartlist_t *sl = tor_malloc(sizeof(smartlist_t));
+ sl->list = tor_malloc(sizeof(void *) * max_elements);
+ sl->num_used = 0;
+ sl->max = max_elements;
+ return sl;
+}
+
+void smartlist_free(smartlist_t *sl) {
+ free(sl->list);
+ free(sl);
+}
+
+/* add element to the list, but only if there's room */
+void smartlist_add(smartlist_t *sl, void *element) {
+ if(sl->num_used < sl->max)
+ sl->list[sl->num_used++] = element;
+}
+
+void smartlist_remove(smartlist_t *sl, void *element) {
+ int i;
+ for(i=0; i < sl->num_used; i++)
+ if(sl->list[i] == element)
+ sl->list[i] = sl->list[--sl->num_used]; /* swap with the end */
+}
+
+void *smartlist_choose(smartlist_t *sl) {
+ if(sl->num_used)
+ return sl->list[crypto_pseudo_rand_int(sl->num_used)];
+ return NULL; /* no elements to choose from */
+}
+
+/*
* String manipulation
*/
@@ -234,11 +274,11 @@ int read_all(int fd, char *buf, size_t count) {
void set_socket_nonblocking(int socket)
{
#ifdef MS_WINDOWS
- /* Yes means no and no means yes. Do you not want to be nonblocking? */
- int nonblocking = 0;
- ioctlsocket(socket, FIONBIO, (unsigned long*) &nonblocking);
+ /* Yes means no and no means yes. Do you not want to be nonblocking? */
+ int nonblocking = 0;
+ ioctlsocket(socket, FIONBIO, (unsigned long*) &nonblocking);
#else
- fcntl(socket, F_SETFL, O_NONBLOCK);
+ fcntl(socket, F_SETFL, O_NONBLOCK);
#endif
}
@@ -378,7 +418,7 @@ tor_socketpair(int family, int type, int protocol, int fd[2])
if (listener != -1)
close(listener);
if (connector != -1)
- close(connector);
+ close(connector);
if (acceptor != -1)
close(acceptor);
errno = save_errno;
@@ -514,7 +554,7 @@ char *read_file_to_str(const char *filename) {
log_fn(LOG_WARN,"Filename %s contains illegal characters.",filename);
return NULL;
}
-
+
if(stat(filename, &statbuf) < 0) {
log_fn(LOG_INFO,"Could not stat %s.",filename);
return NULL;
@@ -616,11 +656,11 @@ get_uname(void)
}
return uname_result;
}
-
+
void daemonize(void) {
#ifdef HAVE_DAEMON
if (daemon(0 /* chdir to / */,
- 0 /* Redirect std* to /dev/null */)) {
+ 0 /* Redirect std* to /dev/null */)) {
log_fn(LOG_ERR, "Daemon returned an error: %s", strerror(errno));
exit(1);
}
diff --git a/src/common/util.h b/src/common/util.h
index bc8ee06c6f..b540181ff4 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -39,6 +39,18 @@ char *tor_strdup(const char *s);
char *tor_strndup(const char *s, size_t n);
#define tor_free(p) do {if(p) {free(p); (p)=NULL;}} while(0)
+typedef struct {
+ void **list;
+ int num_used;
+ int max;
+} smartlist_t;
+
+smartlist_t *smartlist_create(int max_elements);
+void smartlist_free(smartlist_t *sl);
+void smartlist_add(smartlist_t *sl, void *element);
+void smartlist_remove(smartlist_t *sl, void *element);
+void *smartlist_choose(smartlist_t *sl);
+
const char *eat_whitespace(const char *s);
const char *eat_whitespace_no_nl(const char *s);
const char *find_whitespace(const char *s);