udp: refuse to add the same target twice
[paraslash.git] / udp_send.c
index 8baf15e383586ad9a65e726cb62de4af8789f09a..71e85b79f6133ffb2dcc334949e0241885fa29ec 100644 (file)
@@ -213,14 +213,13 @@ static int udp_com_off(__a_unused struct sender_command_data *scd)
        return 1;
 }
 
-static int udp_com_delete(struct sender_command_data *scd)
+static struct sender_client *udp_lookup_target(struct sender_command_data *scd)
 {
        struct sender_client *sc, *tmp;
        char host[MAX_HOSTLEN];
        int32_t port;
 
        list_for_each_entry_safe(sc, tmp, &targets, node) {
-               struct udp_target *ut = sc->private_data;
                parse_url(sc->name, host, sizeof(host), &port);
 
                /* Unspecified port means wildcard port match */
@@ -228,9 +227,22 @@ static int udp_com_delete(struct sender_command_data *scd)
                        continue;
                if (strcmp(host, scd->host))
                        continue;
+               return sc;
+       }
+       return NULL;
+}
+
+static int udp_com_delete(struct sender_command_data *scd)
+{
+       struct udp_target *ut = sc->private_data;
+       struct sender_client *sc = udp_lookup_target(scd);
+
+       if (sc) {
                udp_delete_target(ut, "com_delete");
+               return 1;
        }
-       return 1;
+       PARA_NOTICE_LOG("not deleting non-existing target '%s'\n", scd->host);
+       return -E_TARGET_NOT_FOUND;
 }
 
 /** Initialize UDP session and set maximum payload size. */
@@ -316,18 +328,25 @@ fail:
        return ret;
 }
 
-static void udp_add_target(struct sender_command_data *scd)
+static int udp_com_add(struct sender_command_data *scd)
 {
        int ret;
-       struct udp_target *ut = para_calloc(sizeof(*ut));
+       struct udp_target *ut;
+       struct sender_client *sc = udp_lookup_target(scd);
 
+       if (sc) {
+               PARA_NOTICE_LOG("target %s already exists - not adding it\n",
+                               sc->name);
+               return -E_TARGET_EXISTS;
+       }
+       ut = para_calloc(sizeof(*ut));
+       sc = ut->sc = para_calloc(sizeof(*sc));
        ut->fcp.slices_per_group      = scd->slices_per_group;
        ut->fcp.data_slices_per_group = scd->data_slices_per_group;
        ut->fcp.max_slice_bytes       = scd->max_slice_bytes;
        ut->fcp.init_fec              = udp_init_fec;
        ut->fcp.send_fec              = udp_send_fec;
 
-       ut->sc = para_calloc(sizeof(*ut->sc));
        ut->sc->private_data = ut;
        ut->sc->fd = -1;
        ret = para_connect_simple(IPPROTO_UDP, scd->host, scd->port);
@@ -345,7 +364,7 @@ static void udp_add_target(struct sender_command_data *scd)
        PARA_INFO_LOG("adding to target list (%s)\n", ut->sc->name);
        ut->fc = vss_add_fec_client(ut->sc, &ut->fcp);
        para_list_add(&ut->sc->node, &targets);
-       return;
+       return 1;
 err:
        if (ut->sc->fd >= 0)
                close(ut->sc->fd);
@@ -353,12 +372,7 @@ err:
                        scd->host, scd->port, para_strerror(-ret));
        free(ut->sc);
        free(ut);
-}
-
-static int udp_com_add(struct sender_command_data *scd)
-{
-       udp_add_target(scd);
-       return 1;
+       return ret;
 }
 
 static char *udp_info(void)
@@ -401,7 +415,7 @@ static void udp_init_target_list(void)
                        PARA_CRIT_LOG("not adding requested target '%s'\n",
                                        conf.udp_target_arg[i]);
                else
-                       udp_add_target(&scd);
+                       udp_com_add(&scd);
        }
 }