diff options
Diffstat (limited to 'core/ping.c')
-rw-r--r-- | core/ping.c | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/core/ping.c b/core/ping.c new file mode 100644 index 00000000..8a7d534f --- /dev/null +++ b/core/ping.c | |||
@@ -0,0 +1,95 @@ | |||
1 | /* | ||
2 | * ping.c -- Buffered pinging using cyclic arrays. | ||
3 | * | ||
4 | * This file is donated to the Tox Project. | ||
5 | * Copyright 2013 plutooo | ||
6 | */ | ||
7 | |||
8 | #include <stdbool.h> | ||
9 | #include <stdint.h> | ||
10 | |||
11 | #include "network.h" | ||
12 | #include "util.h" | ||
13 | |||
14 | #define PING_NUM_MAX 256 | ||
15 | #define PING_TIMEOUT 5 // 5s | ||
16 | |||
17 | typedef struct { | ||
18 | IP_Port ipp; | ||
19 | uint64_t id; | ||
20 | uint64_t timestamp; | ||
21 | } pinged_t; | ||
22 | |||
23 | static pinged_t pings[PING_NUM_MAX]; | ||
24 | static size_t num_pings; | ||
25 | static size_t pos_pings; | ||
26 | |||
27 | |||
28 | void init_ping() { | ||
29 | num_pings = 0; | ||
30 | pos_pings = 0; | ||
31 | } | ||
32 | |||
33 | static bool is_timeout(uint64_t time) { | ||
34 | return (time + PING_TIMEOUT) < now(); | ||
35 | } | ||
36 | |||
37 | static void remove_timeouts() { // O(n) | ||
38 | size_t i, id; | ||
39 | size_t new_pos = pos_pings; | ||
40 | size_t new_num = num_pings; | ||
41 | |||
42 | // Loop through buffer, oldest first | ||
43 | for(i=0; i<num_pings; i++) { | ||
44 | id = (pos_pings + i) % PING_NUM_MAX; | ||
45 | |||
46 | if(is_timeout(pings[id].timestamp)) { | ||
47 | new_pos++; | ||
48 | new_num--; | ||
49 | } | ||
50 | // Break here because list is sorted. | ||
51 | else | ||
52 | break; | ||
53 | } | ||
54 | |||
55 | num_pings = new_num; | ||
56 | pos_pings = new_pos % PING_NUM_MAX; | ||
57 | } | ||
58 | |||
59 | uint64_t add_ping(IP_Port ipp) { // O(n) | ||
60 | size_t p; | ||
61 | |||
62 | remove_timeouts(); | ||
63 | |||
64 | // Remove oldest ping if full buffer | ||
65 | if(num_pings == PING_NUM_MAX) { | ||
66 | num_pings--; | ||
67 | pos_pings = (pos_pings + 1) % PING_NUM_MAX; | ||
68 | } | ||
69 | |||
70 | // Insert new ping at end of list | ||
71 | p = (pos_pings + num_pings) % PING_NUM_MAX; | ||
72 | |||
73 | pings[p].ipp = ipp; | ||
74 | pings[p].timestamp = now(); | ||
75 | pings[p].id = random_64b(); | ||
76 | |||
77 | num_pings++; | ||
78 | return pings[p].id; | ||
79 | } | ||
80 | |||
81 | bool is_pinging(IP_Port ipp, uint64_t ping_id) { // O(n) | ||
82 | size_t i, id; | ||
83 | |||
84 | remove_timeouts(); | ||
85 | |||
86 | for(i=0; i<num_pings; i++) { | ||
87 | id = (pos_pings + i) % PING_NUM_MAX; | ||
88 | |||
89 | if(ipp_eq(pings[id].ipp, ipp) && pings[id].id == ping_id) { | ||
90 | return true; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | return false; | ||
95 | } | ||