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
00031 #include "asterisk.h"
00032 #include "asterisk/channel.h"
00033 #include "asterisk/audiohook.h"
00034 #include "asterisk/pbx.h"
00035 #include "asterisk/module.h"
00036 #include "asterisk/options.h"
00037
00038 struct inheritable_audiohook {
00039 AST_LIST_ENTRY(inheritable_audiohook) list;
00040 char source[1];
00041 };
00042
00043 struct audiohook_inheritance_datastore {
00044 AST_LIST_HEAD (, inheritable_audiohook) allowed_list;
00045 };
00046
00047 static void audiohook_inheritance_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan);
00048 static void audiohook_inheritance_destroy (void *data);
00049 static const struct ast_datastore_info audiohook_inheritance_info = {
00050 .type = "audiohook inheritance",
00051 .destroy = audiohook_inheritance_destroy,
00052 .chan_fixup = audiohook_inheritance_fixup,
00053 };
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 static void audiohook_inheritance_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
00065 {
00066 struct inheritable_audiohook *audiohook = NULL;
00067 struct audiohook_inheritance_datastore *datastore = data;
00068
00069 if (option_debug > 1) {
00070 ast_log(LOG_DEBUG, "inheritance fixup occurring for channels %s(%p) and %s(%p)", old_chan->name, old_chan, new_chan->name, new_chan);
00071 }
00072
00073 AST_LIST_TRAVERSE(&datastore->allowed_list, audiohook, list) {
00074 ast_audiohook_move_by_source(old_chan, new_chan, audiohook->source);
00075 if (option_debug > 2) {
00076 ast_log(LOG_DEBUG, "Moved audiohook %s from %s(%p) to %s(%p)\n",
00077 audiohook->source, old_chan->name, old_chan, new_chan->name, new_chan);
00078 }
00079 }
00080 return;
00081 }
00082
00083
00084
00085
00086
00087
00088 static void audiohook_inheritance_destroy(void *data)
00089 {
00090 struct audiohook_inheritance_datastore *audiohook_inheritance_datastore = data;
00091 struct inheritable_audiohook *inheritable_audiohook = NULL;
00092
00093 while ((inheritable_audiohook = AST_LIST_REMOVE_HEAD(&audiohook_inheritance_datastore->allowed_list, list))) {
00094 ast_free(inheritable_audiohook);
00095 }
00096
00097 ast_free(audiohook_inheritance_datastore);
00098 }
00099
00100
00101
00102
00103
00104
00105 static struct audiohook_inheritance_datastore *setup_inheritance_datastore(struct ast_channel *chan)
00106 {
00107 struct ast_datastore *datastore = NULL;
00108 struct audiohook_inheritance_datastore *audiohook_inheritance_datastore = NULL;
00109
00110 if (!(datastore = ast_channel_datastore_alloc(&audiohook_inheritance_info, NULL))) {
00111 return NULL;
00112 }
00113
00114 if (!(audiohook_inheritance_datastore = ast_calloc(1, sizeof(*audiohook_inheritance_datastore)))) {
00115 ast_channel_datastore_free(datastore);
00116 return NULL;
00117 }
00118
00119 datastore->data = audiohook_inheritance_datastore;
00120 ast_channel_lock(chan);
00121 ast_channel_datastore_add(chan, datastore);
00122 ast_channel_unlock(chan);
00123 return audiohook_inheritance_datastore;
00124 }
00125
00126
00127
00128
00129
00130
00131
00132
00133 static int setup_inheritable_audiohook(struct audiohook_inheritance_datastore *audiohook_inheritance_datastore, const char *source)
00134 {
00135 struct inheritable_audiohook *inheritable_audiohook = NULL;
00136
00137 inheritable_audiohook = ast_calloc(1, sizeof(*inheritable_audiohook) + strlen(source));
00138
00139 if (!inheritable_audiohook) {
00140 return -1;
00141 }
00142
00143 strcpy(inheritable_audiohook->source, source);
00144 AST_LIST_INSERT_TAIL(&audiohook_inheritance_datastore->allowed_list, inheritable_audiohook, list);
00145 if (option_debug > 2) {
00146 ast_log(LOG_DEBUG, "Set audiohook %s to be inheritable\n", source);
00147 }
00148 return 0;
00149 }
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 static int func_inheritance_write(struct ast_channel *chan, char *function, char *data, const char *value)
00161 {
00162 int allow;
00163 struct ast_datastore *datastore = NULL;
00164 struct audiohook_inheritance_datastore *inheritance_datastore = NULL;
00165 struct inheritable_audiohook *inheritable_audiohook;
00166
00167
00168 if (ast_strlen_zero(data)) {
00169 ast_log(LOG_WARNING, "No argument provided to INHERITANCE function.\n");
00170 return -1;
00171 }
00172
00173 if (ast_strlen_zero(value)) {
00174 ast_log(LOG_WARNING, "No value provided to INHERITANCE function.\n");
00175 return -1;
00176 }
00177
00178 allow = ast_true(value);
00179
00180
00181 ast_channel_lock(chan);
00182 if (!(datastore = ast_channel_datastore_find(chan, &audiohook_inheritance_info, NULL))) {
00183 ast_channel_unlock(chan);
00184
00185 if (!allow) {
00186 if (option_debug) {
00187 ast_log(LOG_DEBUG, "Audiohook %s is already set to not be inheritable on channel %s\n", data, chan->name);
00188 }
00189 return 0;
00190 } else if (!(inheritance_datastore = setup_inheritance_datastore(chan))) {
00191 ast_log(LOG_WARNING, "Unable to set up audiohook inheritance datastore on channel %s\n", chan->name);
00192 return -1;
00193 } else {
00194 return setup_inheritable_audiohook(inheritance_datastore, data);
00195 }
00196 } else {
00197 inheritance_datastore = datastore->data;
00198 }
00199 ast_channel_unlock(chan);
00200
00201
00202
00203 AST_LIST_TRAVERSE_SAFE_BEGIN(&inheritance_datastore->allowed_list, inheritable_audiohook, list) {
00204 if (!strcasecmp(inheritable_audiohook->source, data)) {
00205 if (allow) {
00206 if (option_debug > 1) {
00207 ast_log(LOG_DEBUG, "Audiohook source %s is already set up to be inherited from channel %s\n", data, chan->name);
00208 }
00209 return 0;
00210 } else {
00211 if (option_debug > 1) {
00212 ast_log(LOG_DEBUG, "Removing inheritability of audiohook %s from channel %s\n", data, chan->name);
00213 }
00214 AST_LIST_REMOVE_CURRENT(&inheritance_datastore->allowed_list, list);
00215 ast_free(inheritable_audiohook);
00216 return 0;
00217 }
00218 }
00219 }
00220 AST_LIST_TRAVERSE_SAFE_END;
00221
00222
00223
00224
00225
00226
00227
00228 if (allow) {
00229 return setup_inheritable_audiohook(inheritance_datastore, data);
00230 } else {
00231 if (option_debug) {
00232 ast_log(LOG_DEBUG, "Audiohook %s is already set to not be inheritable on channel %s\n", data, chan->name);
00233 }
00234 return 0;
00235 }
00236 }
00237
00238 static struct ast_custom_function inheritance_function = {
00239 .name = "AUDIOHOOK_INHERIT",
00240 .synopsis = "Set whether an audiohook may be inherited to another channel",
00241 .syntax = "AUDIOHOOK_INHERIT(source)",
00242 .desc =
00243 "By enabling audiohook inheritance on the channel, you are giving\n"
00244 "permission for an audiohook to be inherited by a descendent channel.\n"
00245 "Inheritance may be be disabled at any point as well.\n"
00246 "\n"
00247 " Example scenario:\n"
00248 " exten => 2000,1,MixMonitor(blah.wav)\n"
00249 " exten => 2000,n,Set(AUDIOHOOK_INHERIT(MixMonitor)=yes)\n"
00250 " exten => 2000,n,Dial(SIP/2000)\n"
00251 "\n"
00252 " exten => 4000,1,Dial(SIP/4000)\n"
00253 "\n"
00254 " exten => 5000,1,MixMonitor(blah2.wav)\n"
00255 " exten => 5000,n,Dial(SIP/5000)\n"
00256 "\n"
00257 " In this basic dialplan scenario, let's consider the following sample calls\n"
00258 " Call 1: Caller dials 2000. The person who answers then executes an attended\n"
00259 " transfer to 4000.\n"
00260 " Result: Since extension 2000 set MixMonitor to be inheritable, after the\n"
00261 " transfer to 400 has completed, the call will continue to be recorded\n"
00262 " to blah.wav\n"
00263 "\n"
00264 " Call 2: Caller dials 5000. The person who answers then executes an attended\n"
00265 " transfer to 4000.\n"
00266 " Result: Since extension 5000 did not set MixMonitor to be inheritable, the\n"
00267 " recording will stop once the call has been transferred to 4000.\n",
00268 .write = func_inheritance_write,
00269 };
00270
00271 static int unload_module(void)
00272 {
00273 return ast_custom_function_unregister(&inheritance_function);
00274 }
00275
00276 static int load_module(void)
00277 {
00278 if (ast_custom_function_register(&inheritance_function)) {
00279 return AST_MODULE_LOAD_DECLINE;
00280 } else {
00281 return AST_MODULE_LOAD_SUCCESS;
00282 }
00283 }
00284 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Audiohook inheritance function");