Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Enumerations | Functions
framehook.c File Reference

FrameHooks Architecture. More...

#include "asterisk.h"
#include "asterisk/channel.h"
#include "asterisk/linkedlists.h"
#include "asterisk/framehook.h"
#include "asterisk/frame.h"
Include dependency graph for framehook.c:

Go to the source code of this file.

Data Structures

struct  ast_framehook
 
struct  ast_framehook_list
 

Enumerations

enum  framehook_detachment_mode { FRAMEHOOK_DETACH_DESTROY = 0, FRAMEHOOK_DETACH_PRESERVE }
 

Functions

int ast_framehook_attach (struct ast_channel *chan, struct ast_framehook_interface *i)
 Attach an framehook onto a channel for frame interception. More...
 
int ast_framehook_detach (struct ast_channel *chan, int id)
 Detach an framehook from a channel. More...
 
int ast_framehook_list_contains_no_active (struct ast_framehook_list *framehooks)
 Determine if a framehook list is free of active framehooks or not. More...
 
int ast_framehook_list_contains_no_active_of_type (struct ast_framehook_list *framehooks, enum ast_frame_type type)
 Determine if a framehook list is free of active framehooks consuming a specific type of frame. More...
 
int ast_framehook_list_destroy (struct ast_channel *chan)
 This is used by the channel API to detach and destroy all framehooks on a channel during channel destruction. More...
 
void ast_framehook_list_fixup (struct ast_channel *old_chan, struct ast_channel *new_chan)
 This is used by the channel API during a masquerade operation to move all mobile framehooks from the original channel to the clone channel. More...
 
int ast_framehook_list_is_empty (struct ast_framehook_list *framehooks)
 Determine if an framehook list is empty or not. More...
 
struct ast_frameast_framehook_list_read_event (struct ast_framehook_list *framehooks, struct ast_frame *frame)
 This is used by the channel API push a frame read event to a channel's framehook list. More...
 
struct ast_frameast_framehook_list_write_event (struct ast_framehook_list *framehooks, struct ast_frame *frame)
 This is used by the channel API push a frame write event to a channel's framehook list. More...
 
static void framehook_detach (struct ast_framehook *framehook, enum framehook_detachment_mode mode)
 
static struct ast_frameframehook_list_push_event (struct ast_framehook_list *framehooks, struct ast_frame *frame, enum ast_framehook_event event)
 

Detailed Description

FrameHooks Architecture.

Author
David Vossel dvoss.nosp@m.el@d.nosp@m.igium.nosp@m..com

Definition in file framehook.c.

Enumeration Type Documentation

◆ framehook_detachment_mode

Enumerator
FRAMEHOOK_DETACH_DESTROY 

Destroy the framehook outright.

FRAMEHOOK_DETACH_PRESERVE 

Remove the framehook from the channel, but don't destroy the data since it will be used by a replacement framehook on another channel.

Definition at line 57 of file framehook.c.

58 {
59  /*! Destroy the framehook outright. */
61  /*! Remove the framehook from the channel, but don't destroy the data since
62  * it will be used by a replacement framehook on another channel. */
64 };

Function Documentation

◆ ast_framehook_attach()

int ast_framehook_attach ( struct ast_channel chan,
struct ast_framehook_interface i 
)

Attach an framehook onto a channel for frame interception.

Since
1.8
Parameters
chanast_channel The channel to attach the hook on to.
iframehook interface, The framehook's callback functions and stored data.
Precondition
The Channel must be locked during this function call.
Note
The data pointer is never touched by the framehook API except to provide it during the event and destruction callbacks. It is entirely up to the application using this API to manage the memory associated with the data pointer.
Return values
Onsuccess, non-negative id representing this hook on the channel
Onfailure, -1

Definition at line 132 of file framehook.c.

References ast_calloc, ast_channel_framehooks(), ast_channel_framehooks_set(), ast_channel_is_bridged(), ast_channel_set_unbridged_nolock(), AST_FRAMEHOOK_EVENT_ATTACHED, AST_FRAMEHOOK_INTERFACE_VERSION, ast_free, ast_frfree, AST_LIST_INSERT_TAIL, ast_log, ast_framehook::chan, ast_framehook_list::count, ast_framehook_interface::data, ast_framehook_interface::event_cb, ast_framehook::i, ast_framehook::id, ast_framehook_list::id_count, ast_framehook::list, LOG_ERROR, NULL, and ast_framehook_interface::version.

Referenced by ast_channel_suppress(), ast_framehook_list_fixup(), ast_jb_create_framehook(), attach_framehook(), dtmfstore_exec(), fax_detect_attach(), fax_gateway_attach(), frame_drop_helper(), frame_trace_helper(), handle_remb_set(), native_rtp_bridge_framehook_attach(), refer_blind_callback(), set_hold_intercept(), and t38_attach_framehook().

133 {
134  struct ast_framehook *framehook;
135  struct ast_framehook_list *fh_list;
136  struct ast_frame *frame;
138  ast_log(LOG_ERROR, "Version '%hu' of framehook interface not what we compiled against (%i)\n",
140  return -1;
141  }
142  if (!i->event_cb || !(framehook = ast_calloc(1, sizeof(*framehook)))) {
143  return -1;
144  }
145  framehook->i = *i;
146  framehook->chan = chan;
147 
148  /* create the framehook list if it didn't already exist */
149  if (!ast_channel_framehooks(chan)) {
150  if (!(fh_list = ast_calloc(1, sizeof(*ast_channel_framehooks(chan))))) {
151  ast_free(framehook);
152  return -1;
153  }
154  ast_channel_framehooks_set(chan, fh_list);
155  }
156 
157  ast_channel_framehooks(chan)->count++;
158  framehook->id = ++ast_channel_framehooks(chan)->id_count;
159  AST_LIST_INSERT_TAIL(&ast_channel_framehooks(chan)->list, framehook, list);
160 
161  /* Tell the event callback we're live and rocking */
162  frame = framehook->i.event_cb(framehook->chan, NULL, AST_FRAMEHOOK_EVENT_ATTACHED, framehook->i.data);
163 
164  /* Never assume anything about this function. If you can return a frame during
165  * the attached event, then assume someone will. */
166  if (frame) {
167  ast_frfree(frame);
168  }
169 
170  if (ast_channel_is_bridged(chan)) {
172  }
173 
174  return framehook->id;
175 }
ast_framehook_event_callback event_cb
Definition: framehook.h:233
void ast_channel_framehooks_set(struct ast_channel *chan, struct ast_framehook_list *value)
struct ast_framehook_list * ast_channel_framehooks(const struct ast_channel *chan)
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
void ast_channel_set_unbridged_nolock(struct ast_channel *chan, int value)
Variant of ast_channel_set_unbridged. Use this if the channel is already locked prior to calling...
unsigned int id_count
Definition: framehook.c:53
#define LOG_ERROR
Definition: logger.h:285
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
#define AST_FRAMEHOOK_INTERFACE_VERSION
Definition: framehook.h:227
int ast_channel_is_bridged(const struct ast_channel *chan)
Determine if a channel is in a bridge.
Definition: channel.c:10746
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
struct ast_framehook_interface i
Definition: framehook.c:38
unsigned int id
Definition: framehook.c:42
unsigned int count
Definition: framehook.c:51
#define ast_frfree(fr)
Data structure associated with a single frame of data.
struct ast_channel * chan
Definition: framehook.c:40

◆ ast_framehook_detach()

int ast_framehook_detach ( struct ast_channel chan,
int  framehook_id 
)

Detach an framehook from a channel.

Since
1.8
Precondition
The Channel must be locked during this function call. If this function is never called after attaching an framehook, the framehook will be detached and destroyed during channel destruction.
Parameters
chanThe channel the framehook is attached to
framehook_idThe framehook's id
Return values
0success
-1framehook did not exist on the channel. This means the framehook either never existed on the channel, or was already detached.

Definition at line 177 of file framehook.c.

References ast_channel_framehooks(), ast_channel_is_bridged(), ast_channel_set_unbridged_nolock(), AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_framehook::detach_and_destroy_me, ast_framehook::id, and ast_framehook::list.

Referenced by acf_faxopt_write(), ast_channel_suppress(), ast_channel_unsuppress(), ast_framehook_list_fixup(), ast_jb_create_framehook(), fax_detect_framehook(), fax_gateway_detect_t38(), fax_gateway_framehook(), fax_gateway_request_t38(), fixup_callback(), frame_drop_helper(), frame_trace_helper(), handle_remb_set(), native_rtp_bridge_framehook_detach(), refer_blind_callback(), refer_progress_bridge(), refer_progress_framehook(), remove_dtmf_store(), remove_hold_intercept(), t38_attach_framehook(), t38_masq(), and transfer_target_framehook_cb().

178 {
179  struct ast_framehook *framehook;
180  int res = -1;
181 
182  if (!ast_channel_framehooks(chan)) {
183  return res;
184  }
185 
187  if (framehook->id == id) {
188  /* we mark for detachment rather than doing explicitly here because
189  * it needs to be safe for this function to be called within the
190  * event callback. If we allowed the hook to actually be destroyed
191  * immediately here, the event callback would crash on exit. */
192  framehook->detach_and_destroy_me = 1;
193  res = 0;
194  break;
195  }
196  }
198 
199  if (!res && ast_channel_is_bridged(chan)) {
201  }
202 
203  return res;
204 }
struct ast_framehook_list * ast_channel_framehooks(const struct ast_channel *chan)
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
struct ast_framehook::@393 list
void ast_channel_set_unbridged_nolock(struct ast_channel *chan, int value)
Variant of ast_channel_set_unbridged. Use this if the channel is already locked prior to calling...
int ast_channel_is_bridged(const struct ast_channel *chan)
Determine if a channel is in a bridge.
Definition: channel.c:10746
unsigned int id
Definition: framehook.c:42
int detach_and_destroy_me
Definition: framehook.c:44
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528

◆ ast_framehook_list_contains_no_active()

int ast_framehook_list_contains_no_active ( struct ast_framehook_list framehooks)

Determine if a framehook list is free of active framehooks or not.

Since
12.0.0
Precondition
The channel must be locked during this function call.
Parameters
framehooksthe framehook list
Return values
0,notempty
1,isempty (aside from dying framehooks)
Note
This function is very similar to ast_framehook_list_is_empty, but it checks individual framehooks to see if they have been marked for destruction and doesn't count them if they are.

Definition at line 282 of file framehook.c.

References ast_framehook_list_contains_no_active_of_type().

Referenced by ast_channel_has_audio_frame_or_monitor().

283 {
284  return ast_framehook_list_contains_no_active_of_type(framehooks, 0);
285 }
int ast_framehook_list_contains_no_active_of_type(struct ast_framehook_list *framehooks, enum ast_frame_type type)
Determine if a framehook list is free of active framehooks consuming a specific type of frame...
Definition: framehook.c:287

◆ ast_framehook_list_contains_no_active_of_type()

int ast_framehook_list_contains_no_active_of_type ( struct ast_framehook_list framehooks,
enum ast_frame_type  type 
)

Determine if a framehook list is free of active framehooks consuming a specific type of frame.

Since
12.3.0
Precondition
The channel must be locked during this function call.
Parameters
framehooksthe framehook list
Return values
0,notempty
1,isempty (aside from dying framehooks)
Note
This function is very similar to ast_framehook_list_is_empty, but it checks individual framehooks to see if they have been marked for destruction and doesn't count them if they are.

Definition at line 287 of file framehook.c.

References AST_LIST_EMPTY, AST_LIST_TRAVERSE, ast_framehook_interface::consume_cb, ast_framehook_interface::data, ast_framehook::detach_and_destroy_me, ast_framehook::i, ast_framehook::list, and ast_framehook_list::list.

Referenced by ast_channel_has_hook_requiring_audio(), and ast_framehook_list_contains_no_active().

289 {
290  struct ast_framehook *cur;
291 
292  if (!framehooks) {
293  return 1;
294  }
295 
296  if (AST_LIST_EMPTY(&framehooks->list)) {
297  return 1;
298  }
299 
300  AST_LIST_TRAVERSE(&framehooks->list, cur, list) {
301  if (cur->detach_and_destroy_me) {
302  continue;
303  }
304  if (type && cur->i.consume_cb && !cur->i.consume_cb(cur->i.data, type)) {
305  continue;
306  }
307  return 0;
308  }
309 
310  return 1;
311 }
static const char type[]
Definition: chan_ooh323.c:109
struct ast_framehook_list::@394 list
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
struct ast_framehook::@393 list
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
ast_framehook_consume_callback consume_cb
Definition: framehook.h:240
struct ast_framehook_interface i
Definition: framehook.c:38
int detach_and_destroy_me
Definition: framehook.c:44

◆ ast_framehook_list_destroy()

int ast_framehook_list_destroy ( struct ast_channel chan)

This is used by the channel API to detach and destroy all framehooks on a channel during channel destruction.

Since
1.8
Precondition
The Channel must be locked during this function call.
Parameters
chanchannel containing the framehook list to destroy.
Return values
0success
-1failure

Definition at line 206 of file framehook.c.

References ast_channel_framehooks(), ast_channel_framehooks_set(), ast_free, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, framehook_detach(), FRAMEHOOK_DETACH_DESTROY, ast_framehook::list, and NULL.

Referenced by destroy_hooks().

207 {
208  struct ast_framehook *framehook;
209 
210  if (!ast_channel_framehooks(chan)) {
211  return 0;
212  }
216  }
220  return 0;
221 }
void ast_channel_framehooks_set(struct ast_channel *chan, struct ast_framehook_list *value)
static void framehook_detach(struct ast_framehook *framehook, enum framehook_detachment_mode mode)
Definition: framehook.c:66
struct ast_framehook_list * ast_channel_framehooks(const struct ast_channel *chan)
#define NULL
Definition: resample.c:96
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
struct ast_framehook::@393 list
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:556
#define ast_free(a)
Definition: astmm.h:182
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528

◆ ast_framehook_list_fixup()

void ast_framehook_list_fixup ( struct ast_channel old_chan,
struct ast_channel new_chan 
)

This is used by the channel API during a masquerade operation to move all mobile framehooks from the original channel to the clone channel.

Since
12.5.0
Precondition
Both channels must be locked prior to this function call.
Parameters
old_chanThe channel being cloned from
new_chanThe channel being cloned to

Definition at line 223 of file framehook.c.

References ast_channel_framehooks(), ast_channel_is_bridged(), ast_channel_set_unbridged_nolock(), ast_framehook_attach(), ast_framehook_detach(), AST_LIST_EMPTY, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log, ast_framehook_interface::chan_breakdown_cb, ast_framehook_interface::chan_fixup_cb, ast_framehook_interface::data, ast_framehook_interface::disable_inheritance, framehook_detach(), FRAMEHOOK_DETACH_DESTROY, FRAMEHOOK_DETACH_PRESERVE, ast_framehook::i, ast_framehook::id, ast_framehook::list, and LOG_WARNING.

Referenced by channel_do_masquerade().

224 {
225  struct ast_framehook *framehook;
226  int moved_framehook_id;
227 
228  if (ast_channel_framehooks(new_chan)) {
230  if (framehook->i.disable_inheritance) {
231  ast_framehook_detach(new_chan, framehook->id);
232  continue;
233  }
234 
235  if (framehook->i.chan_breakdown_cb) {
236  framehook->i.chan_breakdown_cb(framehook->i.data, framehook->id,
237  old_chan, new_chan);
238  }
239  }
241  }
242 
243  if (!ast_channel_framehooks(old_chan)) {
244  return;
245  }
246 
247  if (!AST_LIST_EMPTY(&ast_channel_framehooks(old_chan)->list)
248  && ast_channel_is_bridged(old_chan)) {
250  }
251  while ((framehook = AST_LIST_REMOVE_HEAD(&ast_channel_framehooks(old_chan)->list, list))) {
252  /* If inheritance is not allowed for this framehook, just destroy it. */
253  if (framehook->i.disable_inheritance) {
255  continue;
256  }
257 
258  /* Otherwise move it to the other channel and perform any fixups set by the framehook interface */
259  moved_framehook_id = ast_framehook_attach(new_chan, &framehook->i);
260  if (moved_framehook_id < 0) {
261  ast_log(LOG_WARNING, "Failed framehook copy during masquerade. Expect loss of features.\n");
263  } else {
264  if (framehook->i.chan_fixup_cb) {
265  framehook->i.chan_fixup_cb(framehook->i.data, moved_framehook_id,
266  old_chan, new_chan);
267  }
268 
270  }
271  }
272 }
static void framehook_detach(struct ast_framehook *framehook, enum framehook_detachment_mode mode)
Definition: framehook.c:66
struct ast_framehook_list * ast_channel_framehooks(const struct ast_channel *chan)
#define LOG_WARNING
Definition: logger.h:274
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interface *i)
Attach an framehook onto a channel for frame interception.
Definition: framehook.c:132
struct ast_framehook::@393 list
#define ast_log
Definition: astobj2.c:42
void ast_channel_set_unbridged_nolock(struct ast_channel *chan, int value)
Variant of ast_channel_set_unbridged. Use this if the channel is already locked prior to calling...
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
int ast_channel_is_bridged(const struct ast_channel *chan)
Determine if a channel is in a bridge.
Definition: channel.c:10746
ast_framehook_chan_fixup_callback chan_fixup_cb
Definition: framehook.h:244
ast_framehook_chan_fixup_callback chan_breakdown_cb
Definition: framehook.h:248
struct ast_framehook_interface i
Definition: framehook.c:38
unsigned int id
Definition: framehook.c:42
int ast_framehook_detach(struct ast_channel *chan, int id)
Detach an framehook from a channel.
Definition: framehook.c:177
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528

◆ ast_framehook_list_is_empty()

int ast_framehook_list_is_empty ( struct ast_framehook_list framehooks)

Determine if an framehook list is empty or not.

Since
1.8
Precondition
The Channel must be locked during this function call.
Parameters
framehooksthe framehook list
Return values
0,notempty
1,isempty

Definition at line 274 of file framehook.c.

References AST_LIST_EMPTY, and ast_framehook_list::list.

Referenced by ast_indicate_data().

275 {
276  if (!framehooks) {
277  return 1;
278  }
279  return AST_LIST_EMPTY(&framehooks->list) ? 1 : 0;
280 }
struct ast_framehook_list::@394 list
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449

◆ ast_framehook_list_read_event()

struct ast_frame* ast_framehook_list_read_event ( struct ast_framehook_list framehooks,
struct ast_frame frame 
)

This is used by the channel API push a frame read event to a channel's framehook list.

Since
1.8

After this function completes, the resulting frame that is returned could be anything, even NULL. There is nothing to keep up with after this function. If the frame is modified, the framehook callback is in charge of any memory management associated with that modification.

Precondition
The Channel must be locked during this function call.
Parameters
framehookslist to push event to.
framebeing pushed to the framehook list.
Returns
The resulting frame after being viewed and modified by the framehook callbacks.

Definition at line 318 of file framehook.c.

References AST_FRAMEHOOK_EVENT_READ, and framehook_list_push_event().

Referenced by __ast_read().

319 {
320  return framehook_list_push_event(framehooks, frame, AST_FRAMEHOOK_EVENT_READ);
321 }
static struct ast_frame * framehook_list_push_event(struct ast_framehook_list *framehooks, struct ast_frame *frame, enum ast_framehook_event event)
Definition: framehook.c:83

◆ ast_framehook_list_write_event()

struct ast_frame* ast_framehook_list_write_event ( struct ast_framehook_list framehooks,
struct ast_frame frame 
)

This is used by the channel API push a frame write event to a channel's framehook list.

Since
1.8

After this function completes, the resulting frame that is returned could be anything, even NULL. There is nothing to keep up with after this function. If the frame is modified, the framehook callback is in charge of any memory management associated with that modification.

Precondition
The Channel must be locked during this function call.
Parameters
framehookslist to push event to.
framebeing pushed to the framehook list.
Returns
The resulting frame after being viewed and modified by the framehook callbacks.

Definition at line 313 of file framehook.c.

References AST_FRAMEHOOK_EVENT_WRITE, and framehook_list_push_event().

Referenced by ast_indicate_data(), and ast_write_stream().

314 {
315  return framehook_list_push_event(framehooks, frame, AST_FRAMEHOOK_EVENT_WRITE);
316 }
static struct ast_frame * framehook_list_push_event(struct ast_framehook_list *framehooks, struct ast_frame *frame, enum ast_framehook_event event)
Definition: framehook.c:83

◆ framehook_detach()

static void framehook_detach ( struct ast_framehook framehook,
enum framehook_detachment_mode  mode 
)
static

Definition at line 66 of file framehook.c.

References AST_FRAMEHOOK_EVENT_DETACHED, ast_free, ast_frfree, ast_framehook::chan, ast_framehook_interface::data, ast_framehook_interface::destroy_cb, ast_framehook_interface::event_cb, FRAMEHOOK_DETACH_DESTROY, ast_framehook::i, and NULL.

Referenced by ast_framehook_list_destroy(), ast_framehook_list_fixup(), and framehook_list_push_event().

67 {
68  struct ast_frame *frame;
69  frame = framehook->i.event_cb(framehook->chan, NULL, AST_FRAMEHOOK_EVENT_DETACHED, framehook->i.data);
70  /* never assume anything about this function. If you can return a frame during
71  * the detached event, then assume someone will. */
72  if (frame) {
73  ast_frfree(frame);
74  }
75  framehook->chan = NULL;
76 
77  if (mode == FRAMEHOOK_DETACH_DESTROY && framehook->i.destroy_cb) {
78  framehook->i.destroy_cb(framehook->i.data);
79  }
80  ast_free(framehook);
81 }
ast_framehook_event_callback event_cb
Definition: framehook.h:233
#define NULL
Definition: resample.c:96
ast_framehook_destroy_callback destroy_cb
Definition: framehook.h:236
#define ast_free(a)
Definition: astmm.h:182
struct ast_framehook_interface i
Definition: framehook.c:38
#define ast_frfree(fr)
Data structure associated with a single frame of data.
struct ast_channel * chan
Definition: framehook.c:40

◆ framehook_list_push_event()

static struct ast_frame* framehook_list_push_event ( struct ast_framehook_list framehooks,
struct ast_frame frame,
enum ast_framehook_event  event 
)
static

Definition at line 83 of file framehook.c.

References ast_alloca, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_framehook::chan, ast_framehook_list::count, ast_framehook_interface::data, ast_framehook::detach_and_destroy_me, ast_framehook_interface::event_cb, framehook_detach(), FRAMEHOOK_DETACH_DESTROY, ast_framehook::i, ast_framehook::list, and ast_framehook_list::list.

Referenced by ast_framehook_list_read_event(), and ast_framehook_list_write_event().

84 {
85  struct ast_framehook *framehook;
86  struct ast_frame *original_frame;
87  int *skip;
88  size_t skip_size;
89 
90  if (!framehooks) {
91  return frame;
92  }
93 
94  skip_size = sizeof(int) * framehooks->count;
95  skip = ast_alloca(skip_size);
96  memset(skip, 0, skip_size);
97 
98  do {
99  unsigned int num = 0;
100  original_frame = frame;
101 
102  AST_LIST_TRAVERSE_SAFE_BEGIN(&framehooks->list, framehook, list) {
103  if (framehook->detach_and_destroy_me) {
104  /* this guy is signaled for destruction */
107  continue;
108  }
109 
110  /* If this framehook has been marked as needing to be skipped, do so */
111  if (skip[num]) {
112  num++;
113  continue;
114  }
115 
116  frame = framehook->i.event_cb(framehook->chan, frame, event, framehook->i.data);
117 
118  if (frame != original_frame) {
119  /* To prevent looping we skip any framehooks that have already provided a modified frame */
120  skip[num] = 1;
121  break;
122  }
123 
124  num++;
125  }
127  } while (frame != original_frame);
128 
129  return frame;
130 }
ast_framehook_event_callback event_cb
Definition: framehook.h:233
static void framehook_detach(struct ast_framehook *framehook, enum framehook_detachment_mode mode)
Definition: framehook.c:66
Definition: astman.c:222
struct ast_framehook_list::@394 list
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:556
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
struct ast_framehook_interface i
Definition: framehook.c:38
unsigned int count
Definition: framehook.c:51
Data structure associated with a single frame of data.
int detach_and_destroy_me
Definition: framehook.c:44
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
struct ast_channel * chan
Definition: framehook.c:40