From 3883c9b973ddcbdc88d9807dbe4252a56ece5f92 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 9 Jul 2011 11:54:47 +0000 Subject: [PATCH] new fragmentation API design - with retransmit --- src/fragmentation/Makefile.am | 23 +-- src/fragmentation/defragmentation_new.c | 109 +++++++++++++ src/fragmentation/fragmentation.h | 52 +++++++ src/fragmentation/fragmentation_new.c | 195 ++++++++++++++++++++++++ src/include/gnunet_fragmentation_lib.h | 104 +++++++++---- 5 files changed, 446 insertions(+), 37 deletions(-) create mode 100644 src/fragmentation/defragmentation_new.c create mode 100644 src/fragmentation/fragmentation.h create mode 100644 src/fragmentation/fragmentation_new.c diff --git a/src/fragmentation/Makefile.am b/src/fragmentation/Makefile.am index 5b1367260..15e356fcc 100644 --- a/src/fragmentation/Makefile.am +++ b/src/fragmentation/Makefile.am @@ -11,20 +11,21 @@ endif lib_LTLIBRARIES = libgnunetfragmentation.la libgnunetfragmentation_la_SOURCES = \ - fragmentation.c + fragmentation_new.c \ + defragmentation_new.c libgnunetfragmentation_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la -check_PROGRAMS = \ - test_fragmentation +#check_PROGRAMS = \ +# test_fragmentation -if ENABLE_TEST_RUN -TESTS = $(check_PROGRAMS) -endif +#if ENABLE_TEST_RUN +#TESTS = $(check_PROGRAMS) +#endif -test_fragmentation_SOURCES = \ - test_frag_ji.c -test_fragmentation_LDADD = \ - $(top_builddir)/src/fragmentation/libgnunetfragmentation.la \ - $(top_builddir)/src/util/libgnunetutil.la +#test_fragmentation_SOURCES = \ +# test_frag_ji.c +#test_fragmentation_LDADD = \ +# $(top_builddir)/src/fragmentation/libgnunetfragmentation.la \ +# $(top_builddir)/src/util/libgnunetutil.la diff --git a/src/fragmentation/defragmentation_new.c b/src/fragmentation/defragmentation_new.c new file mode 100644 index 000000000..8fdc334d9 --- /dev/null +++ b/src/fragmentation/defragmentation_new.c @@ -0,0 +1,109 @@ +/* + This file is part of GNUnet + (C) 2009, 2011 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/** + * @file src/fragmentation/defragmentation_new.c + * @brief library to help defragment messages + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet_fragmentation_lib.h" +#include "fragmentation.h" + +/** + * Defragmentation context. + */ +struct GNUNET_DEFRAGMENT_Context +{ + + /** + * For statistics. + */ + struct GNUNET_STATISTICS_Handle *stats; + + /** + * Closure for 'proc' and 'ackp'. + */ + void *cls; + + /** + * Function to call with defragmented messages. + */ + GNUNET_FRAGMENT_MessageProcessor proc; + + /** + * Function to call with acknowledgements. + */ + GNUNET_FRAGMENT_MessageProcessor ackp; +}; + + +/** + * Create a defragmentation context. + * + * @param stats statistics context + * @param cls closure for proc and ackp + * @param proc function to call with defragmented messages + * @param ackp function to call with acknowledgements (to send + * back to the other side) + * @return the defragmentation context + */ +struct GNUNET_DEFRAGMENT_Context * +GNUNET_DEFRAGMENT_context_create (struct GNUNET_STATISTICS_Handle *stats, + void *cls, + GNUNET_FRAGMENT_MessageProcessor proc, + GNUNET_FRAGMENT_MessageProcessor ackp) +{ + struct GNUNET_DEFRAGMENT_Context *dc; + + dc = GNUNET_malloc (sizeof (struct GNUNET_DEFRAGMENT_Context)); + dc->stats = stats; + dc->cls = cls; + dc->proc = proc; + dc->ackp = ackp; + return dc; +} + + +/** + * Destroy the given defragmentation context. + * + * @param dc defragmentation context + */ +void +GNUNET_DEFRAGMENT_context_destroy (struct GNUNET_DEFRAGMENT_Context *dc) +{ + GNUNET_free (dc); +} + + +/** + * We have received a fragment. Process it. + * + * @param dc the context + * @param msg the message that was received + */ +void +GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc, + const struct GNUNET_MessageHeader *msg) +{ +} + +/* end of defragmentation_new.c */ + diff --git a/src/fragmentation/fragmentation.h b/src/fragmentation/fragmentation.h new file mode 100644 index 000000000..e9b3faba5 --- /dev/null +++ b/src/fragmentation/fragmentation.h @@ -0,0 +1,52 @@ +/* + This file is part of GNUnet + (C) 2009, 2011 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/** + * @file src/fragmentation/fragmentation.h + * @brief library to help fragment messages + * @author Christian Grothoff + */ +#ifndef FRAGMENTATION_H +#define FRAGMENTATION_H +#include "platform.h" +#include "gnunet_fragmentation_lib.h" + +/** + * Header for a message fragment. + */ +struct FragmentHeader +{ + + struct GNUNET_MessageHeader header; + +}; + + +/** + * Message fragment acknowledgement. + */ +struct FragmentAcknowledgement +{ + + struct GNUNET_MessageHeader header; + +}; + + +#endif diff --git a/src/fragmentation/fragmentation_new.c b/src/fragmentation/fragmentation_new.c new file mode 100644 index 000000000..a95afc4a4 --- /dev/null +++ b/src/fragmentation/fragmentation_new.c @@ -0,0 +1,195 @@ +/* + This file is part of GNUnet + (C) 2009, 2011 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/** + * @file src/fragmentation/fragmentation_new.c + * @brief library to help fragment messages + * @author Christian Grothoff + */ + +#include "platform.h" +#include "gnunet_fragmentation_lib.h" +#include "fragmentation.h" + +/** + * Fragmentation context. + */ +struct GNUNET_FRAGMENT_Context +{ + /** + * Statistics to use. + */ + struct GNUNET_STATISTICS_Handle *stats; + + /** + * Tracker for flow control. + */ + struct GNUNET_BANDWIDTH_Tracker *tracker; + + /** + * Current expected delay for ACKs. + */ + struct GNUNET_TIME_Relative delay; + + /** + * Message to fragment (allocated at the end of this struct). + */ + const struct GNUNET_MessageHeader *msg; + + /** + * Function to call for transmissions. + */ + GNUNET_FRAGMENT_MessageProcessor proc; + + /** + * Closure for 'proc'. + */ + void *proc_cls; + + /** + * Bitfield, set to 1 for each unacknowledged fragment. + */ + uint64_t acks; + + /** + * Task performing work for the fragmenter. + */ + GNUNET_SCHEDULER_TaskIdentifier task; + + /** + * Target fragment size. + */ + uint16_t mtu; + +}; + + +/** + * Transmit the next fragment to the other peer. + * + * @param cls the 'struct GNUNET_FRAGMENT_Context' + * @param tc scheduler context + */ +static void +transmit_next (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct GNUNET_FRAGMENT_Context *fc = cls; + + fc->task = GNUNET_SCHEDULER_NO_TASK; +} + + +/** + * Create a fragmentation context for the given message. + * Fragments the message into fragments of size "mtu" or + * less. Calls 'proc' on each un-acknowledged fragment, + * using both the expected 'delay' between messages and + * acknowledgements and the given 'tracker' to guide the + * frequency of calls to 'proc'. + * + * @param stats statistics context + * @param mtu the maximum message size for each fragment + * @param tracker bandwidth tracker to use for flow control (can be NULL) + * @param delay expected delay between fragment transmission + * and ACK based on previous messages + * @param msg the message to fragment + * @param proc function to call for each fragment to transmit + * @param proc_cls closure for proc + * @return the fragmentation context + */ +struct GNUNET_FRAGMENT_Context * +GNUNET_FRAGMENT_context_create (struct GNUNET_STATISTICS_Handle *stats, + uint16_t mtu, + struct GNUNET_BANDWIDTH_Tracker *tracker, + struct GNUNET_TIME_Relative delay, + const struct GNUNET_MessageHeader *msg, + GNUNET_FRAGMENT_MessageProcessor proc, + void *proc_cls) +{ + struct GNUNET_FRAGMENT_Context *fc; + size_t size; + uint64_t bits; + + GNUNET_assert (mtu >= 1024 + sizeof (struct FragmentHeader)); + size = ntohs (msg->size); + GNUNET_assert (size > mtu); + fc = GNUNET_malloc (sizeof (struct GNUNET_FRAGMENT_Context) + size); + fc->stats = stats; + fc->mtu = mtu; + fc->tracker = tracker; + fc->delay = delay; + fc->msg = (const struct GNUNET_MessageHeader*)&fc[1]; + fc->proc = proc; + fc->proc_cls = proc_cls; + memcpy (&fc[1], msg, size); + bits = (size + mtu - 1) / (mtu - sizeof (struct FragmentHeader)); + GNUNET_assert (bits <= 64); + if (bits == 64) + fc->acks = UINT64_MAX; /* set all 64 bit */ + else + fc->acks = (1 << bits) - 1; /* set lowest 'bits' bit */ + fc->task = GNUNET_SCHEDULER_add_delayed (GNUNET_BANDWIDTH_tracker_get_delay (tracker, mtu), + &transmit_next, + fc); + return fc; +} + + +/** + * Process an acknowledgement message we got from the other + * side (to control re-transmits). + * + * @param fc fragmentation context + * @param msg acknowledgement message we received + * @return GNUNET_OK if this ack completes the work of the 'fc' + * (all fragments have been received); + * GNUNET_NO if more messages are pending + * GNUNET_SYSERR if this ack is not valid for this fc + */ +int +GNUNET_FRAGMENT_process_ack (struct GNUNET_FRAGMENT_Context *fc, + const struct GNUNET_MessageHeader *msg) +{ + return GNUNET_SYSERR; +} + + +/** + * Destroy the given fragmentation context (stop calling 'proc', free + * resources). + * + * @param fc fragmentation context + * @return average delay between transmission and ACK for the + * last message, FOREVER if the message was not fully transmitted + */ +struct GNUNET_TIME_Relative +GNUNET_FRAGMENT_context_destroy (struct GNUNET_FRAGMENT_Context *fc) +{ + struct GNUNET_TIME_Relative ret; + + if (fc->task != GNUNET_SCHEDULER_NO_TASK) + GNUNET_SCHEDULER_cancel (fc->task); + ret = fc->delay; + GNUNET_free (fc); + return ret; +} + +/* end of fragmentation_new.c */ + diff --git a/src/include/gnunet_fragmentation_lib.h b/src/include/gnunet_fragmentation_lib.h index 5c08b2f69..b2ba064f8 100644 --- a/src/include/gnunet_fragmentation_lib.h +++ b/src/include/gnunet_fragmentation_lib.h @@ -1,6 +1,6 @@ /* This file is part of GNUnet - (C) 2009 Christian Grothoff (and other contributing authors) + (C) 2009, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -26,7 +26,8 @@ #ifndef GNUNET_FRAGMENTATION_LIB_H #define GNUNET_FRAGMENTATION_LIB_H -#include "gnunet_common.h" +#include "gnunet_util_lib.h" +#include "gnunet_bandwidth_lib.h" #include "gnunet_statistics_service.h" #ifdef __cplusplus @@ -37,6 +38,13 @@ extern "C" #endif #endif + +/** + * Fragmentation context. + */ +struct GNUNET_FRAGMENT_Context; + + /** * Function that is called with messages * created by the fragmentation module. @@ -45,61 +53,105 @@ extern "C" * @param msg the message that was created */ typedef void (*GNUNET_FRAGMENT_MessageProcessor) (void *cls, - const struct - GNUNET_MessageHeader * msg); + const struct GNUNET_MessageHeader *msg); /** - * Fragment an over-sized message. + * Create a fragmentation context for the given message. + * Fragments the message into fragments of size "mtu" or + * less. Calls 'proc' on each un-acknowledged fragment, + * using both the expected 'delay' between messages and + * acknowledgements and the given 'tracker' to guide the + * frequency of calls to 'proc'. * + * @param stats statistics context + * @param mtu the maximum message size for each fragment + * @param tracker bandwidth tracker to use for flow control (can be NULL) + * @param delay expected delay between fragment transmission + * and ACK based on previous messages * @param msg the message to fragment - * @param mtu the maximum message size - * @param proc function to call for each fragment + * @param proc function to call for each fragment to transmit * @param proc_cls closure for proc + * @return the fragmentation context + */ +struct GNUNET_FRAGMENT_Context * +GNUNET_FRAGMENT_context_create (struct GNUNET_STATISTICS_Handle *stats, + uint16_t mtu, + struct GNUNET_BANDWIDTH_Tracker *tracker, + struct GNUNET_TIME_Relative delay, + const struct GNUNET_MessageHeader *msg, + GNUNET_FRAGMENT_MessageProcessor proc, + void *proc_cls); + + +/** + * Process an acknowledgement message we got from the other + * side (to control re-transmits). + * + * @param fc fragmentation context + * @param msg acknowledgement message we received + * @return GNUNET_OK if this ack completes the work of the 'fc' + * (all fragments have been received); + * GNUNET_NO if more messages are pending + * GNUNET_SYSERR if this ack is not valid for this fc */ -void GNUNET_FRAGMENT_fragment (const struct GNUNET_MessageHeader *msg, - uint16_t mtu, - GNUNET_FRAGMENT_MessageProcessor proc, - void *proc_cls); +int GNUNET_FRAGMENT_process_ack (struct GNUNET_FRAGMENT_Context *fc, + const struct GNUNET_MessageHeader *msg); + + +/** + * Destroy the given fragmentation context (stop calling 'proc', free + * resources). + * + * @param fc fragmentation context + * @return average delay between transmission and ACK for the + * last message, FOREVER if the message was not fully transmitted + */ +struct GNUNET_TIME_Relative +GNUNET_FRAGMENT_context_destroy (struct GNUNET_FRAGMENT_Context *fc); + /** * Defragmentation context. */ -struct GNUNET_FRAGMENT_Context; +struct GNUNET_DEFRAGMENT_Context; + /** * Create a defragmentation context. * * @param stats statistics context + * @param cls closure for proc and ackp * @param proc function to call with defragmented messages - * @param proc_cls closure for proc + * @param ackp function to call with acknowledgements (to send + * back to the other side) * @return the defragmentation context */ -struct GNUNET_FRAGMENT_Context *GNUNET_FRAGMENT_context_create (struct - GNUNET_STATISTICS_Handle - *stats, - GNUNET_FRAGMENT_MessageProcessor - proc, - void - *proc_cls); +struct GNUNET_DEFRAGMENT_Context * +GNUNET_DEFRAGMENT_context_create (struct GNUNET_STATISTICS_Handle *stats, + void *cls, + GNUNET_FRAGMENT_MessageProcessor proc, + GNUNET_FRAGMENT_MessageProcessor ackp); /** * Destroy the given defragmentation context. + * + * @param dc defragmentation context */ -void GNUNET_FRAGMENT_context_destroy (struct GNUNET_FRAGMENT_Context *ctx); +void +GNUNET_DEFRAGMENT_context_destroy (struct GNUNET_DEFRAGMENT_Context *dc); /** * We have received a fragment. Process it. * - * @param ctx the context - * @param sender who transmitted the fragment + * @param dc the context * @param msg the message that was received */ -void GNUNET_FRAGMENT_process (struct GNUNET_FRAGMENT_Context *ctx, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *msg); +void +GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc, + const struct GNUNET_MessageHeader *msg); #if 0 /* keep Emacsens' auto-indent happy */ -- 2.25.1