X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=send_common.c;h=b44c8133d821ef2611650eee0ea40039af18bbc3;hp=d1dcaeb199e4b8f55b5871bfc89664acdc4d56d3;hb=f16b28109fe2f4a7caf83350fff8bfcfe73b7b6c;hpb=a94c0ad6767bf620e085a6c3c9bc3a5d16278801 diff --git a/send_common.c b/send_common.c index d1dcaeb1..b44c8133 100644 --- a/send_common.c +++ b/send_common.c @@ -1,12 +1,15 @@ /* - * Copyright (C) 2005-2009 Andre Noll + * Copyright (C) 2005-2010 Andre Noll * * Licensed under the GPL v2. For licencing details see COPYING. */ /** \file send_common.c Functions used by more than one paraslash sender. */ +#include #include +#include + #include "para.h" #include "error.h" #include "string.h" @@ -39,7 +42,7 @@ */ static int open_sender(unsigned l4type, int port) { - int fd, ret = para_listen(AF_UNSPEC, l4type, port); + int fd, ret = para_listen_simple(l4type, port); if (ret < 0) return ret; @@ -159,8 +162,8 @@ void send_chunk(struct sender_client *sc, struct sender_status *ss, if (ret < 0) goto out; } - sc->header_sent = 1; } + sc->header_sent = 1; ret = send_queued_chunks(sc->fd, sc->cq, max_bytes_per_write); if (ret < 0) { shutdown_client(sc, ss); @@ -214,7 +217,7 @@ void init_sender_status(struct sender_status *ss, char **access_arg, * * \return The string printed in the "si" command. */ -char *get_sender_info(struct sender_status *ss, char *name) +char *get_sender_info(struct sender_status *ss, const char *name) { char *clnts = NULL, *ret; struct sender_client *sc, *tmp_sc; @@ -228,14 +231,14 @@ char *get_sender_info(struct sender_status *ss, char *name) ret = make_message( "%s sender:\n" "\tstatus: %s\n" - "\tport: %d\n" + "\tport: %s\n" "\tnumber of connected clients: %d\n" "\tmaximal number of clients: %d%s\n" "\tconnected clients: %s\n" "\taccess %s list: %s\n", name, (ss->listen_fd >= 0)? "on" : "off", - ss->port, + stringify_port(ss->port, strcmp(name, "http") ? "dccp" : "tcp"), ss->num_clients, ss->max_clients, ss->max_clients > 0? "" : " (unlimited)", @@ -259,7 +262,7 @@ char *get_sender_info(struct sender_status *ss, char *name) void generic_com_allow(struct sender_command_data *scd, struct sender_status *ss) { - acl_allow(scd->addr, scd->netmask, &ss->acl, ss->default_deny); + acl_allow(scd->host, scd->netmask, &ss->acl, ss->default_deny); } /** @@ -273,7 +276,7 @@ void generic_com_allow(struct sender_command_data *scd, void generic_com_deny(struct sender_command_data *scd, struct sender_status *ss) { - acl_deny(scd->addr, scd->netmask, &ss->acl, ss->default_deny); + acl_deny(scd->host, scd->netmask, &ss->acl, ss->default_deny); } /** @@ -345,15 +348,18 @@ void generic_com_off(struct sender_status *ss) * \sa \ref para_accept(), \ref mark_fd_nonblocking(), \ref acl_check_access(), * \ref cq_new(), \ref add_close_on_fork_list(). */ -struct sender_client *accept_sender_client(struct sender_status *ss) +struct sender_client *accept_sender_client(struct sender_status *ss, fd_set *rfds) { struct sender_client *sc; - int fd, ret = para_accept(ss->listen_fd, NULL, 0); - if (ret < 0) { + int fd, ret; + + if (ss->listen_fd < 0) + return NULL; + ret = para_accept(ss->listen_fd, rfds, NULL, 0, &fd); + if (ret < 0) PARA_ERROR_LOG("%s\n", para_strerror(-ret)); + if (ret <= 0) return NULL; - } - fd = ret; ret = -E_MAX_CLIENTS; if (ss->max_clients > 0 && ss->num_clients >= ss->max_clients) goto err_out; @@ -389,7 +395,96 @@ char *generic_sender_help(void) { return make_message( "usage: {on|off}\n" - "usage: {allow|deny} IP mask\n" - "example: allow 127.0.0.1 32\n" + "usage: {allow|deny} IP[/netmask]\n" + " where mask defaults to 32\n" + "example: allow 192.168.0.1/24\n" ); } + +static int parse_fec_parms(const char *arg, struct sender_command_data *scd) +{ + int32_t val; + char *a = para_strdup(arg), *b = a, *e = strchr(b, ':'); + int ret = -E_COMMAND_SYNTAX; + + /* parse max slice bytes */ + if (!e) + goto out; + *e = '\0'; + ret = para_atoi32(b, &val); + if (ret < 0) + goto out; + ret = -ERRNO_TO_PARA_ERROR(EINVAL); + if (val < 0 || val > 65535) + goto out; + scd->max_slice_bytes = val; + /* parse data_slices_per_group */ + b = e + 1; + e = strchr(b, ':'); + ret = -E_COMMAND_SYNTAX; + if (!e) + goto out; + *e = '\0'; + ret = para_atoi32(b, &val); + if (ret < 0) + goto out; + ret = -ERRNO_TO_PARA_ERROR(EINVAL); + if (val < 0 || val > 255) + goto out; + scd->data_slices_per_group = val; + /* parse slices_per_group */ + b = e + 1; + ret = para_atoi32(b, &val); + if (ret < 0) + goto out; + ret = -ERRNO_TO_PARA_ERROR(EINVAL); + if (val < 0 || val < scd->data_slices_per_group) + goto out; + scd->slices_per_group = val; + ret = 0; +out: + free(a); + return ret; +} + +/** + * Parse a FEC URL string. + * + * \param arg the URL string to parse. + * \param scd The structure containing host, port and the FEC parameters. + * + * \return Standard. + * + * A FEC URL consists of an ordinary URL string according to RFC 3986, + * optionally followed by a slash and the three FEC parameters slice_size, + * data_slices_per_group and slices_per_group. The three FEC parameters are + * separated by colons. + * + * \sa \ref parse_url(). + */ +int parse_fec_url(const char *arg, struct sender_command_data *scd) +{ + int ret; + ssize_t len = sizeof(scd->host); + char *a = para_strdup(arg), *p = strchr(a, '/'); + + if (p) { + *p = '\0'; + len = strlen(a); + } + ret = -ERRNO_TO_PARA_ERROR(EINVAL); + if (!parse_url(a, scd->host, len, &scd->port)) + goto out; + if (p) { + ret = parse_fec_parms(p + 1, scd); + goto out; + } + /* use default fec parameters. */ + scd->max_slice_bytes = 1472; + scd->slices_per_group = 16; + scd->data_slices_per_group = 14; + ret = 0; +out: + free(a); + return ret; +}