vss: unify calls to the FEC layer
authorGerrit Renker <grenker@cscs.ch>
Sun, 23 May 2010 05:43:03 +0000 (07:43 +0200)
committerAndre Noll <maan@systemlinux.org>
Mon, 7 Jun 2010 21:24:52 +0000 (23:24 +0200)
This reorganizes the internal vss data structures a bit to unify calls to the
FEC layer across different senders:
 * each sender supplies its sender_client data via the 'sc' pointer;
 * the init_fec()/send_fec() function pointers are now parameters
   (so that a global variable is not needed);
 * both these functions then operate on the supplied sender_client data;
 * the transport layer can then interpret the sender_client data in
   specific ways, e.g. by accessing sc->private_data;
 * a new 'ready' flag has been added to track transport-layer state;
 * max_slice_size as paramter has been restored (for overriding MPS value).

Note: this is one patch out of several. It comments out now-incompatible
      changes in the API for the sake of being able to compile. However,
      the new global API requires the whole set of patches to be applied.

dccp_send.c
send.h
send_common.c
server.h
udp_send.c
vss.c
vss.h

index 0e69a96..b13f719 100644 (file)
@@ -141,7 +141,7 @@ static void dccp_post_select(fd_set *rfds, __a_unused fd_set *wfds)
        dfc = para_calloc(sizeof(*dfc));
        sc->private_data = dfc;
        dfc->sc = sc;
-       vss_add_fec_client(self, dfc, &dfc->fc);
+       /* XXX RESOLVED LATER vss_add_fec_client(self, dfc, &dfc->fc); */
 }
 
 static int dccp_com_on(__a_unused struct sender_command_data *scd)
diff --git a/send.h b/send.h
index 72c7a6c..f831cbc 100644 (file)
--- a/send.h
+++ b/send.h
@@ -20,6 +20,7 @@ enum {SENDER_ADD, SENDER_DELETE, SENDER_ALLOW, SENDER_DENY, SENDER_ON, SENDER_OF
  * vss_del_fec_client().
  */
 struct fec_client;
+struct sender_client;
 
 /** FEC parameters requested by FEC clients. */
 struct fec_client_parms {
@@ -29,6 +30,20 @@ struct fec_client_parms {
        uint8_t data_slices_per_group;
        /** Maximal number of bytes per slice, initially zero. */
        uint16_t max_slice_bytes;
+       /**
+        * Transport-layer initialisation for FEC support.
+        *
+        * This optional function serves (a) to make the transport layer
+        * ready to send FEC slices and (b) to determine the Maximum
+        * Packet Size (MPS) supported by the connection. The MPS value
+        * determines the largest payload size. This value is used to
+        * send FEC slices that are not larger than the path MTU, to avoid
+        * fragmentation and to maximize packet utilization. The user can
+        * alternatively specify a slice size of up to this value.
+        */
+       int (*init_fec)(struct sender_client *sc);
+       /** Push out FEC-encoded packets */
+       int (*send_fec)(struct sender_client *sc, char *buf, size_t len);
 };
 
 /**
index ed140c8..3b23801 100644 (file)
@@ -417,6 +417,7 @@ static int parse_fec_parms(const char *arg, struct sender_command_data *scd)
        ret = -ERRNO_TO_PARA_ERROR(EINVAL);
        if (val < 0 || val > 65535)
                goto out;
+       scd->max_slice_bytes = val;
        /* parse data_slices_per_group */
        b = e + 1;
        e = strchr(b, ':');
@@ -479,6 +480,7 @@ int parse_fec_url(const char *arg, struct sender_command_data *scd)
                goto out;
        }
        /* use default fec parameters. */
+       scd->max_slice_bytes = 0;
        scd->slices_per_group = 16;
        scd->data_slices_per_group = 14;
        ret = 0;
index 822e80e..43ba841 100644 (file)
--- a/server.h
+++ b/server.h
@@ -25,6 +25,8 @@ struct sender_command_data{
        int netmask;
        /** The port number for add/remove. */
        int port;
+       /** Maximal slice size. */
+       uint16_t max_slice_bytes;
        /** Number of data slices plus redundant slices. */
        uint8_t slices_per_group;
        /** Number of slices minus number of redundant slices. */
index 29deafb..478c5d9 100644 (file)
@@ -279,7 +279,7 @@ static void udp_add_target(struct sender_command_data *scd)
        para_list_add(&ut->node, &targets);
        ut->fcp.slices_per_group = scd->slices_per_group;
        ut->fcp.data_slices_per_group = scd->data_slices_per_group;
-       vss_add_fec_client(self, ut, &ut->fc);
+       /* XXX RESOLVED LATER vss_add_fec_client(self, ut, &ut->fc); */
 }
 
 static int udp_com_add(struct sender_command_data *scd)
diff --git a/vss.c b/vss.c
index afde0dc..4be6e18 100644 (file)
--- a/vss.c
+++ b/vss.c
@@ -137,8 +137,10 @@ struct fec_group {
 struct fec_client {
        /** If negative, this client is temporarily disabled. */
        int error;
-       /** UDP or DCCP. */
-       struct sender *sender;
+       /** Whether the sender client is ready to push out data. */
+       bool ready;
+       /** The connected sender client (transport layer). */
+       struct sender_client *sc;
        /** Parameters requested by the client. */
        struct fec_client_parms *fcp;
        /** Used by the core FEC code. */
@@ -412,21 +414,20 @@ size_t vss_get_fec_eof_packet(const char **buf)
 /**
  * Add one entry to the list of active fec clients.
  *
- * \param fcp Describes the fec parameters to be used for this client.
- * \param result An opaque pointer that must be used by remove the client later.
+ * \param sc  Generic sender_client data of the transport layer.
+ * \param fcp FEC parameters as supplied by the transport layer.
  *
- * \return Standard.
+ * \return Newly allocated fec_client struct.
  */
-int vss_add_fec_client(struct sender *sender, void *private_data,
-               struct fec_client **result)
+struct fec_client *vss_add_fec_client(struct sender_client *sc,
+                                     struct fec_client_parms *fcp)
 {
        struct fec_client *fc = para_calloc(sizeof(*fc));
 
-       fc->private_data = private_data;
-       fc->sender = sender;
+       fc->sc  = sc;
+       fc->fcp = fcp;
        para_list_add(&fc->node, &fec_client_list);
-       *result = fc;
-       return 1;
+       return fc;
 }
 
 /**
@@ -700,7 +701,6 @@ static void vss_pre_select(struct sched *s, struct task *t)
                list_for_each_entry_safe(fc, tmp, &fec_client_list, node) {
                        fc->first_stream_chunk = -1;
                        fc->error = 0;
-                       fc->fcp = NULL;
                }
                mmd->stream_start.tv_sec = 0;
                mmd->stream_start.tv_usec = 0;
@@ -825,17 +825,23 @@ err:
        mmd->new_vss_status_flags = VSS_NEXT;
 }
 
-static int open_fec_client(struct fec_client *fc)
+static int initialize_fec_client(struct fec_client *fc)
 {
        int ret;
-       struct fec_client_parms *fcp;
+       struct fec_client_parms *fcp = fc->fcp;
 
-       ret = fc->sender->open(fc->private_data, &fc->fcp);
-       if (ret < 0) {
-               fc->fcp = NULL;
-               return ret;
+       if (fcp->init_fec) {
+               /*
+                * Set the maximum slice size to the Maximum Packet Size if the
+                * transport protocol allows to determine this value. The user
+                * can specify a slice size up to this value.
+                */
+               ret = fcp->init_fec(fc->sc);
+               if (ret < 0)
+                       return ret;
+               if (!fcp->max_slice_bytes || fcp->max_slice_bytes > ret)
+                       fcp->max_slice_bytes = ret;
        }
-       fcp = fc->fcp;
        if (fcp->max_slice_bytes < FEC_HEADER_SIZE + fcp->data_slices_per_group)
                return -ERRNO_TO_PARA_ERROR(EINVAL);
        ret = fec_new(fcp->data_slices_per_group, fcp->slices_per_group,
@@ -848,6 +854,7 @@ static int open_fec_client(struct fec_client *fc)
        fc->num_extra_slices = 0;
        fc->extra_src_buf = para_calloc(fc->fcp->max_slice_bytes);
        fc->next_header_time.tv_sec = 0;
+       fc->ready = true;
        return 1;
 err:
        fec_free(fc->parms);
@@ -879,8 +886,8 @@ static void vss_send(struct vss_task *vsst)
        list_for_each_entry_safe(fc, tmp_fc, &fec_client_list, node) {
                if (fc->error < 0)
                        continue;
-               if (!fc->fcp) {
-                       ret = open_fec_client(fc);
+               if (!fc->ready) {
+                       ret = initialize_fec_client(fc);
                        if (ret < 0) {
                                PARA_ERROR_LOG("%s\n", para_strerror(-ret));
                                continue;
@@ -894,9 +901,8 @@ static void vss_send(struct vss_task *vsst)
                        continue;
                PARA_DEBUG_LOG("sending %d:%d (%u bytes)\n", fc->group.num,
                        fc->current_slice_num, fc->fcp->max_slice_bytes);
-               fc->sender->send_fec((char *)fc->enc_buf,
-                       fc->fcp->max_slice_bytes,
-                       fc->private_data);
+               fc->fcp->send_fec(fc->sc, (char *)fc->enc_buf,
+                                 fc->fcp->max_slice_bytes);
                fc->current_slice_num++;
                fec_active = 1;
        }
diff --git a/vss.h b/vss.h
index 3d80274..9412da8 100644 (file)
--- a/vss.h
+++ b/vss.h
@@ -24,7 +24,7 @@ const char *supported_audio_formats(void);
 /** Currently playing. */
 #define VSS_PLAYING 8
 
-int vss_add_fec_client(struct sender *sender, void *private_data,
-               struct fec_client **result);
+struct fec_client *vss_add_fec_client(struct sender_client *sc,
+                                     struct fec_client_parms *fcp);
 void vss_del_fec_client(struct fec_client *fc);
 size_t vss_get_fec_eof_packet(const char **buf);