chiark / gitweb /
lib/configuration.c, lib/uaudio-rtp.c: Allow tweaking MTU-discovery.
[disorder] / lib / configuration.c
index 602596421b149b4b360f0328ea98af4b6e0a905c..bb75173ed39c6f3a193f9e2680942ae95f94e89d 100644 (file)
@@ -723,15 +723,14 @@ static int validate_tracklength(const struct config_state *cs,
   return 0;
 }
 
-/** @brief Validate a non-negative (@c long) integer
+/** @brief Common code for validating integer values
  * @param cs Configuration state
  * @param nvec Length of (proposed) new value
  * @param vec Elements of new value
- * @return 0 on success, non-0 on error
+ * @param n_out Where to put the value
  */
-static int validate_non_negative(const struct config_state *cs,
-                                int nvec, char **vec) {
-  long n;
+static int common_validate_integer(const struct config_state *cs,
+                                  int nvec, char **vec, long *n_out) {
   char errbuf[1024];
 
   if(nvec < 1) {
@@ -742,11 +741,24 @@ static int validate_non_negative(const struct config_state *cs,
     disorder_error(0, "%s:%d: too many arguments", cs->path, cs->line);
     return -1;
   }
-  if(xstrtol(&n, vec[0], 0, 0)) {
+  if(xstrtol(n_out, vec[0], 0, 0)) {
     disorder_error(0, "%s:%d: %s", cs->path, cs->line,
                    format_error(ec_errno, errno, errbuf, sizeof errbuf));
     return -1;
   }
+  return 0;
+}
+
+/** @brief Validate a non-negative (@c long) integer
+ * @param cs Configuration state
+ * @param nvec Length of (proposed) new value
+ * @param vec Elements of new value
+ * @return 0 on success, non-0 on error
+ */
+static int validate_non_negative(const struct config_state *cs,
+                                int nvec, char **vec) {
+  long n;
+  if(common_validate_integer(cs, nvec, vec, &n)) return -1;
   if(n < 0) {
     disorder_error(0, "%s:%d: must not be negative", cs->path, cs->line);
     return -1;
@@ -763,21 +775,7 @@ static int validate_non_negative(const struct config_state *cs,
 static int validate_positive(const struct config_state *cs,
                          int nvec, char **vec) {
   long n;
-  char errbuf[1024];
-
-  if(nvec < 1) {
-    disorder_error(0, "%s:%d: missing argument", cs->path, cs->line);
-    return -1;
-  }
-  if(nvec > 1) {
-    disorder_error(0, "%s:%d: too many arguments", cs->path, cs->line);
-    return -1;
-  }
-  if(xstrtol(&n, vec[0], 0, 0)) {
-    disorder_error(0, "%s:%d: %s", cs->path, cs->line,
-                   format_error(ec_errno, errno, errbuf, sizeof errbuf));
-    return -1;
-  }
+  if(common_validate_integer(cs, nvec, vec, &n)) return -1;
   if(n <= 0) {
     disorder_error(0, "%s:%d: must be positive", cs->path, cs->line);
     return -1;
@@ -986,6 +984,24 @@ static int validate_pausemode(const struct config_state attribute((unused)) *cs,
   return -1;
 }
 
+/** @brief Validate an MTU-discovery setting
+ * @param cs Configuration state
+ * @param nvec Length of (proposed) new value
+ * @param vec Elements of new value
+ * @return 0 on success, non-0 on error
+ */
+static int validate_mtu_discovery(const struct config_state attribute((unused)) *cs,
+                                 int nvec,
+                                 char **vec) {
+  if (nvec == 1 &&
+      (!strcmp(vec[0], "default") ||
+       !strcmp(vec[0], "yes") ||
+       !strcmp(vec[0], "no")))
+    return 0;
+  disorder_error(0, "%s:%d: invalid MTU-discovery setting", cs->path, cs->line);
+  return -1;
+}
+
 /** @brief Validate a destination network address
  * @param cs Configuration state
  * @param nvec Length of (proposed) new value
@@ -1012,6 +1028,32 @@ static int validate_destaddr(const struct config_state attribute((unused)) *cs,
   return 0;
 }
 
+/** @brief Validate an internet address
+ * @param cs Configuration state
+ * @param nvec Length of (proposed) new value
+ * @param vec Elements of new value
+ * @return 0 on success, non-0 on error
+ *
+ * By a destination address, it is meant that it must be either IPv4 or IPv6.
+ */
+static int validate_inetaddr(const struct config_state *cs,
+                            int nvec, char **vec) {
+  struct netaddress na[1];
+
+  if(netaddress_parse(na, nvec, vec)) {
+    disorder_error(0, "%s:%d: invalid network address", cs->path, cs->line);
+    return -1;
+  }
+  switch(na->af) {
+    case AF_INET: case AF_INET6: case AF_UNSPEC: break;
+    default:
+      disorder_error(0, "%s:%d: must be an intenet address",
+                    cs->path, cs->line);
+      return -1;
+  }
+  return 0;
+}
+
 /** @brief Item name and and offset */
 #define C(x) #x, offsetof(struct config, x)
 /** @brief Item name and and offset */
@@ -1067,8 +1109,15 @@ static const struct conf conf[] = {
   { C(reminder_interval), &type_integer,         validate_positive },
   { C(remote_userman),   &type_boolean,          validate_any },
   { C(replay_min),       &type_integer,          validate_non_negative },
+  { C(rtp_always_request), &type_boolean,       validate_any },
   { C(rtp_delay_threshold), &type_integer,       validate_positive },
+  { C(rtp_max_payload),         &type_integer,          validate_positive },
+  { C(rtp_maxbuffer),   &type_integer,          validate_non_negative },
+  { C(rtp_minbuffer),   &type_integer,          validate_non_negative },
   { C(rtp_mode),         &type_string,           validate_any },
+  { C(rtp_mtu_discovery), &type_string,                 validate_mtu_discovery },
+  { C(rtp_rcvbuf),      &type_integer,          validate_non_negative },
+  { C(rtp_request_address), &type_netaddress,   validate_inetaddr },
   { C(rtp_verbose),      &type_boolean,          validate_any },
   { C(sample_format),    &type_sample_format,    validate_sample_format },
   { C(scratch),          &type_string_accum,     validate_isreg },
@@ -1380,6 +1429,8 @@ static struct config *config_default(void) {
   c->listen.af = -1;
   c->connect.af = -1;
   c->rtp_mode = xstrdup("auto");
+  c->rtp_max_payload = -1;
+  c->rtp_mtu_discovery = xstrdup("default");
   return c;
 }
 
@@ -1487,8 +1538,10 @@ static void config_postdefaults(struct config *c,
   if(server) {
     if(!strcmp(c->api, "command") && !c->speaker_command)
       disorder_fatal(0, "'api command' but speaker_command is not set");
-    if((!strcmp(c->api, "rtp")) && c->broadcast.af == -1)
-      disorder_fatal(0, "'api rtp' but broadcast is not set");
+    if((!strcmp(c->api, "rtp")) &&
+       c->broadcast.af == -1 && strcmp(c->rtp_mode, "request"))
+      disorder_fatal(0, "'api rtp' but broadcast is not set "
+                    "and mode is not not 'request'");
   }
   /* Override sample format */
   if(!strcmp(c->api, "rtp")) {