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
00098
00099
00100
00101
00102
00103 static struct audiohook_inheritance_datastore *setup_inheritance_datastore(struct ast_channel *chan)
00104 {
00105 struct ast_datastore *datastore = NULL;
00106 struct audiohook_inheritance_datastore *audiohook_inheritance_datastore = NULL;
00107
00108 if (!(datastore = ast_channel_datastore_alloc(&audiohook_inheritance_info, NULL))) {
00109 return NULL;
00110 }
00111
00112 if (!(audiohook_inheritance_datastore = ast_calloc(1, sizeof(*audiohook_inheritance_datastore)))) {
00113 ast_channel_datastore_free(datastore);
00114 return NULL;
00115 }
00116
00117 datastore->data = audiohook_inheritance_datastore;
00118 ast_channel_lock(chan);
00119 ast_channel_datastore_add(chan, datastore);
00120 ast_channel_unlock(chan);
00121 return audiohook_inheritance_datastore;
00122 }
00123
00124
00125
00126
00127
00128
00129
00130
00131 static int setup_inheritable_audiohook(struct audiohook_inheritance_datastore *audiohook_inheritance_datastore, const char *source)
00132 {
00133 struct inheritable_audiohook *inheritable_audiohook = NULL;
00134
00135 inheritable_audiohook = ast_calloc(1, sizeof(*inheritable_audiohook) + strlen(source));
00136
00137 if (!inheritable_audiohook) {
00138 return -1;
00139 }
00140
00141 strcpy(inheritable_audiohook->source, source);
00142 AST_LIST_INSERT_TAIL(&audiohook_inheritance_datastore->allowed_list, inheritable_audiohook, list);
00143 if (option_debug > 2) {
00144 ast_log(LOG_DEBUG, "Set audiohook %s to be inheritable\n", source);
00145 }
00146 return 0;
00147 }
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 static int func_inheritance_write(struct ast_channel *chan, char *function, char *data, const char *value)
00159 {
00160 int allow;
00161 struct ast_datastore *datastore = NULL;
00162 struct audiohook_inheritance_datastore *inheritance_datastore = NULL;
00163 struct inheritable_audiohook *inheritable_audiohook;
00164
00165
00166 if (ast_strlen_zero(data)) {
00167 ast_log(LOG_WARNING, "No argument provided to INHERITANCE function.\n");
00168 return -1;
00169 }
00170
00171 if (ast_strlen_zero(value)) {
00172 ast_log(LOG_WARNING, "No value provided to INHERITANCE function.\n");
00173 return -1;
00174 }
00175
00176 allow = ast_true(value);
00177
00178
00179 ast_channel_lock(chan);
00180 if (!(datastore = ast_channel_datastore_find(chan, &audiohook_inheritance_info, NULL))) {
00181 ast_channel_unlock(chan);
00182
00183 if (!allow) {
00184 if (option_debug) {
00185 ast_log(LOG_DEBUG, "Audiohook %s is already set to not be inheritable on channel %s\n", data, chan->name);
00186 }
00187 return 0;
00188 } else if (!(inheritance_datastore = setup_inheritance_datastore(chan))) {
00189 ast_log(LOG_WARNING, "Unable to set up audiohook inheritance datastore on channel %s\n", chan->name);
00190 return -1;
00191 } else {
00192 return setup_inheritable_audiohook(inheritance_datastore, data);
00193 }
00194 } else {
00195 inheritance_datastore = datastore->data;
00196 }
00197 ast_channel_unlock(chan);
00198
00199
00200
00201 AST_LIST_TRAVERSE_SAFE_BEGIN(&inheritance_datastore->allowed_list, inheritable_audiohook, list) {
00202 if (!strcasecmp(inheritable_audiohook->source, data)) {
00203 if (allow) {
00204 if (option_debug > 1) {
00205 ast_log(LOG_DEBUG, "Audiohook source %s is already set up to be inherited from channel %s\n", data, chan->name);
00206 }
00207 return 0;
00208 } else {
00209 if (option_debug > 1) {
00210 ast_log(LOG_DEBUG, "Removing inheritability of audiohook %s from channel %s\n", data, chan->name);
00211 }
00212 AST_LIST_REMOVE_CURRENT(&inheritance_datastore->allowed_list, list);
00213 ast_free(inheritable_audiohook);
00214 return 0;
00215 }
00216 }
00217 }
00218 AST_LIST_TRAVERSE_SAFE_END;
00219
00220
00221
00222
00223
00224
00225
00226 if (allow) {
00227 return setup_inheritable_audiohook(inheritance_datastore, data);
00228 } else {
00229 if (option_debug) {
00230 ast_log(LOG_DEBUG, "Audiohook %s is already set to not be inheritable on channel %s\n", data, chan->name);
00231 }
00232 return 0;
00233 }
00234 }
00235
00236 static struct ast_custom_function inheritance_function = {
00237 .name = "AUDIOHOOK_INHERIT",
00238 .synopsis = "Set whether an audiohook may be inherited to another channel",
00239 .syntax = "AUDIOHOOK_INHERIT(source)",
00240 .desc =
00241 "By enabling audiohook inheritance on the channel, you are giving\n"
00242 "permission for an audiohook to be inherited by a descendent channel.\n"
00243 "Inheritance may be be disabled at any point as well.\n"
00244 "\n"
00245 " Example scenario:\n"
00246 " exten => 2000,1,MixMonitor(blah.wav)\n"
00247 " exten => 2000,n,Set(AUDIOHOOK_INHERIT(MixMonitor)=yes)\n"
00248 " exten => 2000,n,Dial(SIP/2000)\n"
00249 "\n"
00250 " exten => 4000,1,Dial(SIP/4000)\n"
00251 "\n"
00252 " exten => 5000,1,MixMonitor(blah2.wav)\n"
00253 " exten => 5000,n,Dial(SIP/5000)\n"
00254 "\n"
00255 " In this basic dialplan scenario, let's consider the following sample calls\n"
00256 " Call 1: Caller dials 2000. The person who answers then executes an attended\n"
00257 " transfer to 4000.\n"
00258 " Result: Since extension 2000 set MixMonitor to be inheritable, after the\n"
00259 " transfer to 400 has completed, the call will continue to be recorded\n"
00260 " to blah.wav\n"
00261 "\n"
00262 " Call 2: Caller dials 5000. The person who answers then executes an attended\n"
00263 " transfer to 4000.\n"
00264 " Result: Since extension 5000 did not set MixMonitor to be inheritable, the\n"
00265 " recording will stop once the call has been transferred to 4000.\n",
00266 .write = func_inheritance_write,
00267 };
00268
00269 static int unload_module(void)
00270 {
00271 return ast_custom_function_unregister(&inheritance_function);
00272 }
00273
00274 static int load_module(void)
00275 {
00276 if (ast_custom_function_register(&inheritance_function)) {
00277 return AST_MODULE_LOAD_DECLINE;
00278 } else {
00279 return AST_MODULE_LOAD_SUCCESS;
00280 }
00281 }
00282 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Audiohook inheritance function");