aboutsummaryrefslogtreecommitdiff
path: root/src/dv/plugin_transport_dv.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-03-15 10:35:13 +0000
committerChristian Grothoff <christian@grothoff.org>2013-03-15 10:35:13 +0000
commit914435c7d72b24b9810c5c05712a73de423feb1e (patch)
tree38bfea92c94ef47f9df1bc0297506c7d282a45d4 /src/dv/plugin_transport_dv.c
parenta815c8c65bb1d10808854e7286e761ee6a4b782c (diff)
downloadgnunet-914435c7d72b24b9810c5c05712a73de423feb1e.tar.gz
gnunet-914435c7d72b24b9810c5c05712a73de423feb1e.zip
-dv work
Diffstat (limited to 'src/dv/plugin_transport_dv.c')
-rw-r--r--src/dv/plugin_transport_dv.c247
1 files changed, 207 insertions, 40 deletions
diff --git a/src/dv/plugin_transport_dv.c b/src/dv/plugin_transport_dv.c
index c07fc52de..3b44d486d 100644
--- a/src/dv/plugin_transport_dv.c
+++ b/src/dv/plugin_transport_dv.c
@@ -37,7 +37,6 @@
37#include "gnunet_transport_plugin.h" 37#include "gnunet_transport_plugin.h"
38#include "dv.h" 38#include "dv.h"
39 39
40#define DEBUG_TEMPLATE GNUNET_EXTRA_LOGGING
41 40
42/** 41/**
43 * Encapsulation of all of the state of the plugin. 42 * Encapsulation of all of the state of the plugin.
@@ -52,9 +51,9 @@ struct Session
52{ 51{
53 52
54 /** 53 /**
55 * Stored in a linked list. 54 * Mandatory session header.
56 */ 55 */
57 struct Session *next; 56 struct SessionHeader header;
58 57
59 /** 58 /**
60 * Pointer to the global plugin struct. 59 * Pointer to the global plugin struct.
@@ -62,11 +61,6 @@ struct Session
62 struct Plugin *plugin; 61 struct Plugin *plugin;
63 62
64 /** 63 /**
65 * The client (used to identify this connection)
66 */
67 /* void *client; */
68
69 /**
70 * Continuation function to call once the transmission buffer 64 * Continuation function to call once the transmission buffer
71 * has again space available. NULL if there is no 65 * has again space available. NULL if there is no
72 * continuation to call. 66 * continuation to call.
@@ -79,30 +73,24 @@ struct Session
79 void *transmit_cont_cls; 73 void *transmit_cont_cls;
80 74
81 /** 75 /**
82 * To whom are we talking to (set to our identity 76 * To whom are we talking to.
83 * if we are still waiting for the welcome message)
84 */ 77 */
85 struct GNUNET_PeerIdentity sender; 78 struct GNUNET_PeerIdentity sender;
86 79
87 /** 80 /**
88 * At what time did we reset last_received last? 81 * Current distance to the given peer.
89 */ 82 */
90 struct GNUNET_TIME_Absolute last_quota_update; 83 uint32_t distance;
91 84
92 /** 85 /**
93 * How many bytes have we received since the "last_quota_update" 86 * Does the transport service know about this session (and we thus
94 * timestamp? 87 * need to call 'session_end' when it is released?)
95 */ 88 */
96 uint64_t last_received; 89 int active;
97
98 /**
99 * Number of bytes per ms that this peer is allowed
100 * to send to us.
101 */
102 uint32_t quota;
103 90
104}; 91};
105 92
93
106/** 94/**
107 * Encapsulation of all of the state of the plugin. 95 * Encapsulation of all of the state of the plugin.
108 */ 96 */
@@ -114,9 +102,9 @@ struct Plugin
114 struct GNUNET_TRANSPORT_PluginEnvironment *env; 102 struct GNUNET_TRANSPORT_PluginEnvironment *env;
115 103
116 /** 104 /**
117 * List of open sessions. FIXME: use hash map! 105 * Hash map of sessions (active and inactive).
118 */ 106 */
119 struct Session *sessions; 107 struct GNUNET_CONTAINER_MultiHashMap *sessions;
120 108
121 /** 109 /**
122 * Copy of the handler array where the closures are 110 * Copy of the handler array where the closures are
@@ -148,21 +136,110 @@ handle_dv_message_received (void *cls,
148{ 136{
149 struct Plugin *plugin = cls; 137 struct Plugin *plugin = cls;
150 struct GNUNET_ATS_Information ats; 138 struct GNUNET_ATS_Information ats;
151 139 struct Session *session;
140
141 session = GNUNET_CONTAINER_multihashmap_get (plugin->sessions,
142 &sender->hashPubKey);
143 if (NULL == session)
144 {
145 GNUNET_break (0);
146 return;
147 }
152 ats.type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); 148 ats.type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
153 ats.value = htonl (distance); 149 ats.value = htonl (distance);
154 150 session->active = GNUNET_YES;
155 plugin->env->receive (plugin->env->cls, sender, 151 plugin->env->receive (plugin->env->cls, sender,
156 msg, 152 msg,
157 &ats, 1, 153 &ats, 1,
158 NULL, NULL, 0); 154 session, "", 0);
155}
156
157
158/**
159 * Function called if DV starts to be able to talk to a peer.
160 *
161 * @param cls closure with 'struct Plugin'
162 * @param peer newly connected peer
163 * @param distance distance to the peer
164 */
165static void
166handle_dv_connect (void *cls,
167 const struct GNUNET_PeerIdentity *peer,
168 uint32_t distance)
169{
170 struct Plugin *plugin = cls;
171 struct Session *session;
172
173 session = GNUNET_CONTAINER_multihashmap_get (plugin->sessions,
174 &peer->hashPubKey);
175 if (NULL != session)
176 {
177 GNUNET_break (0);
178 session->distance = distance;
179 if (GNUNET_YES == session->active)
180 GNUNET_break (0); // FIXME: notify transport about distance change
181 return; /* nothing to do */
182 }
183 session = GNUNET_malloc (sizeof (struct Session));
184 session->sender = *peer;
185 session->distance = distance;
186 GNUNET_assert (GNUNET_YES ==
187 GNUNET_CONTAINER_multihashmap_put (plugin->sessions,
188 &session->sender.hashPubKey,
189 session,
190 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
159} 191}
160 192
161 193
162/* Question: how does the transport service learn of a newly connected (gossipped about) 194/**
163 * DV peer? Should the plugin (here) create a HELLO for that peer and send it along, 195 * Function called if DV distance to a peer is changed.
164 * or should the DV service create a HELLO and send it to us via the other part? 196 *
197 * @param cls closure with 'struct Plugin'
198 * @param peer connected peer
199 * @param distance new distance to the peer
165 */ 200 */
201static void
202handle_dv_distance_changed (void *cls,
203 const struct GNUNET_PeerIdentity *peer,
204 uint32_t distance)
205{
206 struct Plugin *plugin = cls;
207 struct Session *session;
208
209 session = GNUNET_CONTAINER_multihashmap_get (plugin->sessions,
210 &peer->hashPubKey);
211 if (NULL == session)
212 {
213 GNUNET_break (0);
214 handle_dv_connect (plugin, peer, distance);
215 return;
216 }
217 session->distance = distance;
218 if (GNUNET_YES == session->active)
219 GNUNET_break (0); // FIXME: notify transport about distance change
220}
221
222
223/**
224 * Function called if DV is no longer able to talk to a peer.
225 *
226 * @param cls closure with 'struct Plugin'
227 * @param peer peer that disconnected
228 */
229static void
230handle_dv_disconnect (void *cls,
231 const struct GNUNET_PeerIdentity *peer)
232{
233 struct Plugin *plugin = cls;
234 struct Session *session;
235
236 session = GNUNET_CONTAINER_multihashmap_get (plugin->sessions,
237 &peer->hashPubKey);
238 if (NULL == session)
239 return; /* nothing to do */
240 GNUNET_break (0); // FIXME!
241}
242
166 243
167/** 244/**
168 * Function that can be used by the transport service to transmit 245 * Function that can be used by the transport service to transmit
@@ -192,11 +269,11 @@ dv_plugin_send (void *cls,
192{ 269{
193 int ret = -1; 270 int ret = -1;
194 271
272 GNUNET_break (0); // FIXME!
195 return ret; 273 return ret;
196} 274}
197 275
198 276
199
200/** 277/**
201 * Function that can be used to force the plugin to disconnect 278 * Function that can be used to force the plugin to disconnect
202 * from the given peer and cancel all previous transmissions 279 * from the given peer and cancel all previous transmissions
@@ -208,8 +285,16 @@ dv_plugin_send (void *cls,
208static void 285static void
209dv_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target) 286dv_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
210{ 287{
211 // struct Plugin *plugin = cls; 288 struct Plugin *plugin = cls;
212 // TODO: Add message type to send to dv service to "disconnect" a peer 289 struct Session *session;
290
291 session = GNUNET_CONTAINER_multihashmap_get (plugin->sessions,
292 &target->hashPubKey);
293 if (NULL == session)
294 return; /* nothing to do */
295 session->transmit_cont = NULL;
296 session->transmit_cont_cls = NULL;
297 session->active = GNUNET_NO;
213} 298}
214 299
215 300
@@ -234,6 +319,9 @@ dv_plugin_address_pretty_printer (void *cls, const char *type, const void *addr,
234 GNUNET_TRANSPORT_AddressStringCallback asc, 319 GNUNET_TRANSPORT_AddressStringCallback asc,
235 void *asc_cls) 320 void *asc_cls)
236{ 321{
322 if ( (0 == addrlen) &&
323 (0 == strcmp (type, "dv")) )
324 asc (asc_cls, "dv");
237 asc (asc_cls, NULL); 325 asc (asc_cls, NULL);
238} 326}
239 327
@@ -248,9 +336,14 @@ dv_plugin_address_pretty_printer (void *cls, const char *type, const void *addr,
248 * @return string representing the DV address 336 * @return string representing the DV address
249 */ 337 */
250static const char * 338static const char *
251address_to_string (void *cls, const void *addr, size_t addrlen) 339dv_plugin_address_to_string (void *cls, const void *addr, size_t addrlen)
252{ 340{
253 return "<not implemented>"; 341 if (0 != addrlen)
342 {
343 GNUNET_break (0); /* malformed */
344 return NULL;
345 }
346 return "dv";
254} 347}
255 348
256 349
@@ -273,11 +366,12 @@ address_to_string (void *cls, const void *addr, size_t addrlen)
273static int 366static int
274dv_plugin_check_address (void *cls, const void *addr, size_t addrlen) 367dv_plugin_check_address (void *cls, const void *addr, size_t addrlen)
275{ 368{
276 return GNUNET_SYSERR; 369 if (0 != addrlen)
370 return GNUNET_SYSERR;
371 return GNUNET_OK;
277} 372}
278 373
279 374
280
281/** 375/**
282 * Create a new session to transmit data to the target 376 * Create a new session to transmit data to the target
283 * This session will used to send data to this peer and the plugin will 377 * This session will used to send data to this peer and the plugin will
@@ -291,7 +385,46 @@ static struct Session *
291dv_get_session (void *cls, 385dv_get_session (void *cls,
292 const struct GNUNET_HELLO_Address *address) 386 const struct GNUNET_HELLO_Address *address)
293{ 387{
294 return NULL; 388 struct Plugin *plugin = cls;
389 struct Session *session;
390
391 if (0 != address->address_length)
392 return NULL;
393 session = GNUNET_CONTAINER_multihashmap_get (plugin->sessions,
394 &address->peer.hashPubKey);
395 if (NULL == session)
396 return NULL; /* not valid right now */
397 session->active = GNUNET_YES;
398 return session;
399}
400
401
402/**
403 * Function called to convert a string address to
404 * a binary address.
405 *
406 * @param cls closure ('struct Plugin*')
407 * @param addr string address
408 * @param addrlen length of the address including \0 termination
409 * @param buf location to store the buffer
410 * If the function returns GNUNET_SYSERR, its contents are undefined.
411 * @param added length of created address
412 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
413 */
414static int
415dv_plugin_string_to_address (void *cls,
416 const char *addr,
417 uint16_t addrlen,
418 void **buf,
419 size_t *added)
420{
421 if ( (addrlen == 3) &&
422 (0 == strcmp ("dv", addr)) )
423 {
424 *added = 0;
425 return GNUNET_OK;
426 }
427 return GNUNET_SYSERR;
295} 428}
296 429
297 430
@@ -307,24 +440,54 @@ libgnunet_plugin_transport_dv_init (void *cls)
307 440
308 plugin = GNUNET_malloc (sizeof (struct Plugin)); 441 plugin = GNUNET_malloc (sizeof (struct Plugin));
309 plugin->env = env; 442 plugin->env = env;
443 plugin->sessions = GNUNET_CONTAINER_multihashmap_create (1024 * 8, GNUNET_YES);
310 plugin->dvh = GNUNET_DV_service_connect (env->cfg, 444 plugin->dvh = GNUNET_DV_service_connect (env->cfg,
311 plugin, 445 plugin,
312 NULL, NULL, NULL, /*FIXME! */ 446 &handle_dv_connect,
447 &handle_dv_distance_changed,
448 &handle_dv_disconnect,
313 &handle_dv_message_received); 449 &handle_dv_message_received);
450 if (NULL == plugin->dvh)
451 {
452 GNUNET_CONTAINER_multihashmap_destroy (plugin->sessions);
453 GNUNET_free (plugin);
454 return NULL;
455 }
314 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions)); 456 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
315 api->cls = plugin; 457 api->cls = plugin;
316 api->send = &dv_plugin_send; 458 api->send = &dv_plugin_send;
317 api->disconnect = &dv_plugin_disconnect; 459 api->disconnect = &dv_plugin_disconnect;
318 api->address_pretty_printer = &dv_plugin_address_pretty_printer; 460 api->address_pretty_printer = &dv_plugin_address_pretty_printer;
319 api->check_address = &dv_plugin_check_address; 461 api->check_address = &dv_plugin_check_address;
320 api->address_to_string = &address_to_string; 462 api->address_to_string = &dv_plugin_address_to_string;
321 api->string_to_address = NULL; /* FIXME */ 463 api->string_to_address = &dv_plugin_string_to_address;
322 api->get_session = dv_get_session; 464 api->get_session = dv_get_session;
323 return api; 465 return api;
324} 466}
325 467
326 468
327/** 469/**
470 * Function called to free a session.
471 *
472 * @param cls NULL
473 * @param key unused
474 * @param value session to free
475 * @return GNUNET_OK (continue to iterate)
476 */
477static int
478free_session_iterator (void *cls,
479 const struct GNUNET_HashCode *key,
480 void *value)
481{
482 struct Session *session = value;
483
484 // FIXME: still call transmit_cont's here!?
485 GNUNET_free (session);
486 return GNUNET_OK;
487}
488
489
490/**
328 * Exit point from the plugin. 491 * Exit point from the plugin.
329 */ 492 */
330void * 493void *
@@ -334,6 +497,10 @@ libgnunet_plugin_transport_dv_done (void *cls)
334 struct Plugin *plugin = api->cls; 497 struct Plugin *plugin = api->cls;
335 498
336 GNUNET_DV_service_disconnect (plugin->dvh); 499 GNUNET_DV_service_disconnect (plugin->dvh);
500 GNUNET_CONTAINER_multihashmap_iterate (plugin->sessions,
501 &free_session_iterator,
502 NULL);
503 GNUNET_CONTAINER_multihashmap_destroy (plugin->sessions);
337 GNUNET_free (plugin); 504 GNUNET_free (plugin);
338 GNUNET_free (api); 505 GNUNET_free (api);
339 return NULL; 506 return NULL;