summaryrefslogtreecommitdiff
path: root/core/ping.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/ping.c')
-rw-r--r--core/ping.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/core/ping.c b/core/ping.c
new file mode 100644
index 00000000..ffabe221
--- /dev/null
+++ b/core/ping.c
@@ -0,0 +1,103 @@
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
17typedef struct {
18 IP_Port ipp;
19 uint64_t id;
20 uint64_t timestamp;
21} pinged_t;
22
23static pinged_t pings[PING_NUM_MAX];
24static size_t num_pings;
25static size_t pos_pings;
26
27
28void init_ping()
29{
30 num_pings = 0;
31 pos_pings = 0;
32}
33
34static bool is_timeout(uint64_t time)
35{
36 return (time + PING_TIMEOUT) < now();
37}
38
39static void remove_timeouts() // O(n)
40{
41 size_t i, id;
42 size_t new_pos = pos_pings;
43 size_t new_num = num_pings;
44
45 // Loop through buffer, oldest first
46 for (i=0; i<num_pings; i++) {
47 id = (pos_pings + i) % PING_NUM_MAX;
48
49 if(is_timeout(pings[id].timestamp)) {
50 new_pos++;
51 new_num--;
52 }
53 // Break here because list is sorted.
54 else
55 break;
56 }
57
58 num_pings = new_num;
59 pos_pings = new_pos % PING_NUM_MAX;
60}
61
62uint64_t add_ping(IP_Port ipp) // O(n)
63{
64 size_t p;
65
66 remove_timeouts();
67
68 // Remove oldest ping if full buffer
69 if (num_pings == PING_NUM_MAX) {
70 num_pings--;
71 pos_pings = (pos_pings + 1) % PING_NUM_MAX;
72 }
73
74 // Insert new ping at end of list
75 p = (pos_pings + num_pings) % PING_NUM_MAX;
76
77 pings[p].ipp = ipp;
78 pings[p].timestamp = now();
79 pings[p].id = random_64b();
80
81 num_pings++;
82 return pings[p].id;
83}
84
85bool is_pinging(IP_Port ipp, uint64_t ping_id) // O(n) TODO: replace this with something else.
86{
87 if (ipp.ip.i == 0 && ping_id == 0)
88 return false;
89
90 size_t i, id;
91
92 remove_timeouts();
93
94 for (i=0; i<num_pings; i++) {
95 id = (pos_pings + i) % PING_NUM_MAX;
96
97 if ((ipp_eq(pings[id].ipp, ipp) || ipp.ip.i == 0) && (pings[id].id == ping_id || ping_id == 0)) {
98 return true;
99 }
100 }
101
102 return false;
103}