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: 369001 $")
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_frame *frame;
00098 if (i->version != AST_FRAMEHOOK_INTERFACE_VERSION) {
00099 ast_log(LOG_ERROR, "Version '%hu' of framehook interface not what we compiled against (%hu)\n",
00100 i->version, AST_FRAMEHOOK_INTERFACE_VERSION);
00101 return -1;
00102 }
00103 if (!i->event_cb || !(framehook = ast_calloc(1, sizeof(*framehook)))) {
00104 return -1;
00105 }
00106 framehook->i = *i;
00107 framehook->chan = chan;
00108
00109
00110 if (!chan->framehooks && !(chan->framehooks = ast_calloc(1, sizeof(*chan->framehooks)))) {
00111 ast_free(framehook);
00112 return -1;
00113 }
00114
00115 framehook->id = ++chan->framehooks->id_count;
00116 AST_LIST_INSERT_TAIL(&chan->framehooks->list, framehook, list);
00117
00118
00119 frame = framehook->i.event_cb(framehook->chan, NULL, AST_FRAMEHOOK_EVENT_ATTACHED, framehook->i.data);
00120
00121
00122
00123 if (frame) {
00124 ast_frfree(frame);
00125 }
00126
00127 return framehook->id;
00128 }
00129
00130 int ast_framehook_detach(struct ast_channel *chan, int id)
00131 {
00132 struct ast_framehook *framehook;
00133 int res = -1;
00134
00135 if (!chan->framehooks) {
00136 return res;
00137 }
00138
00139 AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->framehooks->list, framehook, list) {
00140 if (framehook->id == id) {
00141
00142
00143
00144
00145 framehook->detach_and_destroy_me = 1;
00146 res = 0;
00147 break;
00148 }
00149 }
00150 AST_LIST_TRAVERSE_SAFE_END;
00151
00152 return res;
00153 }
00154
00155 int ast_framehook_list_destroy(struct ast_channel *chan)
00156 {
00157 struct ast_framehook *framehook;
00158
00159 if (!chan->framehooks) {
00160 return 0;
00161 }
00162 AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->framehooks->list, framehook, list) {
00163 AST_LIST_REMOVE_CURRENT(list);
00164 framehook_detach_and_destroy(framehook);
00165 }
00166 AST_LIST_TRAVERSE_SAFE_END;
00167 ast_free(chan->framehooks);
00168 chan->framehooks = NULL;
00169 return 0;
00170 }
00171
00172 int ast_framehook_list_is_empty(struct ast_framehook_list *framehooks)
00173 {
00174 if (!framehooks) {
00175 return 1;
00176 }
00177 return AST_LIST_EMPTY(&framehooks->list) ? 1 : 0;
00178 }
00179
00180 struct ast_frame *ast_framehook_list_write_event(struct ast_framehook_list *framehooks, struct ast_frame *frame)
00181 {
00182 return framehook_list_push_event(framehooks, frame, AST_FRAMEHOOK_EVENT_WRITE);
00183 }
00184
00185 struct ast_frame *ast_framehook_list_read_event(struct ast_framehook_list *framehooks, struct ast_frame *frame)
00186 {
00187 return framehook_list_push_event(framehooks, frame, AST_FRAMEHOOK_EVENT_READ);
00188 }