Asterisk - The Open Source Telephony Project GIT-master-a358458
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};
@ FRAMEHOOK_DETACH_DESTROY
Definition: framehook.c:60
@ FRAMEHOOK_DETACH_PRESERVE
Definition: framehook.c:63

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
non-negativesuccess, id representing this hook on the channel
-1failure

Definition at line 132 of file framehook.c.

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
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}
#define ast_free(a)
Definition: astmm.h:180
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#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.
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)
int ast_channel_is_bridged(const struct ast_channel *chan)
Determine if a channel is in a bridge.
Definition: channel.c:10545
@ AST_FRAMEHOOK_EVENT_ATTACHED
Definition: framehook.h:154
#define AST_FRAMEHOOK_INTERFACE_VERSION
Definition: framehook.h:227
#define ast_frfree(fr)
#define LOG_ERROR
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define NULL
Definition: resample.c:96
Data structure associated with a single frame of data.
ast_framehook_event_callback event_cb
Definition: framehook.h:233
unsigned int count
Definition: framehook.c:51
unsigned int id_count
Definition: framehook.c:53
struct ast_framehook_interface i
Definition: framehook.c:38
struct ast_channel * chan
Definition: framehook.c:40
unsigned int id
Definition: framehook.c:42

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, LOG_ERROR, NULL, and ast_framehook_interface::version.

Referenced by aoc_attach_framehook(), 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().

◆ 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.

178{
179 struct ast_framehook *framehook;
180 int res = -1;
181
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}
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
struct ast_framehook::@357 list
int detach_and_destroy_me
Definition: framehook.c:44

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::chan, 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_framehook(), remove_hold_intercept(), t38_attach_framehook(), t38_masq(), and transfer_target_framehook_cb().

◆ 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
0not empty
1is empty (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.

283{
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

References ast_framehook_list_contains_no_active_of_type().

Referenced by ast_channel_has_audio_frame_or_monitor().

◆ 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
typetype of frame
Return values
0not empty
1is empty (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.

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
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:450
ast_framehook_consume_callback consume_cb
Definition: framehook.h:240
struct ast_framehook_list::@358 list

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, ast_framehook_list::list, and type.

Referenced by ast_channel_has_hook_requiring_audio(), and ast_framehook_list_contains_no_active().

◆ 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.

207{
208 struct ast_framehook *framehook;
209
211 return 0;
212 }
216 }
220 return 0;
221}
static void framehook_detach(struct ast_framehook *framehook, enum framehook_detachment_mode mode)
Definition: framehook.c:66
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557

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

Referenced by destroy_hooks().

◆ 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.

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
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}
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
int ast_framehook_detach(struct ast_channel *chan, int id)
Detach an framehook from a channel.
Definition: framehook.c:177
#define LOG_WARNING
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
ast_framehook_chan_fixup_callback chan_fixup_cb
Definition: framehook.h:244
ast_framehook_chan_fixup_callback chan_breakdown_cb
Definition: framehook.h:248

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().

◆ 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
0not empty
1is empty

Definition at line 274 of file framehook.c.

275{
276 if (!framehooks) {
277 return 1;
278 }
279 return AST_LIST_EMPTY(&framehooks->list) ? 1 : 0;
280}

References AST_LIST_EMPTY, and ast_framehook_list::list.

Referenced by ast_indicate_data().

◆ 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.

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_EVENT_READ
Definition: framehook.h:152

References AST_FRAMEHOOK_EVENT_READ, and framehook_list_push_event().

Referenced by __ast_read().

◆ 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.

314{
315 return framehook_list_push_event(framehooks, frame, AST_FRAMEHOOK_EVENT_WRITE);
316}
@ AST_FRAMEHOOK_EVENT_WRITE
Definition: framehook.h:153

References AST_FRAMEHOOK_EVENT_WRITE, and framehook_list_push_event().

Referenced by ast_indicate_data(), and ast_write_stream().

◆ framehook_detach()

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

Definition at line 66 of file framehook.c.

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_DETACHED
Definition: framehook.h:155
ast_framehook_destroy_callback destroy_cb
Definition: framehook.h:236

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().

◆ 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.

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}
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
Definition: astman.c:222

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, and ast_framehook_list::list.

Referenced by ast_framehook_list_read_event(), and ast_framehook_list_write_event().