From f099900540c4e4c54b10181254b895ccfe6ef410 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Sun, 23 May 2010 07:43:03 +0200 Subject: [PATCH] vss: unify calls to the FEC layer 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 | 2 +- send.h | 15 ++++++++++++++ send_common.c | 2 ++ server.h | 2 ++ udp_send.c | 2 +- vss.c | 54 ++++++++++++++++++++++++++++----------------------- vss.h | 4 ++-- 7 files changed, 53 insertions(+), 28 deletions(-) diff --git a/dccp_send.c b/dccp_send.c index 0e69a969..b13f719e 100644 --- a/dccp_send.c +++ b/dccp_send.c @@ -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 72c7a6c6..f831cbc4 100644 --- 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); }; /** diff --git a/send_common.c b/send_common.c index ed140c84..3b238014 100644 --- a/send_common.c +++ b/send_common.c @@ -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; diff --git a/server.h b/server.h index 822e80e1..43ba841d 100644 --- 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. */ diff --git a/udp_send.c b/udp_send.c index 29deafb0..478c5d9f 100644 --- a/udp_send.c +++ b/udp_send.c @@ -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 afde0dcb..4be6e18a 100644 --- 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 3d80274b..9412da81 100644 --- 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); -- 2.30.2