]> git.tuebingen.mpg.de Git - paraslash.git/commitdiff
10_set-client-ccid.diff
authorGerrit Renker <grenker@cscs.ch>
Thu, 25 Feb 2010 16:05:46 +0000 (17:05 +0100)
committerAndre Noll <maan@systemlinux.org>
Thu, 25 Feb 2010 16:05:46 +0000 (17:05 +0100)
This adds a commandline option to either
 * select the CCID in use for the sender-receiver half-connection or
 * advertise the (para_)client's priorities for the CCID;
 * the feature is optional and can be used to fine-tune a connection.

The arguments are both range-checked by gengetopt, and against the CCIDs
available on the host. Currently known CCIDs are 2-4, 248-254. Trying a
CCID which is not supported by the host exits via the following route:

 dccp_recv_ccid_support_check: 'CCID-253' not supported on this host.
 main: parse failed
 main: recv syntax error

The CCID negotiation can be watched in wireshark, between the 'Request'
packet sent by the para_client and the corresponding 'Response' packet of
the para_server. Here are some example negotiations:

     +-------------+---------------+----------------+
     | client-list |  server-list  | resulting CCID |
     +-------------+---------------+----------------+
     |  3, 2       |   2, 3, 4     |       2        |
     |  4, 3, 2, 4 |   3, 2, 4     |       3        |
     |  2, 4       |   2, 3, 4     |       2        |
     |  4, 3, 2, 4 |   2, 3, 4     |       2        |
     |  2          |   2, 3, 4     |       2        |
     |  3          |   2, 3, 4     |       3        |
     |  4          |   2, 3, 4     |       4        |
     +-------------+---------------+----------------+

The server list of (2, 3, 4) is the unaltered default, it can be changed on
the server using the same mechanism.

As shown, the easiest way is to use just a single '--ccid <n>' argument;
when passing multiple values, the outcome is determined by the algorithm
described in RFC 4340, 6.3.1:
 * 'server-priority' means that the server overrids the result;
 * the server traverses its list of preferences in order of priority and
 * uses the first entry which also appears in the client-list;
 * resets connection with negotiation failure when there is no common value.

Applying this algorithm on the above lists can be used to verify the
table. This also illustrates that repetition of CCID values has no effect
on the outcome: if the repeated value is first in the server list, it will
be chosen; otherwise all instances of that value are ignored.

dccp_recv.c
ggo/dccp_recv.ggo

index 0a7b3c069271329152f131afa1f1334416473d10..a0f8371efae6b0974a4f9c88ef1365b208a48eda 100644 (file)
@@ -57,11 +57,25 @@ static int dccp_recv_open(struct receiver_node *rn)
 {
        struct private_dccp_recv_data *pdd;
        struct dccp_recv_args_info *conf = rn->conf;
-       int fd, ret = para_connect_simple(IPPROTO_DCCP, conf->host_arg,
-                                                       conf->port_arg);
-       if (ret < 0)
-               return ret;
-       fd = ret;
+       struct flowopts *fo = NULL;
+       uint8_t *ccids = NULL;
+       int fd, ret, i;
+
+       /* Copy CCID preference list (u8 array required) */
+       if (conf->ccid_given) {
+               ccids = para_malloc(conf->ccid_given);
+               fo    = flowopt_new();
+
+               for (i = 0; i < conf->ccid_given; i++)
+                       ccids[i] = conf->ccid_arg[i];
+
+               OPT_ADD(fo, SOL_DCCP, DCCP_SOCKOPT_CCID, ccids, i);
+       }
+
+       fd = makesock(IPPROTO_DCCP, 0, conf->host_arg, conf->port_arg, fo);
+       free(ccids);
+       if (fd < 0)
+               return fd;
        /*
         * Disable unused CCIDs: the receiver does not send any application
         * data to the server. By shutting down this unused path we reduce
@@ -84,11 +98,37 @@ err:
        return ret;
 }
 
+/**
+ * Check whether the host supports the requested 'ccid' arguments.
+ * \param conf DCCP receiver arguments.
+ * \return True if all CCIDs requested in \a conf are supported.
+ */
+static bool dccp_recv_ccid_support_check(struct dccp_recv_args_info *conf)
+{
+       uint8_t ccids[DCCP_MAX_HOST_CCIDS];
+       uint8_t nccids = sizeof(ccids), i, j;
+
+       if (dccp_available_ccids(ccids, &nccids) == NULL)
+               return false;
+
+       for (i = 0; i < conf->ccid_given; i++) {
+               for (j = 0; j < nccids && ccids[j] != conf->ccid_arg[i]; j++)
+                       ;
+               if (j == nccids) {
+                       PARA_ERROR_LOG("'CCID-%d' not supported on this host.\n",
+                                       conf->ccid_arg[i]);
+                       return false;
+               }
+       }
+       return true;
+}
+
 static void *dccp_recv_parse_config(int argc, char **argv)
 {
-       struct dccp_recv_args_info *tmp = para_calloc(sizeof(struct dccp_recv_args_info));
+       struct dccp_recv_args_info *tmp = para_calloc(sizeof(*tmp));
 
-       if (!dccp_recv_cmdline_parser(argc, argv, tmp))
+       if (!dccp_recv_cmdline_parser(argc, argv, tmp) &&
+           dccp_recv_ccid_support_check(tmp))
                return tmp;
        free(tmp);
        return NULL;
index 9717329d29b036baf460fb747901ea41b913e632..2c7f364ca7f296f7bbbcf175aa9fd79d39b3651b 100644 (file)
@@ -11,3 +11,31 @@ option "port" p
 int
 default="8000"
 optional
+
+option "ccid" c
+"CCID preference(s) for this connection"
+int
+# restrict the maximum number of times this option can be passed
+optional multiple(-10)
+# currently known CCIDs:
+# - CCID-2 (RFC 4341),
+# - CCID-3 (RFC 4342),
+# - CCID-4 (RFC 5622),
+# - CCID-248 ... CCID-254 are experimental (RFC 4340, 19.5)
+values="2", "3", "4", "248", "249", "250", "251", "252", "253", "254"
+details="
+       Depends on the CCIDs available on the server; this information
+       can be seen in the display of 'para_client si'.
+
+       When present exactly once, this option mandates the CCID
+       to use for the sender-receiver connection.
+
+       If it is passed more than once, it sets a preference list
+       of CCIDs for this connection. The order of appearance here
+       signifies descending priority. For example,
+                   --ccid 4   --c 2   --ccid 3
+       generates the preference list (CCID-4, CCID-2, CCID-3).
+
+       The request is reconciled with the CCIDs on the server via
+       the 'server-priority' mechanism of RFC 4340 6.3.1/10.
+"