2 This file is part of GNUnet.
3 (C) 2010,2011 Christian Grothoff (and other contributing authors)
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.
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.
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.
22 * @file transport/gnunet-service-transport_manipulation.c
23 * @brief transport component manipulation traffic for simulation
24 * @author Christian Grothoff
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"
37 static struct GNUNET_CONTAINER_MultiHashMap *peers;
44 struct DelayQueueEntry
46 struct DelayQueueEntry *prev;
47 struct DelayQueueEntry *next;
49 struct GNUNET_TIME_Absolute sent_at;
52 struct GNUNET_TIME_Relative timeout;
53 GST_NeighbourSendContinuation cont;
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;
69 set_delay(struct TM_Peer *tmp, struct GNUNET_PeerIdentity *peer, int direction, uint32_t value)
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);
76 if (UINT32_MAX == value)
77 val = UINT32_MAX - 1; /* prevent overflow */
79 val = UINT32_MAX; /* disable */
85 tmp->metrics[TM_SEND][DELAY] = val;
86 tmp->metrics[TM_RECEIVE][DELAY] = val;
89 tmp->metrics[TM_SEND][DELAY] = val;
92 tmp->metrics[TM_RECEIVE][DELAY] = val;
101 set_distance (struct TM_Peer *tmp, struct GNUNET_PeerIdentity *peer, int direction, uint32_t value)
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);
108 if (UINT32_MAX == value)
109 val = UINT32_MAX - 1; /* prevent overflow */
111 val = UINT32_MAX; /* disable */
117 tmp->metrics[TM_SEND][DISTANCE] = val;
118 tmp->metrics[TM_RECEIVE][DISTANCE] = val;
121 tmp->metrics[TM_SEND][DISTANCE] = val;
124 tmp->metrics[TM_RECEIVE][DISTANCE] = val;
132 GST_manipulation_set_metric (void *cls, struct GNUNET_SERVER_Client *client,
133 const struct GNUNET_MessageHeader *message)
135 struct TrafficMetricMessage *tm = (struct TrafficMetricMessage *) message;
136 struct GNUNET_ATS_Information *ats;
143 if (0 == ntohs (tm->ats_count))
144 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
146 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received traffic metrics for peer `%s'\n",
147 GNUNET_i2s(&tm->peer));
149 if (NULL == (tmp = GNUNET_CONTAINER_multihashmap_get (peers, &tm->peer.hashPubKey)))
151 tmp = GNUNET_malloc (sizeof (struct TM_Peer));
152 tmp->peer = (tm->peer);
153 for (c = 0; c < TM_BOTH; c++)
155 for (c2 = 0; c2 < GNUNET_ATS_QualityPropertiesCount; c2++)
157 tmp->metrics[c][c2] = UINT32_MAX;
160 GNUNET_CONTAINER_multihashmap_put (peers, &tm->peer.hashPubKey, tmp, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
163 ats = (struct GNUNET_ATS_Information *) &tm[1];
164 for (c = 0; c < ntohs (tm->ats_count); c++)
166 type = htonl (ats[c].type);
167 value = htonl (ats[c].value);
169 case GNUNET_ATS_QUALITY_NET_DELAY:
170 set_delay (tmp, &tm->peer, ntohs (tm->direction), value);
172 case GNUNET_ATS_QUALITY_NET_DISTANCE:
173 set_distance (tmp, &tm->peer, ntohs (tm->direction), value);
180 GNUNET_SERVER_receive_done (client, GNUNET_OK);
184 send_delayed (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
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);
194 next = tmp->send_head;
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);
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)
211 struct DelayQueueEntry *dqe;
212 struct GNUNET_TIME_Relative delay;
214 if (NULL != (tmp = GNUNET_CONTAINER_multihashmap_get (peers, &target->hashPubKey)))
216 /* Manipulate here */
218 if (UINT32_MAX != tmp->metrics[TM_SEND][DELAY])
220 /* We have a delay */
221 delay.rel_value = tmp->metrics[TM_SEND][DELAY];
222 dqe = GNUNET_malloc (sizeof (struct DelayQueueEntry) + msg_size);
224 dqe->sent_at = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), delay);
226 dqe->cont_cls = cont_cls;
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);
238 GST_neighbours_send (target, msg, msg_size, timeout, cont, cont_cls);
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)
251 struct GNUNET_ATS_Information ats_new[ats_count];
252 struct GNUNET_TIME_Relative q_delay;
253 struct GNUNET_TIME_Relative m_delay;
255 for (d = 0; d < ats_count; d++)
257 if (NULL != (tmp = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey)))
259 /* Manipulate distance */
260 for (d = 0; d < ats_count; d++)
264 if ((ntohl(ats[d].type) == GNUNET_ATS_QUALITY_NET_DISTANCE) &&
265 (UINT32_MAX != tmp->metrics[TM_RECEIVE][DISTANCE]))
266 ats_new[d].value = htonl(tmp->metrics[TM_RECEIVE][DISTANCE]);
268 /* Manipulate receive delay */
269 if (UINT32_MAX != tmp->metrics[TM_RECEIVE][DELAY])
271 m_delay.rel_value = tmp->metrics[TM_RECEIVE][DELAY];
272 q_delay = GST_receive_callback (cls, peer, message, &ats_new[0], ats_count,
273 session, sender_address, sender_address_len);
275 if (q_delay.rel_value >= m_delay.rel_value)
285 return GST_receive_callback (cls, peer, message, &ats_new[0], ats_count,
286 session, sender_address, sender_address_len);
289 return GST_receive_callback (cls, peer, message, ats, ats_count,
290 session, sender_address, sender_address_len);
294 GST_manipulation_init ()
296 peers = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
299 int free_tmps (void *cls,
300 const struct GNUNET_HashCode * key,
303 struct DelayQueueEntry *dqe;
304 struct DelayQueueEntry *next;
307 struct TM_Peer *tmp = (struct TM_Peer *) value;
308 GNUNET_CONTAINER_multihashmap_remove (peers, key, value);
309 next = tmp->send_head;
310 while (NULL != (dqe = next))
313 GNUNET_CONTAINER_DLL_remove (tmp->send_head, tmp->send_tail, dqe);
316 if (GNUNET_SCHEDULER_NO_TASK != tmp->send_delay_task)
318 GNUNET_SCHEDULER_cancel (tmp->send_delay_task);
319 tmp->send_delay_task = GNUNET_SCHEDULER_NO_TASK;
327 GST_manipulation_stop ()
329 GNUNET_CONTAINER_multihashmap_iterate (peers, &free_tmps,NULL);
331 GNUNET_CONTAINER_multihashmap_destroy (peers);
336 /* end of file gnunet-service-transport_manipulation.c */