diff options
author | irungentoo <irungentoo@gmail.com> | 2014-05-12 14:07:03 -0400 |
---|---|---|
committer | irungentoo <irungentoo@gmail.com> | 2014-05-12 14:07:03 -0400 |
commit | 10da970e0dfcb21fda4da96635b690065375daff (patch) | |
tree | f2459735e1d51906e063b3288b60f41cd287b47f /toxcore/ping_array.c | |
parent | 87cec792062a755675e53b5603049cdb067aa70f (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.c | 162 |
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 | |||
33 | static 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 | */ | ||
44 | static 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 | */ | ||
62 | uint64_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 | */ | ||
101 | int 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 | */ | ||
133 | int 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 | */ | ||
151 | void 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 | |||