summaryrefslogtreecommitdiff
path: root/other
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2013-08-20 17:07:55 -0700
committerirungentoo <irungentoo@gmail.com>2013-08-20 17:07:55 -0700
commitc12853275c03ca6153c9424f29220bc5b8903875 (patch)
treed8191c6a088bcaf8c908fbb5e81a22825712330f /other
parent617b2c8ba59970a67178c602d5348d036140d559 (diff)
parent128223d9d1c70afe0adb4cfe0cfda39204379c3a (diff)
Merge pull request #506 from irungentoo/refactor
Refactored Everything.
Diffstat (limited to 'other')
-rw-r--r--other/DHT_bootstrap.c39
-rw-r--r--other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c52
-rw-r--r--other/unused/timer.c290
-rw-r--r--other/unused/timer.h104
4 files changed, 436 insertions, 49 deletions
diff --git a/other/DHT_bootstrap.c b/other/DHT_bootstrap.c
index 299e030c..5d97b37a 100644
--- a/other/DHT_bootstrap.c
+++ b/other/DHT_bootstrap.c
@@ -44,7 +44,7 @@
44 44
45 45
46 46
47void manage_keys() 47void manage_keys(DHT *dht)
48{ 48{
49 const uint32_t KEYS_SIZE = crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; 49 const uint32_t KEYS_SIZE = crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
50 uint8_t keys[KEYS_SIZE]; 50 uint8_t keys[KEYS_SIZE];
@@ -60,12 +60,12 @@ void manage_keys()
60 exit(1); 60 exit(1);
61 } 61 }
62 62
63 load_keys(keys); 63 load_keys(dht->c, keys);
64 printf("Keys loaded successfully\n"); 64 printf("Keys loaded successfully\n");
65 } else { 65 } else {
66 //otherwise save new keys 66 //otherwise save new keys
67 new_keys(); 67 new_keys(dht->c);
68 save_keys(keys); 68 save_keys(dht->c, keys);
69 keys_file = fopen("key", "w"); 69 keys_file = fopen("key", "w");
70 70
71 if (fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keys_file) != KEYS_SIZE) { 71 if (fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keys_file) != KEYS_SIZE) {
@@ -81,7 +81,13 @@ void manage_keys()
81 81
82int main(int argc, char *argv[]) 82int main(int argc, char *argv[])
83{ 83{
84 manage_keys(); 84 //initialize networking
85 //bind to ip 0.0.0.0:PORT
86 IP ip;
87 ip.i = 0;
88 DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT)));
89 init_cryptopackets(dht);
90 manage_keys(dht);
85 printf("Public key: "); 91 printf("Public key: ");
86 uint32_t i; 92 uint32_t i;
87 93
@@ -89,22 +95,17 @@ int main(int argc, char *argv[])
89 file = fopen("PUBLIC_ID.txt", "w"); 95 file = fopen("PUBLIC_ID.txt", "w");
90 96
91 for (i = 0; i < 32; i++) { 97 for (i = 0; i < 32; i++) {
92 if (self_public_key[i] < 16) 98 if (dht->c->self_public_key[i] < 16)
93 printf("0"); 99 printf("0");
94 100
95 printf("%hhX", self_public_key[i]); 101 printf("%hhX", dht->c->self_public_key[i]);
96 fprintf(file, "%hhX", self_public_key[i]); 102 fprintf(file, "%hhX", dht->c->self_public_key[i]);
97 } 103 }
98 104
99 fclose(file); 105 fclose(file);
100 106
101 printf("\n"); 107 printf("\n");
102 printf("Port: %u\n", PORT); 108 printf("Port: %u\n", PORT);
103 //initialize networking
104 //bind to ip 0.0.0.0:PORT
105 IP ip;
106 ip.i = 0;
107 init_networking(ip, PORT);
108 109
109 perror("Initialization"); 110 perror("Initialization");
110 111
@@ -114,28 +115,24 @@ int main(int argc, char *argv[])
114 bootstrap_info.ip.i = inet_addr(argv[1]); 115 bootstrap_info.ip.i = inet_addr(argv[1]);
115 bootstrap_info.port = htons(atoi(argv[2])); 116 bootstrap_info.port = htons(atoi(argv[2]));
116 uint8_t *bootstrap_key = hex_string_to_bin(argv[3]); 117 uint8_t *bootstrap_key = hex_string_to_bin(argv[3]);
117 DHT_bootstrap(bootstrap_info, bootstrap_key); 118 DHT_bootstrap(dht, bootstrap_info, bootstrap_key);
118 free(bootstrap_key); 119 free(bootstrap_key);
119 } 120 }
120 121
121 DHT_init();
122 friendreq_init();
123
124 int is_waiting_for_dht_connection = 1; 122 int is_waiting_for_dht_connection = 1;
125 123
126 while (1) { 124 while (1) {
127 if (is_waiting_for_dht_connection && DHT_isconnected()) { 125 if (is_waiting_for_dht_connection && DHT_isconnected(dht)) {
128 printf("Connected to other bootstrap server successfully.\n"); 126 printf("Connected to other bootstrap server successfully.\n");
129 is_waiting_for_dht_connection = 0; 127 is_waiting_for_dht_connection = 0;
130 } 128 }
131 129
132 doDHT(); 130 do_DHT(dht);
133 131
134 networking_poll(); 132 networking_poll(dht->c->lossless_udp->net);
135 133
136 c_sleep(1); 134 c_sleep(1);
137 } 135 }
138 136
139 shutdown_networking();
140 return 0; 137 return 0;
141} 138}
diff --git a/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c b/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c
index 896d6a69..81ac538b 100644
--- a/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c
+++ b/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c
@@ -77,7 +77,7 @@ and connect to them.
77returns 1 if the connection to the DHT is up 77returns 1 if the connection to the DHT is up
78returns -1 if all attempts failed 78returns -1 if all attempts failed
79*/ 79*/
80int connect_to_servers(struct server_info_s *info) 80int connect_to_servers(DHT *dht, struct server_info_s *info)
81{ 81{
82 int i; 82 int i;
83 int c; 83 int c;
@@ -86,7 +86,7 @@ int connect_to_servers(struct server_info_s *info)
86 if (info[i].valid) { 86 if (info[i].valid) {
87 /* Actual bootstrapping code goes here */ 87 /* Actual bootstrapping code goes here */
88 //puts("Calling DHT_bootstrap"); 88 //puts("Calling DHT_bootstrap");
89 DHT_bootstrap(info[i].conn, info[i].bs_pk); 89 DHT_bootstrap(dht, info[i].conn, info[i].bs_pk);
90 } 90 }
91 } 91 }
92 92
@@ -94,28 +94,28 @@ int connect_to_servers(struct server_info_s *info)
94 for (c = 0; c != 100; ++c) { 94 for (c = 0; c != 100; ++c) {
95 usleep(10000); 95 usleep(10000);
96 96
97 if (DHT_isconnected()) { 97 if (DHT_isconnected(dht)) {
98 //puts("Connected"); 98 //puts("Connected");
99 return 1; 99 return 1;
100 break; 100 break;
101 } 101 }
102 102
103 if (DHT_isconnected() == 0 && c == 99) { 103 if (DHT_isconnected(dht) == 0 && c == 99) {
104 //puts("Not connected"); 104 //puts("Not connected");
105 return -1; 105 return -1;
106 break; 106 break;
107 } 107 }
108 108
109 doDHT(); 109 do_DHT(dht);
110 110
111 networking_poll(); 111 networking_poll(dht->c->lossless_udp->net);
112 } 112 }
113 113
114 /* This probably never happens */ 114 /* This probably never happens */
115 return 0; 115 return 0;
116} 116}
117 117
118void manage_keys(char *keys_file) 118void manage_keys(DHT *dht, char *keys_file)
119{ 119{
120 const uint32_t KEYS_SIZE = crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; 120 const uint32_t KEYS_SIZE = crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
121 uint8_t keys[KEYS_SIZE]; 121 uint8_t keys[KEYS_SIZE];
@@ -134,13 +134,13 @@ void manage_keys(char *keys_file)
134 printf("Keys loaded successfully\n"); 134 printf("Keys loaded successfully\n");
135 } 135 }
136 136
137 load_keys(keys); 137 load_keys(dht->c, keys);
138 138
139 } else { 139 } else {
140 /* otherwise save new keys */ 140 /* otherwise save new keys */
141 /* Silly work-around to ignore any errors coming from new_keys() */ 141 /* Silly work-around to ignore any errors coming from new_keys() */
142 new_keys(); 142 new_keys(dht->c);
143 save_keys(keys); 143 save_keys(dht->c, keys);
144 keysf = fopen(keys_file, "w"); 144 keysf = fopen(keys_file, "w");
145 145
146 if (fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keysf) != KEYS_SIZE) { 146 if (fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keysf) != KEYS_SIZE) {
@@ -294,9 +294,14 @@ int main(int argc, char *argv[])
294 exit(EXIT_FAILURE); 294 exit(EXIT_FAILURE);
295 } 295 }
296 296
297 /* Read the config file */
298 server_conf = configure_server(argv[1]); 297 server_conf = configure_server(argv[1]);
299 298
299 /* initialize networking
300 bind to ip 0.0.0.0:PORT */
301 IP ip;
302 ip.i = 0;
303 DHT *dht = new_DHT(new_net_crypto(new_networking(ip, server_conf.port)));
304 /* Read the config file */
300 printf("PID file: %s\n", server_conf.pid_file); 305 printf("PID file: %s\n", server_conf.pid_file);
301 printf("Key file: %s\n", server_conf.keys_file); 306 printf("Key file: %s\n", server_conf.keys_file);
302 307
@@ -313,38 +318,32 @@ int main(int argc, char *argv[])
313 /* Manage the keys */ 318 /* Manage the keys */
314 /* for now, just ignore any errors after this call. */ 319 /* for now, just ignore any errors after this call. */
315 int tmperr = errno; 320 int tmperr = errno;
316 manage_keys(server_conf.keys_file); 321 manage_keys(dht, server_conf.keys_file);
317 errno = tmperr; 322 errno = tmperr;
318 323
324 init_cryptopackets(dht);
319 /* Public key */ 325 /* Public key */
320 int i; 326 int i;
321 printf("\nPublic Key: "); 327 printf("\nPublic Key: ");
322 328
323 for (i = 0; i < 32; ++i) { 329 for (i = 0; i < 32; ++i) {
324 uint8_t ln, hn; 330 uint8_t ln, hn;
325 ln = 0x0F & self_public_key[i]; 331 ln = 0x0F & dht->c->self_public_key[i];
326 hn = 0xF0 & self_public_key[i]; 332 hn = 0xF0 & dht->c->self_public_key[i];
327 hn = hn >> 4; 333 hn = hn >> 4;
328 printf("%X%X", hn, ln); 334 printf("%X%X", hn, ln);
329 } 335 }
330 336
331 printf("\n"); 337 printf("\n");
332 338
333 /* initialize networking
334 bind to ip 0.0.0.0:PORT */
335 IP ip;
336 ip.i = 0;
337 init_networking(ip, server_conf.port);
338
339 /* Bootstrap the DHT 339 /* Bootstrap the DHT
340 This one throws odd errors, too. Ignore. I assume they come 340 This one throws odd errors, too. Ignore. I assume they come
341 from somewhere in the core. */ 341 from somewhere in the core. */
342 DHT_init();
343 tmperr = errno; 342 tmperr = errno;
344 connect_to_servers(server_conf.info); 343 connect_to_servers(dht, server_conf.info);
345 errno = tmperr; 344 errno = tmperr;
346 345
347 if (!DHT_isconnected()) { 346 if (!DHT_isconnected(dht)) {
348 puts("Could not establish DHT connection. Check server settings.\n"); 347 puts("Could not establish DHT connection. Check server settings.\n");
349 exit(EXIT_FAILURE); 348 exit(EXIT_FAILURE);
350 } else { 349 } else {
@@ -404,13 +403,10 @@ int main(int argc, char *argv[])
404 close(STDIN_FILENO); 403 close(STDIN_FILENO);
405 close(STDERR_FILENO); 404 close(STDERR_FILENO);
406 405
407 /* Main loop */
408 friendreq_init();
409
410 while (1) { 406 while (1) {
411 doDHT(); 407 do_DHT(dht);
412 408
413 networking_poll(); 409 networking_poll(dht->c->lossless_udp->net);
414 usleep(10000); 410 usleep(10000);
415 } 411 }
416 412
diff --git a/other/unused/timer.c b/other/unused/timer.c
new file mode 100644
index 00000000..29190921
--- /dev/null
+++ b/other/unused/timer.c
@@ -0,0 +1,290 @@
1#define __STDC_FORMAT_MACROS
2#include <inttypes.h>
3
4#include "timer.h"
5#include "network.h"
6
7/*
8A nested linked list increases efficiency of insertions.
9Depending on the number of timers we have, we might need to have nested linked lists
10in order to improve insertion efficiency.
11The code below is preperation for that end, should it be necessary.
12
13typedef struct {
14 struct timer_package* _next;
15 union {
16 timer_packet* _inner;
17 timer* queue;
18 };
19 uint64_t pkgtime;
20} timer_package;
21
22timer_package* timer_package_pool;
23
24static timer_package* new_package()
25{
26 timer_package* ret;
27 if (timer_package_pool) {
28 ret = timer_package_pool;
29 timer_package_pool = timer_package_pool->_next;
30 } else {
31 ret = calloc(1, sizeof(struct timer_package));
32 }
33 return ret;
34}
35
36static void delete_package(timer_package* p)
37{
38 p->_next = timer_package_pool;
39 timer_package_pool = p;
40}
41*/
42
43enum timer_state {
44 STATE_INACTIVE = 0,
45 STATE_ACTIVE,
46 STATE_CALLBACK
47};
48
49struct timer {
50 enum timer_state state;
51 timer *_prev;
52 timer *_next;
53 timer_callback cb;
54 void *userdata;
55 uint64_t deadline;
56};
57
58static timer *timer_main_queue;
59static timer *timer_us_queue; /* hi-speed queue */
60
61inline static void timer_dequeue(timer *t, timer **queue)
62{
63 if (t->state == STATE_INACTIVE) return; /* not in a queue */
64
65 if (t->_prev) {
66 t->_prev->_next = t->_next;
67 } else {
68 *queue = t->_next;
69 }
70
71 if (t->_next) t->_next->_prev = t->_prev;
72
73 t->state = STATE_INACTIVE;
74}
75
76static void timer_enqueue(timer *t, timer **queue, timer *prev)
77{
78 t->state = STATE_ACTIVE;
79
80 while (true) {
81 if (!*queue) {
82 t->_next = 0;
83 t->_prev = prev;
84 *queue = t;
85 return;
86 }
87
88 if ((*queue)->deadline > t->deadline) {
89 (*queue)->_prev = t;
90 t->_next = *queue;
91 t->_prev = prev;
92 *queue = t;
93 return;
94 }
95
96 prev = *queue;
97 queue = &((*queue)->_next);
98 }
99}
100
101/*** interface ***/
102
103void timer_init()
104{
105 /* Nothing needs to be done... yet. */
106}
107
108/* Do not depend on fields being zeroed */
109static timer *timer_pool; /* timer_pool is SINGLY LINKED!! */
110
111timer *new_timer(void)
112{
113 timer *ret;
114
115 if (timer_pool) {
116 ret = timer_pool;
117 timer_pool = timer_pool->_next;
118 } else {
119 ret = calloc(1, sizeof(struct timer));
120 }
121
122 ret->state = STATE_INACTIVE;
123 return ret;
124}
125
126void delete_timer(timer *t)
127{
128 timer_dequeue(t, &timer_main_queue);
129 t->_next = timer_pool;
130 t->state = STATE_INACTIVE;
131 timer_pool = t;
132}
133
134void timer_setup(timer *t, timer_callback cb, void *userarg)
135{
136 t->cb = cb;
137 t->userdata = userarg;
138}
139
140void *timer_get_userdata(timer *t)
141{
142 return t->userdata;
143}
144
145static void timer_delay_us(timer *t, int us)
146{
147 t->deadline += us;
148 timer **queue = t->_prev ? &(t->_prev->_next) : &timer_main_queue;
149 timer_dequeue(t, &timer_main_queue);
150 timer_enqueue(t, queue, t->_prev);
151}
152
153/* Starts the timer so that it's called in sec seconds in the future.
154 * A non-positive value of sec results in the callback being called immediately.
155 * This function may be called again after a timer has been started to adjust
156 * the expiry time. */
157void timer_start(timer *t, int sec)
158{
159 uint64_t newdeadline = current_time() + sec * US_PER_SECOND;
160
161 if (timer_is_active(t)) {
162 if (t->deadline < newdeadline) {
163 timer_delay_us(t, newdeadline - t->deadline);
164 return;
165 }
166
167 timer_dequeue(t, &timer_main_queue);
168 }
169
170 t->deadline = newdeadline;
171 timer_enqueue(t, &timer_main_queue, 0);
172}
173
174/* Stops the timer. Returns -1 if the timer was not active. */
175int timer_stop(timer *t)
176{
177 int ret = timer_is_active(t) ? -1 : 0;
178 timer_dequeue(t, &timer_main_queue);
179 return ret;
180}
181
182/* Adds additionalsec seconds to the timer.
183 * Returns -1 and does nothing if the timer was not active. */
184int timer_delay(timer *t, int additonalsec)
185{
186 if (!timer_is_active(t)) return -1;
187
188 timer_delay_us(t, additonalsec * US_PER_SECOND);
189 return 0;
190}
191
192static uint64_t timer_diff(timer *t, uint64_t time)
193{
194 if (t->deadline <= time) return 0;
195
196 return time - t->deadline;
197}
198
199/* Returns the time remaining on a timer in seconds.
200 * Returns -1 if the timer is not active.
201 * Returns 0 if the timer has expired and will be called upon the next call to timer_poll. */
202int timer_time_remaining(timer *t)
203{
204 if (!timer_is_active(t)) return -1;
205
206 return timer_diff(t, current_time()) / US_PER_SECOND;
207}
208
209bool timer_is_active(timer *t)
210{
211 return t->state != STATE_INACTIVE;
212}
213
214/* Single-use timer.
215 * Creates a new timer, preforms setup and starts it. */
216void timer_single(timer_callback cb, void *userarg, int sec)
217{
218 timer *t = new_timer();
219 timer_setup(t, cb, userarg);
220 timer_start(t, sec);
221}
222
223/* Single-use microsecond timer. */
224void timer_us(timer_callback cb, void *userarg, int us)
225{
226 timer *t = new_timer();
227 timer_setup(t, cb, userarg);
228 t->deadline = current_time() + us;
229 t->state = STATE_ACTIVE;
230 timer_enqueue(t, &timer_us_queue, 0);
231}
232
233uint64_t prevtime = 0;
234void timer_poll(void)
235{
236 uint64_t time = current_time();
237
238 /* Handle millisecond timers */
239 while (timer_us_queue) {
240 if (timer_diff(timer_us_queue, time) != 0) break;
241
242 timer *t = timer_us_queue;
243 timer_dequeue(t, &timer_us_queue);
244 t->cb(0, t->userdata);
245 delete_timer(t);
246 }
247
248 if (time - prevtime > US_PER_SECOND || prevtime == 0 || prevtime > time) {
249 /* time moving backwards is just a sanity check */
250 prevtime = time;
251
252 while (timer_main_queue) {
253 if (timer_diff(timer_main_queue, time) != 0) break;
254
255 timer *t = timer_main_queue;
256 t->state = STATE_CALLBACK;
257 int rv = t->cb(t, t->userdata);
258
259 if (rv != 0) {
260 timer_dequeue(t, &timer_main_queue);
261 delete_timer(t);
262 continue;
263 }
264
265 if (t->state != STATE_ACTIVE) {
266 timer_dequeue(t, &timer_main_queue);
267 }
268 }
269 }
270}
271
272/*** Internal Testing ***/
273
274/* I do not want to expose internals to the public,
275 * which is why internals testing is done this way. */
276void timer_internal_tests(bool (*assert)(bool, char *))
277{
278
279}
280
281void timer_debug_print()
282{
283 timer *t = timer_main_queue;
284 printf("Queue:\n");
285
286 while (t) {
287 printf("%" PRIu64 " (%" PRIu64 ") : %s\n", t->deadline, t->deadline / US_PER_SECOND, (char *)t->userdata);
288 t = t->_next;
289 }
290}
diff --git a/other/unused/timer.h b/other/unused/timer.h
new file mode 100644
index 00000000..15491326
--- /dev/null
+++ b/other/unused/timer.h
@@ -0,0 +1,104 @@
1/* timer.h
2 *
3 * Timing subsystem. Provides deadline timers.
4 * All times are aliased to a second for efficiency.
5 *
6 * Timer Guarantees:
7 * - The callback will not be called before the timer expires.
8 * - The callback will be called sometime after the timer expires,
9 * on a best effort basis.
10 * - If timer_poll is called at least once a second, the callback
11 * will be called at most one second after it expires.
12 *
13 * Copyright (C) 2013 Tox project All Rights Reserved.
14 *
15 * This file is part of Tox.
16 *
17 * Tox is free software: you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation, either version 3 of the License, or
20 * (at your option) any later version.
21 *
22 * Tox is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
29 *
30 */
31
32#ifndef TIMER_H
33#define TIMER_H
34
35#include <stdint.h>
36#include <stdbool.h>
37
38#define US_PER_SECOND 1000000 /* 1 s = 10^6 us */
39
40struct timer;
41typedef struct timer timer;
42
43/* If time_callback returns a non-zero value, timer t is deleted.
44 * You may call any of the timer functions within the callback:
45 * For example, you may call timer_start to restart the timer from
46 * within a callback. */
47typedef int (*timer_callback)(timer *t, void *userarg);
48
49/* Initisalise timer subsystem */
50void timer_init(void);
51
52/* Poll. (I will eventually replace all polling in Tox with an async system.) */
53void timer_poll(void);
54
55/* Creates a new timer. Does not enqueue/start it. */
56timer *new_timer(void);
57
58/* Destroys a timer instance. */
59void delete_timer(timer *t);
60
61/* Sets up the timer callback. */
62void timer_setup(timer *t, timer_callback cb, void *userarg);
63
64/* Accessor Function. */
65void *timer_get_userdata(timer *t);
66
67/* Starts the timer so that it's called in sec seconds in the future from now.
68 * A non-positive value of sec results in the callback being called immediately.
69 * This function may be called again after a timer has been started to adjust
70 * the expiry time. */
71void timer_start(timer *t, int sec);
72
73/* Stops the timer. Returns -1 if the timer was not active. */
74int timer_stop(timer *t);
75
76/* Adds additionalsec seconds to the timer.
77 * Returns -1 and does nothing if the timer was not active. */
78int timer_delay(timer *t, int additonalsec);
79
80/* Returns the time remaining on a timer in seconds.
81 * Returns -1 if the timer is not active.
82 * Returns 0 if the timer has expired and the callback hasn't been called yet. */
83int timer_time_remaining(timer *t);
84
85/* Determines if timer is active. Returns TRUE if it is active */
86bool timer_is_active(timer *t);
87
88/* Single-use timer.
89 * Creates a new timer, preforms setup and starts it.
90 * Callback must return a non-zero value to prevent memory leak. */
91void timer_single(timer_callback cb, void *userarg, int sec);
92
93/* Single-use microsecond timer.
94 * Creates a new timer, preforms setup and starts it.
95 * Please do not use this when accuracy is not absolutely required.
96 * Use when one needs to time a period < 1 s.
97 * Use the more coarse timers above for periods > 5 s.
98 * WARNING: the callback will be called with NULL as the first argument */
99void timer_us(timer_callback cb, void *userarg, int us);
100
101/* Internal Testing */
102void timer_internal_tests(bool( *)(bool, char *));
103
104#endif