UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
messaging.cpp File Reference
#include "messaging.h"
#include <condition_variable>
#include <iostream>
#include <memory>
#include <mutex>
#include <unordered_map>
#include "debug.h"
#include "module.h"
#include "utils/list.h"
#include "utils/lock_guard.h"
Include dependency graph for messaging.cpp:

Go to the source code of this file.

Classes

struct  response
 

Macros

#define MAX_MESSAGES   100
 
#define MAX_MESSAGES_FOR_NOT_EXISTING_RECV   10
 
#define MOD_NAME   "[messaging] "
 

Functions

struct message * check_message (struct module *mod)
 
void free_message (struct message *msg, struct response *r)
 
void free_message_for_child (void *m, struct response *r)
 
void free_response (struct response *r)
 
void module_check_undelivered_messages (struct module *node)
 Sends message with waiting for response.
 
void module_store_message (struct module *node, struct message *m)
 
struct message * new_message (size_t len)
 
struct response * new_response (int status, const char *text)
 
int response_get_status (struct response *r)
 
const char * response_get_text (struct response *r)
 
const char * response_status_to_text (int status)
 
struct response * send_message (struct module *root, const char *const_path, struct message *msg)
 Sends message without waiting for response.
 
static struct response * send_message_common (struct module *root, const char *const_path, struct message *msg, bool sync, int timeout_ms, int flags)
 
struct response * send_message_sync (struct module *root, const char *const_path, struct message *msg, int timeout_ms, int flags)
 Sends message without waiting for response.
 
struct response * send_message_to_receiver (struct module *receiver, struct message *msg)
 

Detailed Description

Author
Martin Pulec marti.nosp@m.n.pu.nosp@m.lec@c.nosp@m.esne.nosp@m.t.cz

Communication infrastructure for passing messages between individual UltraGrid modules.

Definition in file messaging.cpp.

Macro Definition Documentation

◆ MAX_MESSAGES

#define MAX_MESSAGES   100

Definition at line 59 of file messaging.cpp.

Referenced by send_message_common().

◆ MAX_MESSAGES_FOR_NOT_EXISTING_RECV

#define MAX_MESSAGES_FOR_NOT_EXISTING_RECV   10

Definition at line 60 of file messaging.cpp.

Referenced by send_message_common().

◆ MOD_NAME

#define MOD_NAME   "[messaging] "

Definition at line 61 of file messaging.cpp.

Referenced by send_message_common().

Function Documentation

◆ check_message()

struct message * check_message ( struct module * mod)

Definition at line 394 of file messaging.cpp.

395{
397
398 if(simple_linked_list_size(mod->msg_queue) > 0) {
399 return (struct message *) simple_linked_list_pop(mod->msg_queue);
400 } else {
401 return NULL;
402 }
403}
int simple_linked_list_size(struct simple_linked_list *l)
Definition list.cpp:93
void * simple_linked_list_pop(struct simple_linked_list *l)
Definition list.cpp:82
class generic_lock_guard< pthread_mutex_t, pthread_mutex_lock, pthread_mutex_unlock > pthread_mutex_guard
Definition lock_guard.h:43
struct simple_linked_list * msg_queue
Definition module.h:122
pthread_mutex_t msg_queue_lock
Definition module.h:121

References module::msg_queue, module::msg_queue_lock, simple_linked_list_pop(), and simple_linked_list_size().

Referenced by audio_decoder_process_message(), audio_done(), audio_receiver_thread(), audio_sender_thread(), capture_filter(), video_rxtx::check_sender_messages(), compress_frame(), decoder_process_message(), display_conference_worker(), display_get_frame(), display_sdl2_run(), display_sdl_run(), fec_check_messages(), filter(), filter(), filter(), Filter_chain::filter(), gl_process_frames(), module_done(), keyboard_control::impl::msg_received(), process_messages(), process_messages(), ultragrid_rtp_video_rxtx::receiver_process_messages(), vidcap_file_process_messages(), vidcap_import_new_message(), vidcap_switcher_grab(), and writer().

Here is the call graph for this function:

◆ free_message()

void free_message ( struct message * msg,
struct response * r )

Frees message

Additionally, it enforces user to pass response to be sent to sender.

Definition at line 318 of file messaging.cpp.

319{
320 if (!msg) {
321 return;
322 }
323
324 if (r) {
325 if (msg->send_response) {
326 msg->send_response(msg->priv_data, r);
327 } else {
328 free_response(r);
329 }
330 }
331
332 if (msg->data_deleter) {
333 msg->data_deleter(msg);
334 }
335
336 if (msg->priv_data) {
337 delete (shared_ptr<struct responder> *) msg->priv_data;
338 }
339
340 free(msg);
341}
void free_response(struct response *r)

References free_response().

Referenced by audio_decoder_process_message(), audio_done(), audio_receiver_thread(), audio_sender_thread(), capture_filter(), video_rxtx::check_sender_messages(), compress_process_message(), decoder_process_message(), display_conference_worker(), display_get_frame(), display_sdl2_run(), display_sdl_run(), fec_check_messages(), filter(), filter(), filter(), Filter_chain::filter(), free_message_for_child(), gl_process_frames(), module_done(), keyboard_control::impl::msg_received(), process_audio_message(), process_messages(), process_messages(), ultragrid_rtp_video_rxtx::receiver_process_messages(), send_message_common(), set_fec(), vidcap_file_process_messages(), vidcap_import_new_message(), vidcap_switcher_grab(), and writer().

Here is the call graph for this function:

◆ free_message_for_child()

void free_message_for_child ( void * m,
struct response * r )

Definition at line 99 of file messaging.cpp.

99 {
100 struct pair_msg_path *mp = (struct pair_msg_path *) m;
101 free_message(mp->msg, r);
102 free(mp);
103
104}
void free_message(struct message *msg, struct response *r)

References free_message().

Referenced by module_done(), and send_message_common().

Here is the call graph for this function:

◆ free_response()

◆ module_check_undelivered_messages()

void module_check_undelivered_messages ( struct module * node)

Sends message with waiting for response.

Stores message to module message box. If new_message callback is present it is called. Otherwise it may take a long time until module reads the message therefore setting timeout_ms is strongly recommended to prevent freeze (unless knowing that module implements synchronnous message processing via module::new_message callback).

If not set otherwise, when receiver doesn't exist, message is stored by nearest existing parent until it starts (this may be disabled with flag SEND_MESSAGE_FLAG_NO_STORE).

Parameters
syncwait for response timeout_ms milliseconds, if false, 202 is immediately returned (or 404 if NO_STORE flag is set and receiver doesn't exist)
timeout_msif sync==true number of ms to wait for response (-1 means infinitely), ignored if sync is false, @params flags bit mask of SEND_MESSAGE_FLAG_NO_STORE and SEND_MESSAGE_FLAG_QUIET

Definition at line 265 of file messaging.cpp.

266{
267 pthread_mutex_guard guard(node->lock);
268
269 for(void *it = simple_linked_list_it_init(node->msg_queue_children); it != NULL; ) {
270 struct pair_msg_path *msg = (struct pair_msg_path *) simple_linked_list_it_next(&it);
271 struct module *receiver = get_matching_child(node, msg->path);
272 if (receiver) {
273 struct response *resp = send_message_to_receiver(receiver, msg->msg);
274 free_response(resp);
276 free(msg);
277 // reinit iterator
279 }
280 }
281}
struct module * get_matching_child(struct module *node, const char *const_path)
Definition module.c:300
void * simple_linked_list_it_next(void **i)
Definition list.cpp:119
bool simple_linked_list_remove(struct simple_linked_list *l, void *item)
Definition list.cpp:144
void * simple_linked_list_it_init(struct simple_linked_list *l)
Definition list.cpp:108
struct response * send_message_to_receiver(struct module *receiver, struct message *msg)
pthread_mutex_t lock
Definition module.h:114
struct simple_linked_list * msg_queue_children
messages for childern that were not delivered
Definition module.h:124

References free_response(), get_matching_child(), module::lock, module::msg_queue_children, send_message_to_receiver(), simple_linked_list_it_init(), simple_linked_list_it_next(), and simple_linked_list_remove().

Referenced by module_register().

Here is the call graph for this function:

◆ module_store_message()

void module_store_message ( struct module * node,
struct message * m )

Definition at line 283 of file messaging.cpp.

284{
287}
void simple_linked_list_append(struct simple_linked_list *l, void *data)
Definition list.cpp:68

References module::msg_queue, module::msg_queue_lock, and simple_linked_list_append().

Here is the call graph for this function:

◆ new_message()

struct message * new_message ( size_t len)

Definition at line 303 of file messaging.cpp.

304{
305 assert(len >= sizeof(struct message));
306
307 struct message *ret = (struct message *)
308 calloc(1, len);
309
310 return ret;
311}
int void size_t * len

References len.

◆ new_response()

◆ response_get_status()

◆ response_get_text()

const char * response_get_text ( struct response * r)

Definition at line 369 of file messaging.cpp.

369 {
370 return r->text;
371}

References response::text.

Referenced by keyboard_control::impl::info(), send_response(), and AudioDriftFixer::update().

◆ response_status_to_text()

const char * response_status_to_text ( int status)

Definition at line 373 of file messaging.cpp.

374{
375 const static unordered_map<int, const char *> mapping = {
376 { RESPONSE_OK, "OK" },
377 { RESPONSE_ACCEPTED, "Accepted" },
378 { RESPONSE_NO_CONTENT, "No Content" },
379 { RESPONSE_BAD_REQUEST, "Bad Request" },
380 { RESPONSE_NOT_FOUND, "Not Found" },
381 { RESPONSE_REQ_TIMEOUT, "Request Timeout" },
382 { RESPONSE_INT_SERV_ERR, "Internal Server Error" },
383 { RESPONSE_NOT_IMPL, "Not Implemented" },
384 };
385
386 auto it = mapping.find(status);
387 if (it != mapping.end()) {
388 return it->second;
389 }
390
391 return NULL;
392}
static const struct codec_param mapping[AC_COUNT]
Definition libavcodec.c:87
#define RESPONSE_NO_CONTENT
Definition messaging.h:59
#define RESPONSE_NOT_IMPL
Definition messaging.h:64
#define RESPONSE_REQ_TIMEOUT
Definition messaging.h:62
#define RESPONSE_OK
Definition messaging.h:57
#define RESPONSE_BAD_REQUEST
Definition messaging.h:60
#define RESPONSE_INT_SERV_ERR
Definition messaging.h:63
#define RESPONSE_ACCEPTED
Definition messaging.h:58
#define RESPONSE_NOT_FOUND
Definition messaging.h:61

References mapping, RESPONSE_ACCEPTED, RESPONSE_BAD_REQUEST, RESPONSE_INT_SERV_ERR, RESPONSE_NO_CONTENT, RESPONSE_NOT_FOUND, RESPONSE_NOT_IMPL, RESPONSE_OK, and RESPONSE_REQ_TIMEOUT.

Referenced by send_response().

◆ send_message()

struct response * send_message ( struct module * root,
const char * const_path,
struct message * msg )

Sends message without waiting for response.

Stores message to module message box. If new_message callback is present it is called. Otherwise it may take a long time until module reads the message therefore setting timeout_ms is strongly recommended to prevent freeze (unless knowing that module implements synchronnous message processing via module::new_message callback).

If not set otherwise, when receiver doesn't exist, message is stored by nearest existing parent until it starts (this may be disabled with flag SEND_MESSAGE_FLAG_NO_STORE).

Parameters
syncwait for response timeout_ms milliseconds, if false, 202 is immediately returned (or 404 if NO_STORE flag is set and receiver doesn't exist)
timeout_msif sync==true number of ms to wait for response (-1 means infinitely), ignored if sync is false, @params flags bit mask of SEND_MESSAGE_FLAG_NO_STORE and SEND_MESSAGE_FLAG_QUIET

Definition at line 249 of file messaging.cpp.

250{
251 return send_message_common(root, const_path, msg, false, 0, 0);
252}
static struct response * send_message_common(struct module *root, const char *const_path, struct message *msg, bool sync, int timeout_ms, int flags)

References send_message_common().

Referenced by BasicRTSPOnlySubsession::deleteStream(), process_audio_message(), process_msg(), keyboard_control::impl::run(), sdp_send_change_address_message(), h264_sdp_video_rxtx::send_frame(), and BasicRTSPOnlySubsession::startStream().

Here is the call graph for this function:

◆ send_message_common()

static struct response * send_message_common ( struct module * root,
const char * const_path,
struct message * msg,
bool sync,
int timeout_ms,
int flags )
static

Stores message to module message box. If new_message callback is present it is called. Otherwise it may take a long time until module reads the message therefore setting timeout_ms is strongly recommended to prevent freeze (unless knowing that module implements synchronnous message processing via module::new_message callback).

If not set otherwise, when receiver doesn't exist, message is stored by nearest existing parent until it starts (this may be disabled with flag SEND_MESSAGE_FLAG_NO_STORE).

Parameters
syncwait for response timeout_ms milliseconds, if false, 202 is immediately returned (or 404 if NO_STORE flag is set and receiver doesn't exist)
timeout_msif sync==true number of ms to wait for response (-1 means infinitely), ignored if sync is false, @params flags bit mask of SEND_MESSAGE_FLAG_NO_STORE and SEND_MESSAGE_FLAG_QUIET
Invariant
either receiver is NULL or receiver->lock is locked (exactly once)

Definition at line 121 of file messaging.cpp.

122{
127 char *path, *tmp;
128 char *item, *save_ptr;
129 tmp = path = strdup(const_path);
130 struct module *receiver = root;
131 shared_ptr<struct responder> responder;
132
133 if (sync) {
134 msg->send_response = responder::receive_response;
135 responder = shared_ptr<struct responder>(new struct responder());
136 msg->priv_data = new shared_ptr<struct responder>(responder);
137 }
138
139 pthread_mutex_lock(&receiver->lock);
140
141 while ((item = strtok_r(path, ".", &save_ptr))) {
142 path = NULL;
143 struct module *old_receiver = receiver;
144
145 if (strcmp(item, "root") == 0)
146 continue;
147
148 receiver = get_matching_child(receiver, item);
149
150 if (!receiver) {
153 printf("Receiver %s does not exist.\n", const_path);
154 //dump_tree(root, 0);
157 printf("Dropping some old messages for %s (queue full).\n", const_path);
159 new_response(RESPONSE_NOT_FOUND, "Receiver not found"));
160 }
161
162 struct pair_msg_path *saved_message = (struct pair_msg_path *)
163 malloc(sizeof(struct pair_msg_path) + strlen(const_path + (item - tmp)) + 1);
164 saved_message->msg = msg;
165 strcpy(saved_message->path, const_path + (item - tmp));
166
167 simple_linked_list_append(old_receiver->msg_queue_children, saved_message);
168 pthread_mutex_unlock(&old_receiver->lock);
169
170 free(tmp);
171 if (!sync) {
172 return new_response(RESPONSE_ACCEPTED, "(receiver not yet exists)");
173 } else {
174 unique_lock<mutex> lk(responder->lock);
175 if (timeout_ms == -1) {
176 log_msg(LOG_LEVEL_WARNING, MOD_NAME "Warning: infinite wait for "
177 "non-existent recv. Please report!\n");
178 responder->cv.wait(lk, [responder]{return responder->received_response != NULL;});
179 } else {
180 responder->cv.wait_for(lk, std::chrono::milliseconds(timeout_ms), [responder]{return responder->received_response != NULL;});
181 }
182 if (responder->received_response) {
183 struct response *resp = responder->received_response;
184 responder->received_response = NULL;
185 return resp;
186 } else {
187 return new_response(RESPONSE_ACCEPTED, NULL);
188 }
189 }
190 } else {
191 pthread_mutex_unlock(&old_receiver->lock);
192 free_message(msg, NULL);
193 free(tmp);
194 return new_response(RESPONSE_NOT_FOUND, NULL);
195 }
196 }
197 pthread_mutex_lock(&receiver->lock);
198 pthread_mutex_unlock(&old_receiver->lock);
199 }
200
201 free(tmp);
202
203 //pthread_mutex_guard guard(receiver->lock, lock_guard_retain_ownership_t());
204
205 pthread_mutex_lock(&receiver->msg_queue_lock);
206 int size = simple_linked_list_size(receiver->msg_queue);
207 pthread_mutex_unlock(&receiver->msg_queue_lock);
208 if (size >= MAX_MESSAGES) {
209 struct message *m = (struct message *) simple_linked_list_pop(receiver->msg_queue);
210 free_message(m, new_response(RESPONSE_INT_SERV_ERR, "Too many unprocessed messages"));
211 printf("Dropping some messages for %s - queue full.\n", const_path);
212 }
213 pthread_mutex_lock(&receiver->msg_queue_lock);
215 pthread_mutex_unlock(&receiver->msg_queue_lock);
216
217 if (receiver->new_message) {
218 receiver->new_message(receiver);
219 }
220
221 pthread_mutex_unlock(&receiver->lock);
222
223 if (!sync) {
224 return new_response(RESPONSE_ACCEPTED, NULL);
225 } else {
226 unique_lock<mutex> lk(responder->lock);
227 if (timeout_ms == -1) {
228 if (receiver->new_message == NULL) {
229 log_msg(LOG_LEVEL_WARNING, MOD_NAME "Warning: infinite wait for "
230 "module without msg notifier. Please report!\n");
231 }
232 responder->cv.wait(lk, [responder]{return responder->received_response != NULL;});
233 } else {
234 responder->cv.wait_for(lk, std::chrono::milliseconds(timeout_ms), [responder]{return responder->received_response != NULL;});
235 }
236 if (responder->received_response) {
237 struct response *resp = responder->received_response;
238 responder->received_response = NULL;
239 return resp;
240 } else {
241 return new_response(RESPONSE_ACCEPTED, NULL);
242 }
243 }
244}
const char unsigned int flags
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
#define MAX_MESSAGES
Definition messaging.cpp:59
struct response * new_response(int status, const char *text)
void free_message_for_child(void *m, struct response *r)
Definition messaging.cpp:99
#define MOD_NAME
Definition messaging.cpp:61
#define MAX_MESSAGES_FOR_NOT_EXISTING_RECV
Definition messaging.cpp:60
#define SEND_MESSAGE_FLAG_QUIET
do not print error messages on console (recv not found/queue full)
Definition messaging.h:171
#define SEND_MESSAGE_FLAG_NO_STORE
if receiver doesn't exist, doesn't store it and retur 404 instead
Definition messaging.h:172
struct msghdr msg
Definition hd-rum.c:27
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 flags, free_message(), free_message_for_child(), get_matching_child(), module::lock, LOG_LEVEL_WARNING, log_msg(), MAX_MESSAGES, MAX_MESSAGES_FOR_NOT_EXISTING_RECV, MOD_NAME, msg, module::msg_queue, module::msg_queue_children, module::msg_queue_lock, module::new_message, new_response(), RESPONSE_ACCEPTED, RESPONSE_INT_SERV_ERR, RESPONSE_NOT_FOUND, SEND_MESSAGE_FLAG_NO_STORE, SEND_MESSAGE_FLAG_QUIET, simple_linked_list_append(), simple_linked_list_pop(), and simple_linked_list_size().

Referenced by send_message(), and send_message_sync().

Here is the call graph for this function:

◆ send_message_sync()

struct response * send_message_sync ( struct module * root,
const char * const_path,
struct message * msg,
int timeout_ms,
int flags )

Sends message without waiting for response.

Stores message to module message box. If new_message callback is present it is called. Otherwise it may take a long time until module reads the message therefore setting timeout_ms is strongly recommended to prevent freeze (unless knowing that module implements synchronnous message processing via module::new_message callback).

If not set otherwise, when receiver doesn't exist, message is stored by nearest existing parent until it starts (this may be disabled with flag SEND_MESSAGE_FLAG_NO_STORE).

Parameters
syncwait for response timeout_ms milliseconds, if false, 202 is immediately returned (or 404 if NO_STORE flag is set and receiver doesn't exist)
timeout_msif sync==true number of ms to wait for response (-1 means infinitely), ignored if sync is false, @params flags bit mask of SEND_MESSAGE_FLAG_NO_STORE and SEND_MESSAGE_FLAG_QUIET

Definition at line 257 of file messaging.cpp.

258{
259 return send_message_common(root, const_path, msg, true, timeout_ms, flags);
260}

References flags, and send_message_common().

Referenced by keyboard_control::impl::exec_external_commands(), keyboard_control::impl::info(), keycontrol_register_key(), keycontrol_send_key(), AudioDriftFixer::update(), and vidcap_switcher_register_keyboard_ctl().

Here is the call graph for this function:

◆ send_message_to_receiver()

struct response * send_message_to_receiver ( struct module * receiver,
struct message * msg )

Definition at line 289 of file messaging.cpp.

290{
291 pthread_mutex_lock(&receiver->msg_queue_lock);
293 pthread_mutex_unlock(&receiver->msg_queue_lock);
294
295 pthread_mutex_guard guard(receiver->lock);
296 if (receiver->new_message) {
297 receiver->new_message(receiver);
298 }
299
300 return new_response(RESPONSE_ACCEPTED, NULL);
301}

References module::lock, module::msg_queue, module::msg_queue_lock, module::new_message, new_response(), RESPONSE_ACCEPTED, and simple_linked_list_append().

Referenced by compress_process_message(), module_check_undelivered_messages(), reconfigure_decoder(), set_fec(), Participant_manager::tick(), and tx_update().

Here is the call graph for this function: