summaryrefslogtreecommitdiff
path: root/toxcore/ping_array.c
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2014-05-12 14:07:03 -0400
committerirungentoo <irungentoo@gmail.com>2014-05-12 14:07:03 -0400
commit10da970e0dfcb21fda4da96635b690065375daff (patch)
treef2459735e1d51906e063b3288b60f41cd287b47f /toxcore/ping_array.c
parent87cec792062a755675e53b5603049cdb067aa70f (diff)
Added ping_array, a special efficient array for use in operations
that require sending ping type packets. Made ping packets use it.
Diffstat (limited to 'toxcore/ping_array.c')
-rw-r--r--toxcore/ping_array.c162
1 files changed, 162 insertions, 0 deletions
diff --git a/toxcore/ping_array.c b/toxcore/ping_array.c
new file mode 100644
index 00000000..cb18ceb3
--- /dev/null
+++ b/toxcore/ping_array.c
@@ -0,0 +1,162 @@
1/* ping_array.c
2 *
3 * Implementation of an efficient array to store that we pinged something.
4 *
5 *
6 * Copyright (C) 2014 Tox project All Rights Reserved.
7 *
8 * This file is part of Tox.
9 *
10 * Tox is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * Tox is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 *
23 */
24
25#ifdef HAVE_CONFIG_H
26#include "config.h"
27#endif
28
29#include "ping_array.h"
30#include "crypto_core.h"
31#include "util.h"
32
33static void clear_entry(Ping_Array *array, uint32_t index)
34{
35 free(array->entries[index].data);
36 array->entries[index].data = NULL;
37 array->entries[index].length =
38 array->entries[index].time =
39 array->entries[index].ping_id = 0;
40}
41
42/* Clear timed out entries.
43 */
44static void ping_array_clear_timedout(Ping_Array *array)
45{
46 while (array->last_deleted != array->last_added) {
47 uint32_t index = array->last_deleted % array->total_size;
48
49 if (!is_timeout(array->entries[index].time, array->timeout))
50 break;
51
52 clear_entry(array, index);
53 ++array->last_deleted;
54 }
55}
56
57/* Add a data with length to the Ping_Array list and return a ping_id.
58 *
59 * return ping_id on success.
60 * return 0 on failure.
61 */
62uint64_t ping_array_add(Ping_Array *array, uint8_t *data, uint32_t length)
63{
64 ping_array_clear_timedout(array);
65 uint32_t index = array->last_added % array->total_size;
66
67 if (array->entries[index].data != NULL) {
68 array->last_deleted = array->last_added - array->total_size;
69 clear_entry(array, index);
70 }
71
72 array->entries[index].data = malloc(length);
73
74 if (array->entries[index].data == NULL)
75 return 0;
76
77 memcpy(array->entries[index].data, data, length);
78 array->entries[index].length = length;
79 array->entries[index].time = unix_time();
80 ++array->last_added;
81 uint64_t ping_id = random_64b();
82 ping_id /= array->total_size;
83 ping_id *= array->total_size;
84 ping_id += index;
85
86 if (ping_id == 0)
87 ping_id += array->total_size;
88
89 array->entries[index].ping_id = ping_id;
90 return ping_id;
91}
92
93
94/* Check if ping_id is valid and not timed out.
95 *
96 * On success, copies the data into data of length,
97 *
98 * return length of data copied on success.
99 * return -1 on failure.
100 */
101int ping_array_check(uint8_t *data, uint32_t length, Ping_Array *array, uint64_t ping_id)
102{
103 if (ping_id == 0)
104 return -1;
105
106 uint32_t index = ping_id % array->total_size;
107
108 if (array->entries[index].ping_id != ping_id)
109 return -1;
110
111 if (is_timeout(array->entries[index].time, array->timeout))
112 return -1;
113
114 if (array->entries[index].length > length)
115 return -1;
116
117 if (array->entries[index].data == NULL)
118 return -1;
119
120 memcpy(data, array->entries[index].data, array->entries[index].length);
121 uint32_t len = array->entries[index].length;
122 clear_entry(array, index);
123 return len;
124}
125
126/* Initialize a Ping_Array.
127 * size represents the total size of the array and should be a power of 2.
128 * timeout represents the maximum timeout in seconds for the entry.
129 *
130 * return 0 on success.
131 * return -1 on failure.
132 */
133int ping_array_init(Ping_Array *empty_array, uint32_t size, uint32_t timeout)
134{
135 if (size == 0 || timeout == 0 || empty_array == NULL)
136 return -1;
137
138 empty_array->entries = malloc(size * sizeof(Ping_Array_Entry));
139
140 if (empty_array->entries == NULL)
141 return -1;
142
143 empty_array->last_deleted = empty_array->last_added = 0;
144 empty_array->total_size = size;
145 empty_array->timeout = timeout;
146 return 0;
147}
148
149/* Free all the allocated memory in a Ping_Array.
150 */
151void ping_array_free_all(Ping_Array *array)
152{
153 while (array->last_deleted != array->last_added) {
154 uint32_t index = array->last_deleted % array->total_size;
155 clear_entry(array, index);
156 ++array->last_deleted;
157 }
158
159 free(array->entries);
160 array->entries = NULL;
161}
162