diff options
author | Matthias Wachs <wachs@net.in.tum.de> | 2013-02-05 15:35:32 +0000 |
---|---|---|
committer | Matthias Wachs <wachs@net.in.tum.de> | 2013-02-05 15:35:32 +0000 |
commit | 9ea6140052f8340045bf0b363030a1e6ab79a435 (patch) | |
tree | c18a5b21e01f3026fef9df36c2e109fc841904dd /src/transport/gnunet-service-transport_manipulation.c | |
parent | 1c388b347390fbc2e784891dad42a2287e90a584 (diff) | |
download | gnunet-9ea6140052f8340045bf0b363030a1e6ab79a435.tar.gz gnunet-9ea6140052f8340045bf0b363030a1e6ab79a435.zip |
traffic manipulation: receive delay
Diffstat (limited to 'src/transport/gnunet-service-transport_manipulation.c')
-rw-r--r-- | src/transport/gnunet-service-transport_manipulation.c | 335 |
1 files changed, 335 insertions, 0 deletions
diff --git a/src/transport/gnunet-service-transport_manipulation.c b/src/transport/gnunet-service-transport_manipulation.c new file mode 100644 index 000000000..74f903c98 --- /dev/null +++ b/src/transport/gnunet-service-transport_manipulation.c | |||
@@ -0,0 +1,335 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2010,2011 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file transport/gnunet-service-transport_manipulation.c | ||
23 | * @brief transport component manipulation traffic for simulation | ||
24 | * @author Christian Grothoff | ||
25 | * @author | ||
26 | */ | ||
27 | #include "platform.h" | ||
28 | #include "gnunet-service-transport_blacklist.h" | ||
29 | #include "gnunet-service-transport_clients.h" | ||
30 | #include "gnunet-service-transport_hello.h" | ||
31 | #include "gnunet-service-transport_neighbours.h" | ||
32 | #include "gnunet-service-transport_plugins.h" | ||
33 | #include "gnunet-service-transport_validation.h" | ||
34 | #include "gnunet-service-transport.h" | ||
35 | #include "transport.h" | ||
36 | |||
37 | static struct GNUNET_CONTAINER_MultiHashMap *peers; | ||
38 | |||
39 | #define DELAY 0 | ||
40 | #define DISTANCE 1 | ||
41 | |||
42 | struct TM_Peer; | ||
43 | |||
44 | struct DelayQueueEntry | ||
45 | { | ||
46 | struct DelayQueueEntry *prev; | ||
47 | struct DelayQueueEntry *next; | ||
48 | struct TM_Peer *tmp; | ||
49 | struct GNUNET_TIME_Absolute sent_at; | ||
50 | void *msg; | ||
51 | size_t msg_size; | ||
52 | struct GNUNET_TIME_Relative timeout; | ||
53 | GST_NeighbourSendContinuation cont; | ||
54 | void *cont_cls; | ||
55 | }; | ||
56 | |||
57 | struct TM_Peer | ||
58 | { | ||
59 | struct GNUNET_PeerIdentity peer; | ||
60 | uint32_t metrics [TM_BOTH][GNUNET_ATS_QualityPropertiesCount]; | ||
61 | GNUNET_SCHEDULER_TaskIdentifier send_delay_task; | ||
62 | struct DelayQueueEntry *send_head; | ||
63 | struct DelayQueueEntry *send_tail; | ||
64 | }; | ||
65 | |||
66 | |||
67 | |||
68 | static void | ||
69 | set_delay(struct TM_Peer *tmp, struct GNUNET_PeerIdentity *peer, int direction, uint32_t value) | ||
70 | { | ||
71 | uint32_t val; | ||
72 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Set traffic metrics %s for peer `%s' in direction %s to %u\n", | ||
73 | "DELAY", GNUNET_i2s(peer), | ||
74 | (TM_BOTH == direction) ? "BOTH" : (TM_SEND == direction) ? "SEND": "RECEIVE", value); | ||
75 | |||
76 | if (UINT32_MAX == value) | ||
77 | val = UINT32_MAX - 1; /* prevent overflow */ | ||
78 | else if (0 == value) | ||
79 | val = UINT32_MAX; /* disable */ | ||
80 | else | ||
81 | val = value; | ||
82 | |||
83 | switch (direction) { | ||
84 | case TM_BOTH: | ||
85 | tmp->metrics[TM_SEND][DELAY] = val; | ||
86 | tmp->metrics[TM_RECEIVE][DELAY] = val; | ||
87 | break; | ||
88 | case TM_SEND: | ||
89 | tmp->metrics[TM_SEND][DELAY] = val; | ||
90 | break; | ||
91 | case TM_RECEIVE: | ||
92 | tmp->metrics[TM_RECEIVE][DELAY] = val; | ||
93 | break; | ||
94 | default: | ||
95 | break; | ||
96 | } | ||
97 | |||
98 | } | ||
99 | |||
100 | static void | ||
101 | set_distance (struct TM_Peer *tmp, struct GNUNET_PeerIdentity *peer, int direction, uint32_t value) | ||
102 | { | ||
103 | uint32_t val; | ||
104 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Set traffic metrics %s for peer `%s' in direction %s to %u\n", | ||
105 | "DISTANCE", GNUNET_i2s(peer), | ||
106 | (TM_BOTH == direction) ? "BOTH" : (TM_SEND == direction) ? "SEND": "RECEIVE", value); | ||
107 | |||
108 | if (UINT32_MAX == value) | ||
109 | val = UINT32_MAX - 1; /* prevent overflow */ | ||
110 | else if (0 == value) | ||
111 | val = UINT32_MAX; /* disable */ | ||
112 | else | ||
113 | val = value; | ||
114 | |||
115 | switch (direction) { | ||
116 | case TM_BOTH: | ||
117 | tmp->metrics[TM_SEND][DISTANCE] = val; | ||
118 | tmp->metrics[TM_RECEIVE][DISTANCE] = val; | ||
119 | break; | ||
120 | case TM_SEND: | ||
121 | tmp->metrics[TM_SEND][DISTANCE] = val; | ||
122 | break; | ||
123 | case TM_RECEIVE: | ||
124 | tmp->metrics[TM_RECEIVE][DISTANCE] = val; | ||
125 | break; | ||
126 | default: | ||
127 | break; | ||
128 | } | ||
129 | } | ||
130 | |||
131 | void | ||
132 | GST_manipulation_set_metric (void *cls, struct GNUNET_SERVER_Client *client, | ||
133 | const struct GNUNET_MessageHeader *message) | ||
134 | { | ||
135 | struct TrafficMetricMessage *tm = (struct TrafficMetricMessage *) message; | ||
136 | struct GNUNET_ATS_Information *ats; | ||
137 | struct TM_Peer *tmp; | ||
138 | uint32_t type; | ||
139 | uint32_t value; | ||
140 | int c; | ||
141 | int c2; | ||
142 | |||
143 | if (0 == ntohs (tm->ats_count)) | ||
144 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
145 | |||
146 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received traffic metrics for peer `%s'\n", | ||
147 | GNUNET_i2s(&tm->peer)); | ||
148 | |||
149 | if (NULL == (tmp = GNUNET_CONTAINER_multihashmap_get (peers, &tm->peer.hashPubKey))) | ||
150 | { | ||
151 | tmp = GNUNET_malloc (sizeof (struct TM_Peer)); | ||
152 | tmp->peer = (tm->peer); | ||
153 | for (c = 0; c < TM_BOTH; c++) | ||
154 | { | ||
155 | for (c2 = 0; c2 < GNUNET_ATS_QualityPropertiesCount; c2++) | ||
156 | { | ||
157 | tmp->metrics[c][c2] = UINT32_MAX; | ||
158 | } | ||
159 | } | ||
160 | GNUNET_CONTAINER_multihashmap_put (peers, &tm->peer.hashPubKey, tmp, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
161 | } | ||
162 | |||
163 | ats = (struct GNUNET_ATS_Information *) &tm[1]; | ||
164 | for (c = 0; c < ntohs (tm->ats_count); c++) | ||
165 | { | ||
166 | type = htonl (ats[c].type); | ||
167 | value = htonl (ats[c].value); | ||
168 | switch (type) { | ||
169 | case GNUNET_ATS_QUALITY_NET_DELAY: | ||
170 | set_delay (tmp, &tm->peer, ntohs (tm->direction), value); | ||
171 | break; | ||
172 | case GNUNET_ATS_QUALITY_NET_DISTANCE: | ||
173 | set_distance (tmp, &tm->peer, ntohs (tm->direction), value); | ||
174 | break; | ||
175 | default: | ||
176 | break; | ||
177 | } | ||
178 | } | ||
179 | |||
180 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
181 | } | ||
182 | |||
183 | static void | ||
184 | send_delayed (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
185 | { | ||
186 | struct DelayQueueEntry *dqe = cls; | ||
187 | struct DelayQueueEntry *next; | ||
188 | struct TM_Peer *tmp = dqe->tmp; | ||
189 | struct GNUNET_TIME_Relative delay; | ||
190 | tmp->send_delay_task = GNUNET_SCHEDULER_NO_TASK; | ||
191 | GNUNET_CONTAINER_DLL_remove (tmp->send_head, tmp->send_tail, dqe); | ||
192 | GST_neighbours_send (&tmp->peer, dqe->msg, dqe->msg_size, dqe->timeout, dqe->cont, dqe->cont_cls); | ||
193 | |||
194 | next = tmp->send_head; | ||
195 | if (NULL != next) | ||
196 | { | ||
197 | /* More delayed messages */ | ||
198 | delay = GNUNET_TIME_absolute_get_remaining (next->sent_at); | ||
199 | tmp->send_delay_task = GNUNET_SCHEDULER_add_delayed (delay, &send_delayed, dqe); | ||
200 | } | ||
201 | |||
202 | GNUNET_free (dqe); | ||
203 | } | ||
204 | |||
205 | void | ||
206 | GST_manipulation_send (const struct GNUNET_PeerIdentity *target, const void *msg, | ||
207 | size_t msg_size, struct GNUNET_TIME_Relative timeout, | ||
208 | GST_NeighbourSendContinuation cont, void *cont_cls) | ||
209 | { | ||
210 | struct TM_Peer *tmp; | ||
211 | struct DelayQueueEntry *dqe; | ||
212 | struct GNUNET_TIME_Relative delay; | ||
213 | |||
214 | if (NULL != (tmp = GNUNET_CONTAINER_multihashmap_get (peers, &target->hashPubKey))) | ||
215 | { | ||
216 | /* Manipulate here */ | ||
217 | /* Delay */ | ||
218 | if (UINT32_MAX != tmp->metrics[TM_SEND][DELAY]) | ||
219 | { | ||
220 | /* We have a delay */ | ||
221 | delay.rel_value = tmp->metrics[TM_SEND][DELAY]; | ||
222 | dqe = GNUNET_malloc (sizeof (struct DelayQueueEntry) + msg_size); | ||
223 | dqe->tmp = tmp; | ||
224 | dqe->sent_at = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), delay); | ||
225 | dqe->cont = cont; | ||
226 | dqe->cont_cls = cont_cls; | ||
227 | dqe->msg = &dqe[1]; | ||
228 | dqe->msg_size = msg_size; | ||
229 | dqe->timeout = timeout; | ||
230 | memcpy (dqe->msg, msg, msg_size); | ||
231 | GNUNET_CONTAINER_DLL_insert_tail (tmp->send_head, tmp->send_tail, dqe); | ||
232 | if (GNUNET_SCHEDULER_NO_TASK == tmp->send_delay_task) | ||
233 | tmp->send_delay_task =GNUNET_SCHEDULER_add_delayed (delay, &send_delayed, dqe); | ||
234 | return; | ||
235 | } | ||
236 | } | ||
237 | /* Normal sending */ | ||
238 | GST_neighbours_send (target, msg, msg_size, timeout, cont, cont_cls); | ||
239 | } | ||
240 | |||
241 | struct GNUNET_TIME_Relative | ||
242 | GST_manipulation_recv (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
243 | const struct GNUNET_MessageHeader *message, | ||
244 | const struct GNUNET_ATS_Information *ats, | ||
245 | uint32_t ats_count, struct Session *session, | ||
246 | const char *sender_address, | ||
247 | uint16_t sender_address_len) | ||
248 | { | ||
249 | struct TM_Peer *tmp; | ||
250 | int d; | ||
251 | struct GNUNET_ATS_Information ats_new[ats_count]; | ||
252 | struct GNUNET_TIME_Relative q_delay; | ||
253 | struct GNUNET_TIME_Relative m_delay; | ||
254 | |||
255 | for (d = 0; d < ats_count; d++) | ||
256 | |||
257 | if (NULL != (tmp = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey))) | ||
258 | { | ||
259 | /* Manipulate distance */ | ||
260 | for (d = 0; d < ats_count; d++) | ||
261 | { | ||
262 | ats_new[d] = ats[d]; | ||
263 | /* Set distance */ | ||
264 | if ((ntohl(ats[d].type) == GNUNET_ATS_QUALITY_NET_DISTANCE) && | ||
265 | (UINT32_MAX != tmp->metrics[TM_RECEIVE][DISTANCE])) | ||
266 | { | ||
267 | ats_new[d].value = htonl(tmp->metrics[TM_RECEIVE][DISTANCE]); | ||
268 | } | ||
269 | } | ||
270 | /* Manipulate receive delay */ | ||
271 | if (UINT32_MAX != tmp->metrics[TM_RECEIVE][DELAY]) | ||
272 | { | ||
273 | m_delay.rel_value = tmp->metrics[TM_RECEIVE][DELAY]; | ||
274 | q_delay = GST_receive_callback (cls, peer, message, &ats_new[0], ats_count, | ||
275 | session, sender_address, sender_address_len); | ||
276 | |||
277 | if (q_delay.rel_value >= m_delay.rel_value) | ||
278 | { | ||
279 | return q_delay; | ||
280 | } | ||
281 | else | ||
282 | { | ||
283 | return m_delay; | ||
284 | } | ||
285 | } | ||
286 | } | ||
287 | |||
288 | return GST_receive_callback (cls, peer, message, ats, ats_count, | ||
289 | session, sender_address, sender_address_len); | ||
290 | } | ||
291 | |||
292 | void | ||
293 | GST_manipulation_init () | ||
294 | { | ||
295 | peers = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO); | ||
296 | } | ||
297 | |||
298 | int free_tmps (void *cls, | ||
299 | const struct GNUNET_HashCode * key, | ||
300 | void *value) | ||
301 | { | ||
302 | struct DelayQueueEntry *dqe; | ||
303 | struct DelayQueueEntry *next; | ||
304 | if (NULL != value) | ||
305 | { | ||
306 | struct TM_Peer *tmp = (struct TM_Peer *) value; | ||
307 | GNUNET_CONTAINER_multihashmap_remove (peers, key, value); | ||
308 | next = tmp->send_head; | ||
309 | while (NULL != (dqe = next)) | ||
310 | { | ||
311 | next = dqe->next; | ||
312 | GNUNET_CONTAINER_DLL_remove (tmp->send_head, tmp->send_tail, dqe); | ||
313 | GNUNET_free (dqe); | ||
314 | } | ||
315 | if (GNUNET_SCHEDULER_NO_TASK != tmp->send_delay_task) | ||
316 | { | ||
317 | GNUNET_SCHEDULER_cancel (tmp->send_delay_task); | ||
318 | tmp->send_delay_task = GNUNET_SCHEDULER_NO_TASK; | ||
319 | } | ||
320 | GNUNET_free (tmp); | ||
321 | } | ||
322 | return GNUNET_OK; | ||
323 | } | ||
324 | |||
325 | void | ||
326 | GST_manipulation_stop () | ||
327 | { | ||
328 | GNUNET_CONTAINER_multihashmap_iterate (peers, &free_tmps,NULL); | ||
329 | |||
330 | GNUNET_CONTAINER_multihashmap_destroy (peers); | ||
331 | peers = NULL; | ||
332 | } | ||
333 | |||
334 | |||
335 | /* end of file gnunet-service-transport_manipulation.c */ | ||