/* SPDX-License-Identifier: GPL-2.0 */ /** \file send.h Sender-related defines and structures. * * All senders are always compiled in and are linked into para_server(1). * The core structure of the sender API is struct \ref sender. * * The udp sender employs the FEC (forward error correction) API defined * in \ref fec.c to register FEC clients to the virtual streaming system, * which maintains the FEC client list. * * The file also contains a little preprocessor fu to create the * sender_subcommand enumeration and the list of sender name strings without * duplicating the commands. */ /** * The list of sender subcommands. We shall define \ref SENDER_SUBCOMMAND * (without the plural s) twice, expanding \ref SENDER_SUBCOMMANDS (with * plural s) after either definition. The two expansions result in outputs that * are suitable to be part of an enumeration or a string array, respectively. * * The add and delete subcommands are only implemented by the udp sender * to add/delete one or more targets. The allow and deny subcommands * allow/deny connections from given IP address(es) and the on/off subcommands * activate/deactivate a sender. * * \showinitializer */ #define SENDER_SUBCOMMANDS \ SENDER_SUBCOMMAND(add) \ SENDER_SUBCOMMAND(delete) \ SENDER_SUBCOMMAND(allow) \ SENDER_SUBCOMMAND(deny) \ SENDER_SUBCOMMAND(on) \ SENDER_SUBCOMMAND(off) \ /** * Concatenate "SENDER_" and the given argument, then append a comma. * The expansion is suitable to declare an enumeration. */ #define SENDER_SUBCOMMAND(_name) SENDER_ ## _name, /** * Each sender subcommand gets a SENDER_xxx identifier. The identifier is * passed from the sender command handler to the server process to tell * the server process which sender to address. */ enum sender_subcommand { SENDER_SUBCOMMANDS /**< List of SENDER_xxx identifiers. */ NUM_SENDER_CMDS /**< Used as array size in struct \ref sender. */ }; #undef SENDER_SUBCOMMAND /** * Expand the argument to its stringified version so that \ref * SENDER_SUBCOMMANDS above now expands to the comma-separated list of sender * subcommand C-strings. The output is suitable to define and initialize an * array of char pointers. */ #define SENDER_SUBCOMMAND(_name) #_name, /** * Describes one sender of para_server(1). * * Each sender implements a bunch of methods which are called in server or * in command handler context, or both. * * \sa \ref http_send.c, \ref udp_send.c. */ struct sender { /** The name of the sender. */ const char *name; /** * Parse the command line options and initialize this sender (e.g., * initialize target or access control lists, listen on a network * socket, etc.). */ void (*init)(void); /** * Return the dynamically allocated help text. * * It will be freed by the caller. */ char * (*help)(void); /** * Return current status information. * * Like the help command, the result must be dynamically allocated * and is freed by the caller. */ char * (*status)(void); /** * The send-hook. * * It gets called whenever para_server(1) is playing and the virtual * streaming system detects that it is time to send another chunk * of data. The two chunk values only differ if the stream was * repositioned by the ff or jmp server subcommand. */ void (*send)(long unsigned current_chunk, const char *buf, size_t len, const char *header_buf, size_t header_len); /** Ask the scheduler to monitor file descriptors. */ void (*pre_monitor)(struct sched *s); /** Perform I/O on the file descriptors which are ready. */ void (*post_monitor)(void); /** * Terminate all connected clients. * * This is called e.g. if the stop command was executed. It should make * the clients aware of the end-of-file condition. */ void (*shutdown_clients)(void); /** De-allocate all resources. Only called on exit. */ void (*shutdown)(void); /** * Array of function pointers for the sender subcommands. * * Each sender may implement any subset of the sender commands by * filling in the appropriate function pointer in the array. A NULL * pointer means this command is not implemented by this sender. */ int (*client_cmds[NUM_SENDER_CMDS])(struct sender_command_data*); /** * Resolve target-specific URL string * * This method must be defined if the sender supports the add/delete * subcommands. It interprets a string specifying a target URL in a * sender-specific fashion (e.g. embedded FEC string). It can also * fill in sender-specific defaults if necessary. */ int (*resolve_target)(const char *, struct sender_command_data *); }; /** NULL-terminated list, defined in \ref vss.c. */ extern const struct sender * const senders[]; /** Iterate over all senders. */ #define FOR_EACH_SENDER(_i) for ((_i) = 0; senders[(_i)]; (_i)++) /** Describes one connected client. */ struct sender_client { /** The file descriptor of the client. */ int fd; /** The socket "name" of the client. */ char *name; /** The position of this client in the client list. */ struct list_head node; /** Data specific to the particular sender. */ void *private_data; }; /** * FEC parameters as requested by FEC clients. * * Each paraslash sender may register arbitrary many clients to the virtual * streaming system, possibly with varying fec parameters. To register a * FEC client, the sender must allocate a \ref fec_client_parms structure * and pass it to \ref vss_add_fec_client(). Clients are removed from the * list if a fatal error occurs, or if the sender requests deletion of a * client by calling \ref vss_del_fec_client(). */ struct fec_client_parms { /** Number of data slices plus redundant slices. */ uint8_t slices_per_group; /** Number of slices minus number of redundant slices. */ uint8_t data_slices_per_group; /** Whether the header must be sent periodically. */ bool need_periodic_header; /** * Transport-layer initialisation for FEC support. * * This mandatory function is called from the virtual streaming system * (vss) to prepare the transport layer for sending fec slices. It * must return the maximum packet size (mps) of the connection. The * vss will create and send FEC slices that are not larger than the * mps to avoid fragmentation and to maximize packet utilization. The * user can alternatively specify a slice size of up to this value. */ int (*init_fec)(struct sender_client *sc); /** Push out FEC-encoded packets */ void (*send_fec)(struct sender_client *sc, char *buf, size_t len); };