UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
control_socket.h File Reference
#include <string>
Include dependency graph for control_socket.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define DEFAULT_CONTROL_PORT   5054
 

Functions

int control_audio_ch_report_count (struct control_state *state)
 
void control_done (struct control_state *s)
 
int control_init (int port, int connection_type, struct control_state **state, struct module *root_module, int force_ip_version)
 
void control_report_event (struct control_state *state, const std::string &event_line)
 
void control_report_stats (struct control_state *state, const std::string &stat_line)
 
void control_start (struct control_state *state)
 
bool control_stats_enabled (struct control_state *state)
 

Detailed Description

Macro Definition Documentation

◆ DEFAULT_CONTROL_PORT

#define DEFAULT_CONTROL_PORT   5054

Definition at line 41 of file control_socket.h.

Referenced by usage().

Function Documentation

◆ control_audio_ch_report_count()

int control_audio_ch_report_count ( struct control_state * state)

Definition at line 1021 of file control_socket.cpp.

1021 {
1022 return state ? state->audio_channel_report_count : 0;
1023}
void ** state

References state.

Referenced by decode_audio_frame().

◆ control_done()

void control_done ( struct control_state * s)

Definition at line 953 of file control_socket.cpp.

954{
955 if(!s) {
956 return;
957 }
958
959 module_done(&s->mod);
960
961 if(s->started) {
962 s->stats_lock.lock();
963 s->stat_event_queue.push({});
964 s->stats_lock.unlock();
965 s->stat_event_cv.notify_one();
966 s->stat_event_thread_id.join();
967
968 int ret = write_all(s->internal_fd[1], "quit\r\n", 6);
969 if (ret > 0) {
970 s->control_thread_id.join();
972 } else {
973 fprintf(stderr, "Cannot exit control thread!\n");
974 }
975 }
977 // for client, the socket has already been closed
978 // by the time of control_thread exit
980 }
981
982 delete s;
983}
#define INVALID_SOCKET
#define CLOSESOCKET
static ssize_t write_all(fd_t fd, const void *buf, size_t count)
@ SERVER
void module_done(struct module *module_data)
Definition module.c:93
void platform_pipe_close(fd_t pipe)
enum connection_type connection_type
std::mutex stats_lock
struct module mod
condition_variable stat_event_cv
thread stat_event_thread_id
queue< string > stat_event_queue

References CLOSESOCKET, control_state::connection_type, control_state::control_thread_id, control_state::internal_fd, INVALID_SOCKET, control_state::mod, module_done(), platform_pipe_close(), SERVER, control_state::socket_fd, control_state::started, control_state::stat_event_cv, control_state::stat_event_queue, control_state::stat_event_thread_id, control_state::stats_lock, and write_all().

Referenced by hd_rum_translator_deinit(), and main().

Here is the call graph for this function:

◆ control_init()

int control_init ( int port,
int connection_type,
struct control_state ** state,
struct module * root_module,
int force_ip_version )
Parameters
[in]force_ip_versionIP version to force (4 or 6). Use 0 to use default (both 4 and 6 if available)
Return values
0if success

Definition at line 159 of file control_socket.cpp.

160{
161 control_state *s = new control_state();
162
163 s->root_module = root_module;
164 s->started = false;
165
169 s->mod.priv_data = s;
170
171 if(connection_type == 0) {
172 s->network_port = port;
174 } else {
175 s->network_port = port;
177 }
178
179 if(s->connection_type == SERVER) {
180 int ip_version = 6;
181 if (force_ip_version != 4) {
182 s->socket_fd = socket(AF_INET6, SOCK_STREAM, 0);
183 if (s->socket_fd == INVALID_SOCKET) {
184 socket_error("Control socket - IPv6 not available");
185 }
186 }
187 if (force_ip_version == 4 || (force_ip_version == 0 && s->socket_fd == INVALID_SOCKET && errno == EAFNOSUPPORT)) { // try IPv4
188 ip_version = 4;
189 s->socket_fd = socket(AF_INET, SOCK_STREAM, 0);
190 }
191 if (s->socket_fd == INVALID_SOCKET) {
192 socket_error("Control socket - socket");
193 goto error;
194 }
195 int val = 1;
196 int rc;
197 rc = setsockopt(s->socket_fd, SOL_SOCKET, SO_REUSEADDR,
198 (sso_val_type) &val, sizeof(val));
199 if (rc != 0) {
200 socket_error("Control socket - setsockopt");
201 }
202
203 int ipv6only = 0;
204 if (ip_version == 6 && setsockopt(s->socket_fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only,
205 sizeof(ipv6only)) != 0) {
206 socket_error("setsockopt IPV6_V6ONLY");
207 }
208
209 /* setting address to in6addr_any allows connections to be established
210 * from both IPv4 and IPv6 hosts. This behavior can be modified
211 * using the IPPROTO_IPV6 level socket option IPV6_V6ONLY if required.*/
212 struct sockaddr_storage ss{};
213 socklen_t s_len = 0;
214 if (ip_version == 4) {
215 auto *s_in = reinterpret_cast<struct sockaddr_in *>(&ss);
216 s_in->sin_family = AF_INET;
217 s_in->sin_addr.s_addr = htonl(INADDR_ANY);
218 s_in->sin_port = htons(s->network_port);
219 s_len = sizeof *s_in;
220 } else {
221 auto *s_in6 = reinterpret_cast<struct sockaddr_in6 *>(&ss);
222 s_in6->sin6_family = AF_INET6;
223 s_in6->sin6_addr = in6addr_any;
224 s_in6->sin6_port = htons(s->network_port);
225 s_len = sizeof *s_in6;
226 }
227
228 rc = ::bind(s->socket_fd, reinterpret_cast<const struct sockaddr *>(&ss), s_len);
229 if (rc != 0) {
230 socket_error("Control socket - bind");
231 goto error;
232 } else {
233 rc = listen(s->socket_fd, MAX_CLIENTS);
234 if (rc != 0) {
235 socket_error("Control socket - listen");
236 goto error;
237 }
238 }
239 } else {
240 if (force_ip_version == 6) {
241 log_msg(LOG_LEVEL_ERROR, "Control socket: IPv6 unimplemented in client mode!\n");
242 goto error;
243 }
244 s->socket_fd = socket(AF_INET, SOCK_STREAM, 0);
245 assert(s->socket_fd != INVALID_SOCKET);
246 struct addrinfo hints, *res, *res0;
247 int err;
248
249 memset(&hints, 0, sizeof(hints));
250 hints.ai_family = AF_INET;
251 hints.ai_socktype = SOCK_STREAM;
252 char port_str[10];
253 snprintf(port_str, 10, "%d", s->network_port);
254 err = getaddrinfo("127.0.0.1", port_str, &hints, &res0);
255
256 if(err) {
257 fprintf(stderr, "Unable to get address: %s\n", gai_strerror(err));
258 goto error;
259 }
260 bool connected = false;
261
262 for (res = res0; res; res = res->ai_next) {
263 if(connect(s->socket_fd, res->ai_addr, res->ai_addrlen) == -1) {
264 continue;
265 }
266 connected = true;
267 break; /* okay we got one */
268 }
269
270 freeaddrinfo(res0);
271
272 if(!connected) {
273 fprintf(stderr, "Unable to connect to localhost:%d\n", s->network_port);
274 goto error;
275 }
276 }
277
278
279 module_register(&s->mod, root_module);
280
281 if (const char *val = get_commandline_param("control-report-audio-ch-count")) {
282 s->audio_channel_report_count = strtoll(val, NULL, 0);
283 }
284
285 *state = s;
286 return 0;
287
288error:
289 if (s->socket_fd != INVALID_SOCKET) {
291 }
292 delete s;
293 return -1;
294}
int void * val
#define MAX_CLIENTS
static void new_message(struct module *m)
void * sso_val_type
connection_type
@ CLIENT
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
void module_init_default(struct module *module_data)
Definition module.c:48
void module_register(struct module *module_data, struct module *parent)
Definition module.c:82
@ MODULE_CLASS_CONTROL
Definition module.h:91
const char * get_commandline_param(const char *key)
Definition host.cpp:894
#define socket_error(...)
struct module * root_module
enum module_class cls
Definition module.h:115
void * priv_data
Definition module.h:126
notify_t new_message
if set, notifies module that new message is in queue, receiver lock is hold during the call
Definition module.h:119

References control_state::audio_channel_report_count, CLIENT, CLOSESOCKET, module::cls, control_state::connection_type, get_commandline_param(), INVALID_SOCKET, LOG_LEVEL_ERROR, log_msg(), MAX_CLIENTS, control_state::mod, MODULE_CLASS_CONTROL, module_init_default(), module_register(), control_state::network_port, module::new_message, new_message(), module::priv_data, control_state::root_module, SERVER, socket_error, control_state::socket_fd, control_state::started, state, and val.

Referenced by main(), and main().

Here is the call graph for this function:

◆ control_report_event()

void control_report_event ( struct control_state * state,
const std::string & event_line )

Definition at line 1007 of file control_socket.cpp.

1008{
1009 if (!s) {
1010 return;
1011 }
1012
1013 control_report_stats_event(s, "event " + report_line + "\r\n");
1014}
static void control_report_stats_event(struct control_state *s, const std::string &report_line)

References control_report_stats_event().

Here is the call graph for this function:

◆ control_report_stats()

void control_report_stats ( struct control_state * state,
const std::string & stat_line )

Definition at line 998 of file control_socket.cpp.

999{
1000 if (!s || !s->stats_on) {
1001 return;
1002 }
1003
1004 control_report_stats_event(s, "stats " + report_line + "\r\n");
1005}

References control_report_stats_event(), and control_state::stats_on.

Referenced by decode_audio_frame(), filter(), and report_stats().

Here is the call graph for this function:

◆ control_start()

void control_start ( struct control_state * state)

Definition at line 296 of file control_socket.cpp.

297{
298 if (s == NULL) {
299 return;
300 }
301
302 platform_pipe_init(s->internal_fd);
303
304 s->control_thread_id = thread(control_thread, s);
305 s->stat_event_thread_id = thread(stat_event_thread, s);
306
307 log_msg(LOG_LEVEL_NOTICE, "Control socket listening on port %d\n",
308 socket_get_recv_port(s->socket_fd));
309 s->started = true;
310}
static void * stat_event_thread(void *args)
static void * control_thread(void *args)
#define LOG_LEVEL_NOTICE
information that may be interesting
Definition debug.h:61
uint16_t socket_get_recv_port(int fd)
Definition net.c:200
int platform_pipe_init(fd_t p[2])

References control_thread(), control_state::control_thread_id, control_state::internal_fd, LOG_LEVEL_NOTICE, log_msg(), platform_pipe_init(), control_state::socket_fd, socket_get_recv_port(), control_state::started, stat_event_thread(), and control_state::stat_event_thread_id.

Referenced by main(), and main().

Here is the call graph for this function:

◆ control_stats_enabled()

bool control_stats_enabled ( struct control_state * state)

Definition at line 1016 of file control_socket.cpp.

1017{
1018 return s && s->stats_on;
1019}

References control_state::stats_on.

Referenced by decode_audio_frame(), filter(), and report_stats().