From: Christian Grothoff Date: Fri, 15 Mar 2013 12:57:54 +0000 (+0000) Subject: -draft for DV plugin X-Git-Tag: initial-import-from-subversion-38251~9622 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=efb9b0d1a203a6381eacf6905a4ae43014d8804b;p=oweals%2Fgnunet.git -draft for DV plugin --- diff --git a/src/dv/plugin_transport_dv.c b/src/dv/plugin_transport_dv.c index 3b44d486d..1c03d4a5f 100644 --- a/src/dv/plugin_transport_dv.c +++ b/src/dv/plugin_transport_dv.c @@ -45,20 +45,20 @@ struct Plugin; /** - * Session handle for connections. + * An active request for transmission via DV. */ -struct Session +struct PendingRequest { /** - * Mandatory session header. + * This is a DLL. */ - struct SessionHeader header; + struct PendingRequest *next; /** - * Pointer to the global plugin struct. + * This is a DLL. */ - struct Plugin *plugin; + struct PendingRequest *prev; /** * Continuation function to call once the transmission buffer @@ -72,6 +72,45 @@ struct Session */ void *transmit_cont_cls; + /** + * Transmission handle from DV client library. + */ + struct GNUNET_DV_TransmitHandle *th; + + /** + * Session of this request. + */ + struct Session *session; + +}; + + +/** + * Session handle for connections. + */ +struct Session +{ + + /** + * Mandatory session header. + */ + struct SessionHeader header; + + /** + * Pointer to the global plugin struct. + */ + struct Plugin *plugin; + + /** + * Head of pending requests. + */ + struct PendingRequest *pr_head; + + /** + * Tail of pending requests. + */ + struct PendingRequest *pr_tail; + /** * To whom are we talking to. */ @@ -120,6 +159,18 @@ struct Plugin }; +/** + * Notify transport service about the change in distance. + * + * @param session session where the distance changed + */ +static void +notify_distance_change (struct Session *session) +{ + GNUNET_break (0); // FIXME: need extended plugin API! +} + + /** * Handler for messages received from the DV service. * @@ -177,7 +228,7 @@ handle_dv_connect (void *cls, GNUNET_break (0); session->distance = distance; if (GNUNET_YES == session->active) - GNUNET_break (0); // FIXME: notify transport about distance change + notify_distance_change (session); return; /* nothing to do */ } session = GNUNET_malloc (sizeof (struct Session)); @@ -216,7 +267,43 @@ handle_dv_distance_changed (void *cls, } session->distance = distance; if (GNUNET_YES == session->active) - GNUNET_break (0); // FIXME: notify transport about distance change + notify_distance_change (session); +} + + +/** + * Release session object and clean up associated resources. + * + * @param session session to clean up + */ +static void +free_session (struct Session *session) +{ + struct Plugin *plugin = session->plugin; + struct PendingRequest *pr; + + GNUNET_assert (GNUNET_YES == + GNUNET_CONTAINER_multihashmap_remove (plugin->sessions, + &session->sender.hashPubKey, + session)); + if (GNUNET_YES == session->active) + plugin->env->session_end (plugin->env->cls, + &session->sender, + session); + while (NULL != (pr = session->pr_head)) + { + GNUNET_CONTAINER_DLL_remove (session->pr_head, + session->pr_tail, + pr); + GNUNET_DV_send_cancel (pr->th); + pr->th = NULL; + if (NULL != pr->transmit_cont) + pr->transmit_cont (pr->transmit_cont_cls, + &session->sender, + GNUNET_SYSERR, 0, 0); + GNUNET_free (pr); + } + GNUNET_free (session); } @@ -236,8 +323,34 @@ handle_dv_disconnect (void *cls, session = GNUNET_CONTAINER_multihashmap_get (plugin->sessions, &peer->hashPubKey); if (NULL == session) - return; /* nothing to do */ - GNUNET_break (0); // FIXME! + return; /* nothing to do */ + free_session (session); +} + + +/** + * Function called once the delivery of a message has been successful. + * Clean up the pending request, and call continuations. + * + * @param cls closure + * @param ok GNUNET_OK on success, GNUNET_SYSERR on error + */ +static void +send_finished (void *cls, + int ok) +{ + struct PendingRequest *pr = cls; + struct Session *session = pr->session; + + pr->th = NULL; + GNUNET_CONTAINER_DLL_remove (session->pr_head, + session->pr_tail, + pr); + if (NULL != pr->transmit_cont) + pr->transmit_cont (pr->transmit_cont_cls, + &session->sender, + ok, 0, 0); + GNUNET_free (pr); } @@ -267,10 +380,24 @@ dv_plugin_send (void *cls, struct GNUNET_TIME_Relative timeout, GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) { - int ret = -1; - - GNUNET_break (0); // FIXME! - return ret; + struct PendingRequest *pr; + const struct GNUNET_MessageHeader *msg; + + msg = (const struct GNUNET_MessageHeader *) msgbuf; + GNUNET_assert (ntohs (msg->size) == msgbuf_size); // API will change... + pr = GNUNET_malloc (sizeof (struct PendingRequest)); + pr->transmit_cont = cont; + pr->transmit_cont_cls = cont_cls; + pr->session = session; + GNUNET_CONTAINER_DLL_insert_tail (session->pr_head, + session->pr_tail, + pr); + pr->th = GNUNET_DV_send (session->plugin->dvh, + &session->sender, + msg, + &send_finished, + pr); + return 0; /* DV */ } @@ -287,13 +414,25 @@ dv_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target) { struct Plugin *plugin = cls; struct Session *session; + struct PendingRequest *pr; session = GNUNET_CONTAINER_multihashmap_get (plugin->sessions, &target->hashPubKey); if (NULL == session) return; /* nothing to do */ - session->transmit_cont = NULL; - session->transmit_cont_cls = NULL; + while (NULL != (pr = session->pr_head)) + { + GNUNET_CONTAINER_DLL_remove (session->pr_head, + session->pr_tail, + pr); + GNUNET_DV_send_cancel (pr->th); + pr->th = NULL; + if (NULL != pr->transmit_cont) + pr->transmit_cont (pr->transmit_cont_cls, + &session->sender, + GNUNET_SYSERR, 0, 0); + GNUNET_free (pr); + } session->active = GNUNET_NO; } @@ -481,8 +620,7 @@ free_session_iterator (void *cls, { struct Session *session = value; - // FIXME: still call transmit_cont's here!? - GNUNET_free (session); + free_session (session); return GNUNET_OK; }