#include "net.h"
#include "server.cmdline.h"
#include "list.h"
-#include "vss.h"
#include "send.h"
+#include "vss.h"
#include "ipc.h"
#include "fd.h"
#include "sched.h"
struct fec_client {
/** If negative, this client is temporarily disabled. */
int error;
+ /** UDP or DCCP. */
+ struct sender *sender;
/** Parameters requested by the client. */
struct fec_client_parms *fcp;
/** Used by the core FEC code. */
int num_extra_slices;
/** Contains the FEC-encoded data. */
unsigned char *enc_buf;
+ /** Pointer obtained from sender when the client is added. */
+ void *private_data;
};
/**
*
* \return Standard.
*/
-int vss_add_fec_client(struct fec_client_parms *fcp, struct fec_client **result)
+int vss_add_fec_client(struct sender *sender, void *private_data,
+ struct fec_client **result)
{
- int ret;
- struct fec_client *fc;
+ struct fec_client *fc = para_calloc(sizeof(*fc));
- if (fcp->max_slice_bytes < FEC_HEADER_SIZE + fcp->data_slices_per_group)
- return -ERRNO_TO_PARA_ERROR(EINVAL);
- fc = para_calloc(sizeof(*fc));
- fc->fcp = fcp;
- ret = fec_new(fcp->data_slices_per_group, fcp->slices_per_group,
- &fc->parms);
- if (ret < 0)
- goto err;
- fc->first_stream_chunk = -1; /* stream not yet started */
- fc->src_data = para_malloc(fc->fcp->slices_per_group * sizeof(char *));
- fc->enc_buf = para_calloc(fc->fcp->max_slice_bytes);
- fc->num_extra_slices = 0;
- fc->extra_src_buf = para_calloc(fc->fcp->max_slice_bytes);
- fc->next_header_time.tv_sec = 0;
+ fc->private_data = private_data;
+ fc->sender = sender;
para_list_add(&fc->node, &fec_client_list);
*result = fc;
return 1;
-err:
- fec_free(fc->parms);
- free(fc);
- *result = NULL;
- return ret;
}
/**
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;
mmd->new_vss_status_flags = VSS_NEXT;
}
+static int open_fec_client(struct fec_client *fc)
+{
+ int ret;
+ struct fec_client_parms *fcp;
+
+ ret = fc->sender->open(fc->private_data, &fc->fcp);
+ if (ret < 0) {
+ fc->fcp = NULL;
+ return 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,
+ &fc->parms);
+ if (ret < 0)
+ goto err;
+ fc->first_stream_chunk = -1; /* stream not yet started */
+ fc->src_data = para_malloc(fc->fcp->slices_per_group * sizeof(char *));
+ fc->enc_buf = para_calloc(fc->fcp->max_slice_bytes);
+ fc->num_extra_slices = 0;
+ fc->extra_src_buf = para_calloc(fc->fcp->max_slice_bytes);
+ fc->next_header_time.tv_sec = 0;
+ return 1;
+err:
+ fec_free(fc->parms);
+ return ret;
+}
+
/**
* Main sending function.
*
*/
static void vss_send(struct vss_task *vsst)
{
- int i, fec_active = 0;
+ int ret, i, fec_active = 0;
struct timeval due;
struct fec_client *fc, *tmp_fc;
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 (ret < 0) {
+ PARA_ERROR_LOG("%s\n", para_strerror(-ret));
+ continue;
+ }
+ }
if (!next_slice_is_due(fc, NULL)) {
fec_active = 1;
continue;
continue;
PARA_DEBUG_LOG("sending %d:%d (%u bytes)\n", fc->group.num,
fc->current_slice_num, fc->fcp->max_slice_bytes);
- fc->fcp->send((char *)fc->enc_buf,
+ fc->sender->send_fec((char *)fc->enc_buf,
fc->fcp->max_slice_bytes,
- fc->fcp->private_data);
+ fc->private_data);
fc->current_slice_num++;
fec_active = 1;
}