Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "asterisk.h"
00031
00032 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 369013 $")
00033
00034 #include "asterisk/channel.h"
00035 #include "asterisk/linkedlists.h"
00036 #include "asterisk/framehook.h"
00037 #include "asterisk/frame.h"
00038
00039 struct ast_framehook {
00040 struct ast_framehook_interface i;
00041
00042 struct ast_channel *chan;
00043
00044 unsigned int id;
00045
00046 int detach_and_destroy_me;
00047
00048 AST_LIST_ENTRY(ast_framehook) list;
00049 };
00050
00051 struct ast_framehook_list {
00052 unsigned int id_count;
00053 AST_LIST_HEAD_NOLOCK(, ast_framehook) list;
00054 };
00055
00056 static void framehook_detach_and_destroy(struct ast_framehook *framehook)
00057 {
00058 struct ast_frame *frame;
00059 frame = framehook->i.event_cb(framehook->chan, NULL, AST_FRAMEHOOK_EVENT_DETACHED, framehook->i.data);
00060
00061
00062 if (frame) {
00063 ast_frfree(frame);
00064 }
00065 framehook->chan = NULL;
00066
00067 if (framehook->i.destroy_cb) {
00068 framehook->i.destroy_cb(framehook->i.data);
00069 }
00070 ast_free(framehook);
00071 }
00072
00073 static struct ast_frame *framehook_list_push_event(struct ast_framehook_list *framehooks, struct ast_frame *frame, enum ast_framehook_event event)
00074 {
00075 struct ast_framehook *framehook;
00076
00077 if (!framehooks) {
00078 return frame;
00079 }
00080
00081 AST_LIST_TRAVERSE_SAFE_BEGIN(&framehooks->list, framehook, list) {
00082 if (framehook->detach_and_destroy_me) {
00083
00084 AST_LIST_REMOVE_CURRENT(list);
00085 framehook_detach_and_destroy(framehook);
00086 } else {
00087 frame = framehook->i.event_cb(framehook->chan, frame, event, framehook->i.data);
00088 }
00089 }
00090 AST_LIST_TRAVERSE_SAFE_END;
00091 return frame;
00092 }
00093
00094 int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interface *i)
00095 {
00096 struct ast_framehook *framehook;
00097 struct ast_framehook_list *fh_list;
00098 struct ast_frame *frame;
00099 if (i->version != AST_FRAMEHOOK_INTERFACE_VERSION) {
00100 ast_log(LOG_ERROR, "Version '%hu' of framehook interface not what we compiled against (%hu)\n",
00101 i->version, AST_FRAMEHOOK_INTERFACE_VERSION);
00102 return -1;
00103 }
00104 if (!i->event_cb || !(framehook = ast_calloc(1, sizeof(*framehook)))) {
00105 return -1;
00106 }
00107 framehook->i = *i;
00108 framehook->chan = chan;
00109
00110
00111 if (!ast_channel_framehooks(chan)) {
00112 if (!(fh_list = ast_calloc(1, sizeof(*ast_channel_framehooks(chan))))) {
00113 ast_free(framehook);
00114 return -1;
00115 }
00116 ast_channel_framehooks_set(chan, fh_list);
00117 }
00118
00119 framehook->id = ++ast_channel_framehooks(chan)->id_count;
00120 AST_LIST_INSERT_TAIL(&ast_channel_framehooks(chan)->list, framehook, list);
00121
00122
00123 frame = framehook->i.event_cb(framehook->chan, NULL, AST_FRAMEHOOK_EVENT_ATTACHED, framehook->i.data);
00124
00125
00126
00127 if (frame) {
00128 ast_frfree(frame);
00129 }
00130
00131 return framehook->id;
00132 }
00133
00134 int ast_framehook_detach(struct ast_channel *chan, int id)
00135 {
00136 struct ast_framehook *framehook;
00137 int res = -1;
00138
00139 if (!ast_channel_framehooks(chan)) {
00140 return res;
00141 }
00142
00143 AST_LIST_TRAVERSE_SAFE_BEGIN(&ast_channel_framehooks(chan)->list, framehook, list) {
00144 if (framehook->id == id) {
00145
00146
00147
00148
00149 framehook->detach_and_destroy_me = 1;
00150 res = 0;
00151 break;
00152 }
00153 }
00154 AST_LIST_TRAVERSE_SAFE_END;
00155
00156 return res;
00157 }
00158
00159 int ast_framehook_list_destroy(struct ast_channel *chan)
00160 {
00161 struct ast_framehook *framehook;
00162
00163 if (!ast_channel_framehooks(chan)) {
00164 return 0;
00165 }
00166 AST_LIST_TRAVERSE_SAFE_BEGIN(&ast_channel_framehooks(chan)->list, framehook, list) {
00167 AST_LIST_REMOVE_CURRENT(list);
00168 framehook_detach_and_destroy(framehook);
00169 }
00170 AST_LIST_TRAVERSE_SAFE_END;
00171 ast_free(ast_channel_framehooks(chan));
00172 ast_channel_framehooks_set(chan, NULL);
00173 return 0;
00174 }
00175
00176 int ast_framehook_list_is_empty(struct ast_framehook_list *framehooks)
00177 {
00178 if (!framehooks) {
00179 return 1;
00180 }
00181 return AST_LIST_EMPTY(&framehooks->list) ? 1 : 0;
00182 }
00183
00184 struct ast_frame *ast_framehook_list_write_event(struct ast_framehook_list *framehooks, struct ast_frame *frame)
00185 {
00186 return framehook_list_push_event(framehooks, frame, AST_FRAMEHOOK_EVENT_WRITE);
00187 }
00188
00189 struct ast_frame *ast_framehook_list_read_event(struct ast_framehook_list *framehooks, struct ast_frame *frame)
00190 {
00191 return framehook_list_push_event(framehooks, frame, AST_FRAMEHOOK_EVENT_READ);
00192 }