X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=dccp_send.c;h=6f9895410161e47133d65a4f0893bac14a0743b4;hp=6248ae80ef784d5739298b61b9494e76d2e769e5;hb=23dd2200dd4fc74025ae87f5c2127f3b0ff71e9b;hpb=ffb2eaa90429f6d5c3d369509efcdf91c5463dad diff --git a/dccp_send.c b/dccp_send.c index 6248ae80..6f989541 100644 --- a/dccp_send.c +++ b/dccp_send.c @@ -1,8 +1,4 @@ -/* - * Copyright (C) 2006-2010 Andre Noll - * - * Licensed under the GPL v2. For licencing details see COPYING. - */ +/* Copyright (C) 2006 Andre Noll , see file COPYING. */ /** \file dccp_send.c Paraslash's dccp sender. */ @@ -11,32 +7,38 @@ * (C) 2005 Ian McDonald */ +#include +#include #include #include -#include -#include +#include +#include +#include +#include +#include "server.lsg.h" #include "para.h" #include "error.h" #include "string.h" #include "afh.h" -#include "afs.h" #include "server.h" #include "net.h" #include "list.h" -#include "vss.h" #include "send.h" +#include "sched.h" +#include "vss.h" #include "fd.h" #include "close_on_fork.h" #include "chunk_queue.h" -#include "server.cmdline.h" #include "acl.h" -/** Do not write more than that many bytes at once. */ -#define DCCP_MAX_BYTES_PER_WRITE 1024 - static struct sender_status dccp_sender_status, *dss = &dccp_sender_status; +struct dccp_fec_client { + struct fec_client_parms fcp; + struct fec_client *fc; +}; + static void dccp_pre_select(int *max_fileno, fd_set *rfds, __a_unused fd_set *wfds) { @@ -65,10 +67,57 @@ static int dccp_get_tx_ccid(int sockfd) return tx_ccid; } +static void dccp_shutdown_client(struct sender_client *sc) +{ + struct dccp_fec_client *dfc = sc->private_data; + + vss_del_fec_client(dfc->fc); + shutdown_client(sc, dss); +} + +static void dccp_shutdown_clients(void) +{ + struct sender_client *sc, *tmp; + + list_for_each_entry_safe(sc, tmp, &dss->client_list, node) + dccp_shutdown_client(sc); +} + +/** * Obtain current MPS according to RFC 4340, sec. 14. */ +static int dccp_init_fec(struct sender_client *sc) +{ + int mps, ret; + socklen_t ml = sizeof(mps); + uint32_t mss; /* max slize size */ + + /* If call fails, return some sensible minimum value */ + ret = getsockopt(sc->fd, SOL_DCCP, DCCP_SOCKOPT_GET_CUR_MPS, &mps, &ml); + if (ret < 0) { + PARA_NOTICE_LOG("can not determine MPS: %s\n", strerror(errno)); + mps = generic_max_transport_msg_size(sc->fd) - DCCP_MAX_HEADER; + } + PARA_INFO_LOG("current MPS = %d bytes\n", mps); + assert(mps > 0); + mss = OPT_UINT32_VAL(DCCP_MAX_SLICE_SIZE); + if (mss > 0 && mss <= INT_MAX) + mps = PARA_MIN(mps, (int)mss); + return mps; +} + +static void dccp_send_fec(struct sender_client *sc, char *buf, size_t len) +{ + int ret = xwrite(sc->fd, buf, len); + + if (ret < 0) + dccp_shutdown_client(sc); +} + static void dccp_post_select(fd_set *rfds, __a_unused fd_set *wfds) { struct sender_client *sc; + struct dccp_fec_client *dfc; int tx_ccid; + uint32_t k, n; sc = accept_sender_client(dss, rfds); if (!sc) @@ -85,28 +134,29 @@ 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) + if (shutdown(sc->fd, SHUT_RD) < 0) { + PARA_WARNING_LOG("%s\n", strerror(errno)); + shutdown_client(sc, dss); return; - PARA_WARNING_LOG("%s\n", strerror(errno)); - shutdown_client(sc, dss); -} - -static void dccp_send(long unsigned current_chunk, - __a_unused long unsigned chunks_sent, const char *buf, - size_t len, const char *header_buf, size_t header_len) -{ - struct sender_client *sc, *tmp; - - list_for_each_entry_safe(sc, tmp, &dss->client_list, node) - send_chunk(sc, dss, DCCP_MAX_BYTES_PER_WRITE, current_chunk, buf, - len, header_buf, header_len); -} - -static void dccp_shutdown_clients(void) -{ - shutdown_clients(dss); + } + dfc = para_calloc(sizeof(*dfc)); + sc->private_data = dfc; + k = OPT_UINT32_VAL(DCCP_DATA_SLICES_PER_GROUP); + n = OPT_UINT32_VAL(DCCP_SLICES_PER_GROUP); + if (k == 0 || n == 0 || k >= n) { + PARA_WARNING_LOG("invalid FEC parameters, using defaults\n"); + dfc->fcp.data_slices_per_group = 3; + dfc->fcp.slices_per_group = 4; + } else { + dfc->fcp.data_slices_per_group = k; + dfc->fcp.slices_per_group = n; + } + dfc->fcp.init_fec = dccp_init_fec; + dfc->fcp.send_fec = dccp_send_fec; + dfc->fcp.need_periodic_header = false; + dfc->fc = vss_add_fec_client(sc, &dfc->fcp); } static int dccp_com_on(__a_unused struct sender_command_data *scd) @@ -116,6 +166,7 @@ static int dccp_com_on(__a_unused struct sender_command_data *scd) static int dccp_com_off(__a_unused struct sender_command_data *scd) { + dccp_shutdown_clients(); generic_com_off(dss); return 1; } @@ -154,13 +205,13 @@ static const char *dccp_list_available_ccids(void) return list; } -static char *dccp_info(void) +static char *dccp_status(void) { - char *info = get_sender_info(dss, "dccp"); - char *ret = make_message("%s" "\tsupported ccids: %s\n", - info, dccp_list_available_ccids()); - free(info); - return ret; + char *status = generic_sender_status(dss, "dccp"); + char *result = make_message("%ssupported ccids: %s\n", status, + dccp_list_available_ccids()); + free(status); + return result; } /** @@ -175,22 +226,23 @@ void dccp_send_init(struct sender *s) { int ret; - s->info = dccp_info; - s->send = dccp_send; + 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, conf.dccp_access_arg, conf.dccp_access_given, - conf.dccp_port_arg, conf.dccp_max_clients_arg, - conf.dccp_default_deny_given); + 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_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));