static int parse_fec_parms(const char *arg, struct sender_command_data *scd)
{
int32_t val;
- char *a = para_strdup(arg), *b = a, *e = strchr(b, ':');
+ char *a = para_strdup(arg),
+ *b = strchr(a, ':'),
+ *c = strrchr(a, ':');
int ret = -E_COMMAND_SYNTAX;
- /* parse max slice bytes */
- if (!e)
+ if (!b || !c)
goto out;
- *e = '\0';
- ret = para_atoi32(b, &val);
- if (ret < 0)
- goto out;
- 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, ':');
- ret = -E_COMMAND_SYNTAX;
- if (!e)
- goto out;
- *e = '\0';
- ret = para_atoi32(b, &val);
+ *b = *c = '\0';
+
+ ret = para_atoi32(a, &val);
if (ret < 0)
goto out;
- ret = -ERRNO_TO_PARA_ERROR(EINVAL);
+
+ /* optional max_slice_bytes (0 means "use MTU") */
+ if (b == c) {
+ scd->max_slice_bytes = 0;
+ } else {
+ if (val < 0 || val > 65535)
+ goto fec_einval;
+ scd->max_slice_bytes = val;
+
+ ret = para_atoi32(b + 1, &val);
+ if (ret < 0)
+ goto out;
+ }
+
+ /* k = data_slices_per_group */
if (val < 0 || val > 255)
- goto out;
+ goto fec_einval;
scd->data_slices_per_group = val;
- /* parse slices_per_group */
- b = e + 1;
- ret = para_atoi32(b, &val);
+
+ /* n = slices_per_group */
+ ret = para_atoi32(c + 1, &val);
if (ret < 0)
goto out;
- ret = -ERRNO_TO_PARA_ERROR(EINVAL);
if (val < 0 || val < scd->data_slices_per_group)
- goto out;
+ goto fec_einval;
scd->slices_per_group = val;
ret = 0;
out:
free(a);
return ret;
+fec_einval:
+ ret = -ERRNO_TO_PARA_ERROR(EINVAL);
+ goto out;
}
/**
*/
int parse_fec_url(const char *arg, struct sender_command_data *scd)
{
- int ret;
- ssize_t len = sizeof(scd->host);
char *a = para_strdup(arg), *p = strchr(a, '/');
+ int ret = 0;
+
+ /* default fec parameters */
+ scd->max_slice_bytes = 0;
+ scd->data_slices_per_group = 14;
+ scd->slices_per_group = 16;
if (p) {
*p = '\0';
- len = strlen(a);
- }
- ret = -ERRNO_TO_PARA_ERROR(EINVAL);
- if (!parse_url(a, scd->host, len, &scd->port))
- goto out;
- if (p) {
ret = parse_fec_parms(p + 1, scd);
- goto out;
+ if (ret < 0)
+ goto out;
}
- /* use default fec parameters. */
- scd->max_slice_bytes = 0;
- scd->slices_per_group = 16;
- scd->data_slices_per_group = 14;
- ret = 0;
+ if (!parse_url(a, scd->host, sizeof(scd->host), &scd->port))
+ ret = -ERRNO_TO_PARA_ERROR(EINVAL);
out:
free(a);
return ret;
{
return make_message(
"usage: {on|off}\n"
- "usage: {add|delete} host[:port][/packet_size:k:n]\n"
+ "usage: {add|delete} ip_address[:port][/[packet_size:]k:n]\n"
+ " - k is the number of data slices per FEC group\n"
+ " - n is the total number of slices in a FEC group\n"
+ " - packet_size reduces the slice size below path MTU\n\n"
"examples: add 224.0.1.38:1500 (IPv4 multicast)\n"
- " add 224.0.1.38:1500/1400:14:16\n"
- " (likewise, using 1400 byte packets, with 14\n"
- " data slices per 16 slice FEC group)\n"
+ " add 224.0.1.38:8080/14:16 (explicit FEC)\n"
" add 10.10.1.42 (using default port)\n"
" add [FF05::42]:1500 (IPv6 multicast)\n"
" add [::1] (IPv6 localhost/default port)\n"