paraslash 0.7.3
[paraslash.git] / dccp_send.c
index 61d42126f95ffc98cf10b33c3c286f7082d44692..6182c964fde04719ee4736dc43482caf434ee395 100644 (file)
@@ -1,8 +1,4 @@
-/*
- * Copyright (C) 2006 Andre Noll <maan@tuebingen.mpg.de>
- *
- * Licensed under the GPL v2. For licencing details see COPYING.
- */
+/* Copyright (C) 2006 Andre Noll <maan@tuebingen.mpg.de>, see file COPYING. */
 
 /** \file dccp_send.c Paraslash's dccp sender. */
 
 #include "error.h"
 #include "string.h"
 #include "afh.h"
-#include "server.h"
 #include "net.h"
+#include "server.h"
 #include "list.h"
-#include "send.h"
 #include "sched.h"
+#include "send.h"
 #include "vss.h"
 #include "fd.h"
-#include "close_on_fork.h"
-#include "chunk_queue.h"
-#include "acl.h"
 
 static struct sender_status dccp_sender_status, *dss = &dccp_sender_status;
 
@@ -43,13 +36,19 @@ struct dccp_fec_client {
        struct fec_client *fc;
 };
 
-static void dccp_pre_select(int *max_fileno, fd_set *rfds,
-               __a_unused fd_set *wfds)
+static void dccp_pre_monitor(struct sched *s)
 {
-       if (dss->listen_fd >= 0)
-               para_fd_set(dss->listen_fd, rfds, max_fileno);
+       unsigned n;
+
+       FOR_EACH_LISTEN_FD(n, dss)
+               if (dss->listen_fds[n] >= 0)
+                       sched_monitor_readfd(dss->listen_fds[n], s);
 }
 
+#ifndef DCCP_SOCKOPT_TX_CCID
+#define DCCP_SOCKOPT_TX_CCID 14 /**< Set/get the TX CCID. */
+#endif
+
 /**
  * Query the TX CCID used on the sender-client half connection.
  * \param sockfd Server socket descriptor to query (after accept(2)).
@@ -87,6 +86,20 @@ static void dccp_shutdown_clients(void)
                dccp_shutdown_client(sc);
 }
 
+static void dccp_shutdown(void)
+{
+       dccp_shutdown_clients();
+       generic_acl_deplete(&dss->acl);
+       free_sender_status(dss);
+}
+
+#ifndef DCCP_SOCKOPT_GET_CUR_MPS
+#define DCCP_SOCKOPT_GET_CUR_MPS 5 /**< Max packet size, RFC 4340, 14. */
+#endif
+
+/** Estimated worst-case length of a DCCP header including options. */
+#define DCCP_MAX_HEADER 128
+
 /** * Obtain current MPS according to RFC 4340, sec. 14. */
 static int dccp_init_fec(struct sender_client *sc)
 {
@@ -116,14 +129,14 @@ static void dccp_send_fec(struct sender_client *sc, char *buf, size_t len)
                dccp_shutdown_client(sc);
 }
 
-static void dccp_post_select(fd_set *rfds, __a_unused fd_set *wfds)
+static void dccp_post_monitor(__a_unused struct sched *s)
 {
        struct sender_client *sc;
        struct dccp_fec_client *dfc;
        int tx_ccid;
        uint32_t k, n;
 
-       sc = accept_sender_client(dss, rfds);
+       sc = accept_sender_client(dss);
        if (!sc)
                return;
 
@@ -138,14 +151,14 @@ static void dccp_post_select(fd_set *rfds, __a_unused fd_set *wfds)
        /*
         * Bypass unused CCID paths: the sender does not receive application data
         * from the client; by shutting down this unused communication path we can
-        * reduce processing costs a bit. See analogous comment in dccp_recv.c.
+        * reduce processing costs a bit. See analogous comment in \ref dccp_recv.c.
         */
        if (shutdown(sc->fd, SHUT_RD) < 0) {
                PARA_WARNING_LOG("%s\n", strerror(errno));
                shutdown_client(sc, dss);
                return;
        }
-       dfc = para_calloc(sizeof(*dfc));
+       dfc = zalloc(sizeof(*dfc));
        sc->private_data = dfc;
        k = OPT_UINT32_VAL(DCCP_DATA_SLICES_PER_GROUP);
        n = OPT_UINT32_VAL(DCCP_SLICES_PER_GROUP);
@@ -165,7 +178,8 @@ static void dccp_post_select(fd_set *rfds, __a_unused fd_set *wfds)
 
 static int dccp_com_on(__a_unused struct sender_command_data *scd)
 {
-       return generic_com_on(dss, IPPROTO_DCCP);
+       generic_com_on(dss, IPPROTO_DCCP);
+       return 1;
 }
 
 static int dccp_com_off(__a_unused struct sender_command_data *scd)
@@ -218,36 +232,42 @@ static char *dccp_status(void)
        return result;
 }
 
-/**
- * The init function of the dccp sender.
- *
- * \param s pointer to the dccp sender struct.
- *
- * It initializes all function pointers of \a s and starts
- * listening on the given port.
+/*
+ * Initialize the client list and the access control list and listen on the
+ * dccp port.
  */
-void dccp_send_init(struct sender *s)
+static void dccp_send_init(void)
 {
-       int ret;
-
-       s->status = dccp_status;
-       s->send = NULL;
-       s->pre_select = dccp_pre_select;
-       s->post_select = dccp_post_select;
-       s->shutdown_clients = dccp_shutdown_clients;
-       s->resolve_target = NULL;
-       s->help = generic_sender_help;
-       s->client_cmds[SENDER_on] = dccp_com_on;
-       s->client_cmds[SENDER_off] = dccp_com_off;
-       s->client_cmds[SENDER_deny] = dccp_com_deny;
-       s->client_cmds[SENDER_allow] = dccp_com_allow;
-       s->client_cmds[SENDER_add] = NULL;
-       s->client_cmds[SENDER_delete] = NULL;
-
        init_sender_status(dss, OPT_RESULT(DCCP_ACCESS),
+               OPT_RESULT(DCCP_LISTEN_ADDRESS),
                OPT_UINT32_VAL(DCCP_PORT), OPT_UINT32_VAL(DCCP_MAX_CLIENTS),
                OPT_GIVEN(DCCP_DEFAULT_DENY));
-       ret = generic_com_on(dss, IPPROTO_DCCP);
-       if (ret < 0)
-               PARA_ERROR_LOG("%s\n", para_strerror(-ret));
+       if (OPT_GIVEN(DCCP_NO_AUTOSTART))
+               return;
+       generic_com_on(dss, IPPROTO_DCCP);
 }
+
+/**
+ * The DCCP sender.
+ *
+ * This sender offers congestion control not available in plain TCP. Most
+ * methods of the sender structure are implemented as simple wrappers for the
+ * generic functions defined in \ref send_common.c. Like UDP streams, DCCP
+ * streams are sent FEC-encoded.
+ */
+const struct sender dccp_sender = {
+       .name = "dccp",
+       .init = dccp_send_init,
+       .shutdown = dccp_shutdown,
+       .pre_monitor = dccp_pre_monitor,
+       .post_monitor = dccp_post_monitor,
+       .shutdown_clients = dccp_shutdown_clients,
+       .client_cmds = {
+               [SENDER_on] = dccp_com_on,
+               [SENDER_off] = dccp_com_off,
+               [SENDER_deny] = dccp_com_deny,
+               [SENDER_allow] = dccp_com_allow,
+       },
+       .help = generic_sender_help,
+       .status = dccp_status,
+};