summaryrefslogtreecommitdiff
path: root/send.h
blob: e6424ab52b7ea8508c0ec218b219fa727e770cea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/* 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);
};