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: 380854 $")
00033
00034 #include <sys/time.h>
00035 #include <signal.h>
00036
00037 #include "asterisk/channel.h"
00038 #include "asterisk/utils.h"
00039 #include "asterisk/lock.h"
00040 #include "asterisk/linkedlists.h"
00041 #include "asterisk/dial.h"
00042 #include "asterisk/pbx.h"
00043 #include "asterisk/musiconhold.h"
00044 #include "asterisk/app.h"
00045
00046
00047 struct ast_dial {
00048 int num;
00049 int timeout;
00050 int actual_timeout;
00051 enum ast_dial_result state;
00052 void *options[AST_DIAL_OPTION_MAX];
00053 ast_dial_state_callback state_callback;
00054 void *user_data;
00055 AST_LIST_HEAD(, ast_dial_channel) channels;
00056 pthread_t thread;
00057 struct ast_callid *callid;
00058 ast_mutex_t lock;
00059 };
00060
00061
00062 struct ast_dial_channel {
00063 int num;
00064 int timeout;
00065 char *tech;
00066 char *device;
00067 void *options[AST_DIAL_OPTION_MAX];
00068 int cause;
00069 unsigned int is_running_app:1;
00070 struct ast_channel *owner;
00071 AST_LIST_ENTRY(ast_dial_channel) list;
00072 };
00073
00074
00075 typedef void *(*ast_dial_option_cb_enable)(void *data);
00076
00077
00078 typedef int (*ast_dial_option_cb_disable)(void *data);
00079
00080
00081 struct answer_exec_struct {
00082 char app[AST_MAX_APP];
00083 char *args;
00084 };
00085
00086
00087 static void *answer_exec_enable(void *data)
00088 {
00089 struct answer_exec_struct *answer_exec = NULL;
00090 char *app = ast_strdupa((char*)data), *args = NULL;
00091
00092
00093 if (ast_strlen_zero(app))
00094 return NULL;
00095
00096
00097 if (!(answer_exec = ast_calloc(1, sizeof(*answer_exec))))
00098 return NULL;
00099
00100
00101 if ((args = strchr(app, ','))) {
00102 *args++ = '\0';
00103 answer_exec->args = ast_strdup(args);
00104 }
00105
00106
00107 ast_copy_string(answer_exec->app, app, sizeof(answer_exec->app));
00108
00109 return answer_exec;
00110 }
00111
00112
00113 static int answer_exec_disable(void *data)
00114 {
00115 struct answer_exec_struct *answer_exec = data;
00116
00117
00118 if (!answer_exec)
00119 return -1;
00120
00121
00122 if (answer_exec->args)
00123 ast_free(answer_exec->args);
00124
00125
00126 ast_free(answer_exec);
00127
00128 return 0;
00129 }
00130
00131 static void *music_enable(void *data)
00132 {
00133 return ast_strdup(data);
00134 }
00135
00136 static int music_disable(void *data)
00137 {
00138 if (!data)
00139 return -1;
00140
00141 ast_free(data);
00142
00143 return 0;
00144 }
00145
00146
00147 static void answer_exec_run(struct ast_dial *dial, struct ast_dial_channel *dial_channel, char *app, char *args)
00148 {
00149 struct ast_channel *chan = dial_channel->owner;
00150 struct ast_app *ast_app = pbx_findapp(app);
00151
00152
00153 if (!ast_app)
00154 return;
00155
00156
00157 pbx_exec(chan, ast_app, args);
00158
00159
00160 ast_mutex_lock(&dial->lock);
00161 if (dial->thread != AST_PTHREADT_STOP) {
00162 ast_hangup(chan);
00163 dial_channel->owner = NULL;
00164 }
00165 ast_mutex_unlock(&dial->lock);
00166
00167 return;
00168 }
00169
00170 struct ast_option_types {
00171 enum ast_dial_option option;
00172 ast_dial_option_cb_enable enable;
00173 ast_dial_option_cb_disable disable;
00174 };
00175
00176
00177
00178
00179
00180
00181
00182 static const struct ast_option_types option_types[] = {
00183 { AST_DIAL_OPTION_RINGING, NULL, NULL },
00184 { AST_DIAL_OPTION_ANSWER_EXEC, answer_exec_enable, answer_exec_disable },
00185 { AST_DIAL_OPTION_MUSIC, music_enable, music_disable },
00186 { AST_DIAL_OPTION_DISABLE_CALL_FORWARDING, NULL, NULL },
00187 { AST_DIAL_OPTION_MAX, NULL, NULL },
00188 };
00189
00190
00191 #define AST_MAX_WATCHERS 256
00192
00193
00194 #define FIND_RELATIVE_OPTION(dial, dial_channel, ast_dial_option) (dial_channel->options[ast_dial_option] ? dial_channel->options[ast_dial_option] : dial->options[ast_dial_option])
00195
00196
00197 #define IS_CALLER(chan, owner) (chan == owner ? 1 : 0)
00198
00199
00200
00201
00202
00203 struct ast_dial *ast_dial_create(void)
00204 {
00205 struct ast_dial *dial = NULL;
00206
00207
00208 if (!(dial = ast_calloc(1, sizeof(*dial))))
00209 return NULL;
00210
00211
00212 AST_LIST_HEAD_INIT(&dial->channels);
00213
00214
00215 dial->thread = AST_PTHREADT_NULL;
00216
00217
00218 dial->timeout = -1;
00219 dial->actual_timeout = -1;
00220
00221
00222 ast_mutex_init(&dial->lock);
00223
00224 return dial;
00225 }
00226
00227
00228
00229
00230
00231 int ast_dial_append(struct ast_dial *dial, const char *tech, const char *device)
00232 {
00233 struct ast_dial_channel *channel = NULL;
00234
00235
00236 if (!dial || !tech || !device)
00237 return -1;
00238
00239
00240 if (!(channel = ast_calloc(1, sizeof(*channel))))
00241 return -1;
00242
00243
00244 channel->tech = ast_strdup(tech);
00245 channel->device = ast_strdup(device);
00246
00247
00248 channel->num = ast_atomic_fetchadd_int(&dial->num, +1);
00249
00250
00251 channel->timeout = -1;
00252
00253
00254 AST_LIST_INSERT_TAIL(&dial->channels, channel, list);
00255
00256 return channel->num;
00257 }
00258
00259
00260 static int begin_dial_channel(struct ast_dial_channel *channel, struct ast_channel *chan)
00261 {
00262 char numsubst[AST_MAX_EXTENSION];
00263 int res = 1;
00264 struct ast_format_cap *cap_all_audio = NULL;
00265 struct ast_format_cap *cap_request;
00266
00267
00268 ast_copy_string(numsubst, channel->device, sizeof(numsubst));
00269
00270 if (chan) {
00271 cap_request = ast_channel_nativeformats(chan);
00272 } else {
00273 cap_all_audio = ast_format_cap_alloc_nolock();
00274 ast_format_cap_add_all_by_type(cap_all_audio, AST_FORMAT_TYPE_AUDIO);
00275 cap_request = cap_all_audio;
00276 }
00277
00278
00279 if (!(channel->owner = ast_request(channel->tech, cap_request, chan, numsubst, &channel->cause))) {
00280 cap_all_audio = ast_format_cap_destroy(cap_all_audio);
00281 return -1;
00282 }
00283 cap_request = NULL;
00284 cap_all_audio = ast_format_cap_destroy(cap_all_audio);
00285
00286 ast_channel_appl_set(channel->owner, "AppDial2");
00287 ast_channel_data_set(channel->owner, "(Outgoing Line)");
00288 memset(ast_channel_whentohangup(channel->owner), 0, sizeof(*ast_channel_whentohangup(channel->owner)));
00289
00290
00291 if (chan) {
00292 ast_channel_inherit_variables(chan, channel->owner);
00293 ast_channel_datastore_inherit(chan, channel->owner);
00294
00295
00296 ast_party_redirecting_copy(ast_channel_redirecting(channel->owner), ast_channel_redirecting(chan));
00297
00298 ast_channel_dialed(channel->owner)->transit_network_select = ast_channel_dialed(chan)->transit_network_select;
00299
00300 ast_connected_line_copy_from_caller(ast_channel_connected(channel->owner), ast_channel_caller(chan));
00301
00302 ast_channel_language_set(channel->owner, ast_channel_language(chan));
00303 ast_channel_accountcode_set(channel->owner, ast_channel_accountcode(chan));
00304 if (ast_strlen_zero(ast_channel_musicclass(channel->owner)))
00305 ast_channel_musicclass_set(channel->owner, ast_channel_musicclass(chan));
00306
00307 ast_channel_adsicpe_set(channel->owner, ast_channel_adsicpe(chan));
00308 ast_channel_transfercapability_set(channel->owner, ast_channel_transfercapability(chan));
00309 }
00310
00311
00312 if ((res = ast_call(channel->owner, numsubst, 0))) {
00313 res = 0;
00314 ast_hangup(channel->owner);
00315 channel->owner = NULL;
00316 } else {
00317 if (chan)
00318 ast_poll_channel_add(chan, channel->owner);
00319 res = 1;
00320 ast_verb(3, "Called %s\n", numsubst);
00321 }
00322
00323 return res;
00324 }
00325
00326
00327 static int begin_dial(struct ast_dial *dial, struct ast_channel *chan)
00328 {
00329 struct ast_dial_channel *channel = NULL;
00330 int success = 0;
00331
00332
00333 AST_LIST_LOCK(&dial->channels);
00334 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
00335 success += begin_dial_channel(channel, chan);
00336 }
00337 AST_LIST_UNLOCK(&dial->channels);
00338
00339
00340 return success;
00341 }
00342
00343
00344 static int handle_call_forward(struct ast_dial *dial, struct ast_dial_channel *channel, struct ast_channel *chan)
00345 {
00346 struct ast_channel *original = channel->owner;
00347 char *tmp = ast_strdupa(ast_channel_call_forward(channel->owner));
00348 char *tech = "Local", *device = tmp, *stuff;
00349
00350
00351 if (FIND_RELATIVE_OPTION(dial, channel, AST_DIAL_OPTION_DISABLE_CALL_FORWARDING)) {
00352 ast_hangup(original);
00353 channel->owner = NULL;
00354 return 0;
00355 }
00356
00357
00358 if ((stuff = strchr(tmp, '/'))) {
00359 *stuff++ = '\0';
00360 tech = tmp;
00361 device = stuff;
00362 }
00363
00364
00365 ast_free(channel->tech);
00366 ast_free(channel->device);
00367
00368
00369 channel->tech = ast_strdup(tech);
00370 channel->device = ast_strdup(device);
00371 AST_LIST_UNLOCK(&dial->channels);
00372
00373
00374 begin_dial_channel(channel, chan);
00375
00376
00377 ast_hangup(original);
00378
00379 return 0;
00380 }
00381
00382
00383 static struct ast_dial_channel *find_relative_dial_channel(struct ast_dial *dial, struct ast_channel *owner)
00384 {
00385 struct ast_dial_channel *channel = NULL;
00386
00387 AST_LIST_LOCK(&dial->channels);
00388 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
00389 if (channel->owner == owner)
00390 break;
00391 }
00392 AST_LIST_UNLOCK(&dial->channels);
00393
00394 return channel;
00395 }
00396
00397 static void set_state(struct ast_dial *dial, enum ast_dial_result state)
00398 {
00399 dial->state = state;
00400
00401 if (dial->state_callback)
00402 dial->state_callback(dial);
00403 }
00404
00405
00406 static void handle_frame(struct ast_dial *dial, struct ast_dial_channel *channel, struct ast_frame *fr, struct ast_channel *chan)
00407 {
00408 if (fr->frametype == AST_FRAME_CONTROL) {
00409 switch (fr->subclass.integer) {
00410 case AST_CONTROL_ANSWER:
00411 ast_verb(3, "%s answered %s\n", ast_channel_name(channel->owner), ast_channel_name(chan));
00412 AST_LIST_LOCK(&dial->channels);
00413 AST_LIST_REMOVE(&dial->channels, channel, list);
00414 AST_LIST_INSERT_HEAD(&dial->channels, channel, list);
00415 AST_LIST_UNLOCK(&dial->channels);
00416 set_state(dial, AST_DIAL_RESULT_ANSWERED);
00417 break;
00418 case AST_CONTROL_BUSY:
00419 ast_verb(3, "%s is busy\n", ast_channel_name(channel->owner));
00420 ast_hangup(channel->owner);
00421 channel->owner = NULL;
00422 break;
00423 case AST_CONTROL_CONGESTION:
00424 ast_verb(3, "%s is circuit-busy\n", ast_channel_name(channel->owner));
00425 ast_hangup(channel->owner);
00426 channel->owner = NULL;
00427 break;
00428 case AST_CONTROL_INCOMPLETE:
00429 ast_verb(3, "%s dialed Incomplete extension %s\n", ast_channel_name(channel->owner), ast_channel_exten(channel->owner));
00430 ast_indicate(chan, AST_CONTROL_INCOMPLETE);
00431 break;
00432 case AST_CONTROL_RINGING:
00433 ast_verb(3, "%s is ringing\n", ast_channel_name(channel->owner));
00434 if (!dial->options[AST_DIAL_OPTION_MUSIC])
00435 ast_indicate(chan, AST_CONTROL_RINGING);
00436 set_state(dial, AST_DIAL_RESULT_RINGING);
00437 break;
00438 case AST_CONTROL_PROGRESS:
00439 ast_verb(3, "%s is making progress, passing it to %s\n", ast_channel_name(channel->owner), ast_channel_name(chan));
00440 ast_indicate(chan, AST_CONTROL_PROGRESS);
00441 set_state(dial, AST_DIAL_RESULT_PROGRESS);
00442 break;
00443 case AST_CONTROL_VIDUPDATE:
00444 ast_verb(3, "%s requested a video update, passing it to %s\n", ast_channel_name(channel->owner), ast_channel_name(chan));
00445 ast_indicate(chan, AST_CONTROL_VIDUPDATE);
00446 break;
00447 case AST_CONTROL_SRCUPDATE:
00448 ast_verb(3, "%s requested a source update, passing it to %s\n", ast_channel_name(channel->owner), ast_channel_name(chan));
00449 ast_indicate(chan, AST_CONTROL_SRCUPDATE);
00450 break;
00451 case AST_CONTROL_CONNECTED_LINE:
00452 ast_verb(3, "%s connected line has changed, passing it to %s\n", ast_channel_name(channel->owner), ast_channel_name(chan));
00453 if (ast_channel_connected_line_sub(channel->owner, chan, fr, 1) &&
00454 ast_channel_connected_line_macro(channel->owner, chan, fr, 1, 1)) {
00455 ast_indicate_data(chan, AST_CONTROL_CONNECTED_LINE, fr->data.ptr, fr->datalen);
00456 }
00457 break;
00458 case AST_CONTROL_REDIRECTING:
00459 ast_verb(3, "%s redirecting info has changed, passing it to %s\n", ast_channel_name(channel->owner), ast_channel_name(chan));
00460 if (ast_channel_redirecting_sub(channel->owner, chan, fr, 1) &&
00461 ast_channel_redirecting_macro(channel->owner, chan, fr, 1, 1)) {
00462 ast_indicate_data(chan, AST_CONTROL_REDIRECTING, fr->data.ptr, fr->datalen);
00463 }
00464 break;
00465 case AST_CONTROL_PROCEEDING:
00466 ast_verb(3, "%s is proceeding, passing it to %s\n", ast_channel_name(channel->owner), ast_channel_name(chan));
00467 ast_indicate(chan, AST_CONTROL_PROCEEDING);
00468 set_state(dial, AST_DIAL_RESULT_PROCEEDING);
00469 break;
00470 case AST_CONTROL_HOLD:
00471 ast_verb(3, "Call on %s placed on hold\n", ast_channel_name(chan));
00472 ast_indicate(chan, AST_CONTROL_HOLD);
00473 break;
00474 case AST_CONTROL_UNHOLD:
00475 ast_verb(3, "Call on %s left from hold\n", ast_channel_name(chan));
00476 ast_indicate(chan, AST_CONTROL_UNHOLD);
00477 break;
00478 case AST_CONTROL_OFFHOOK:
00479 case AST_CONTROL_FLASH:
00480 break;
00481 case AST_CONTROL_PVT_CAUSE_CODE:
00482 ast_indicate_data(chan, AST_CONTROL_PVT_CAUSE_CODE, fr->data.ptr, fr->datalen);
00483 break;
00484 case -1:
00485
00486 ast_indicate(chan, -1);
00487 break;
00488 default:
00489 break;
00490 }
00491 }
00492
00493 return;
00494 }
00495
00496
00497 static void handle_frame_ownerless(struct ast_dial *dial, struct ast_dial_channel *channel, struct ast_frame *fr)
00498 {
00499
00500 if (fr->frametype != AST_FRAME_CONTROL)
00501 return;
00502
00503 switch (fr->subclass.integer) {
00504 case AST_CONTROL_ANSWER:
00505 ast_verb(3, "%s answered\n", ast_channel_name(channel->owner));
00506 AST_LIST_LOCK(&dial->channels);
00507 AST_LIST_REMOVE(&dial->channels, channel, list);
00508 AST_LIST_INSERT_HEAD(&dial->channels, channel, list);
00509 AST_LIST_UNLOCK(&dial->channels);
00510 set_state(dial, AST_DIAL_RESULT_ANSWERED);
00511 break;
00512 case AST_CONTROL_BUSY:
00513 ast_verb(3, "%s is busy\n", ast_channel_name(channel->owner));
00514 ast_hangup(channel->owner);
00515 channel->owner = NULL;
00516 break;
00517 case AST_CONTROL_CONGESTION:
00518 ast_verb(3, "%s is circuit-busy\n", ast_channel_name(channel->owner));
00519 ast_hangup(channel->owner);
00520 channel->owner = NULL;
00521 break;
00522 case AST_CONTROL_RINGING:
00523 ast_verb(3, "%s is ringing\n", ast_channel_name(channel->owner));
00524 set_state(dial, AST_DIAL_RESULT_RINGING);
00525 break;
00526 case AST_CONTROL_PROGRESS:
00527 ast_verb(3, "%s is making progress\n", ast_channel_name(channel->owner));
00528 set_state(dial, AST_DIAL_RESULT_PROGRESS);
00529 break;
00530 case AST_CONTROL_PROCEEDING:
00531 ast_verb(3, "%s is proceeding\n", ast_channel_name(channel->owner));
00532 set_state(dial, AST_DIAL_RESULT_PROCEEDING);
00533 break;
00534 default:
00535 break;
00536 }
00537
00538 return;
00539 }
00540
00541
00542 static int handle_timeout_trip(struct ast_dial *dial, struct timeval start)
00543 {
00544 struct ast_dial_channel *channel = NULL;
00545 int diff = ast_tvdiff_ms(ast_tvnow(), start), lowest_timeout = -1, new_timeout = -1;
00546
00547
00548 if (diff >= dial->timeout) {
00549 set_state(dial, AST_DIAL_RESULT_TIMEOUT);
00550 new_timeout = 0;
00551 }
00552
00553
00554 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
00555 if (dial->state == AST_DIAL_RESULT_TIMEOUT || diff >= channel->timeout) {
00556 ast_hangup(channel->owner);
00557 channel->owner = NULL;
00558 } else if ((lowest_timeout == -1) || (lowest_timeout > channel->timeout)) {
00559 lowest_timeout = channel->timeout;
00560 }
00561 }
00562
00563
00564 if (lowest_timeout >= 0)
00565 new_timeout = lowest_timeout - diff;
00566
00567 return new_timeout;
00568 }
00569
00570
00571 static enum ast_dial_result monitor_dial(struct ast_dial *dial, struct ast_channel *chan)
00572 {
00573 int timeout = -1;
00574 struct ast_channel *cs[AST_MAX_WATCHERS], *who = NULL;
00575 struct ast_dial_channel *channel = NULL;
00576 struct answer_exec_struct *answer_exec = NULL;
00577 struct timeval start;
00578
00579 set_state(dial, AST_DIAL_RESULT_TRYING);
00580
00581
00582 if (dial->options[AST_DIAL_OPTION_RINGING]) {
00583 set_state(dial, AST_DIAL_RESULT_RINGING);
00584 if (chan)
00585 ast_indicate(chan, AST_CONTROL_RINGING);
00586 } else if (chan && dial->options[AST_DIAL_OPTION_MUSIC] &&
00587 !ast_strlen_zero(dial->options[AST_DIAL_OPTION_MUSIC])) {
00588 char *original_moh = ast_strdupa(ast_channel_musicclass(chan));
00589 ast_indicate(chan, -1);
00590 ast_channel_musicclass_set(chan, dial->options[AST_DIAL_OPTION_MUSIC]);
00591 ast_moh_start(chan, dial->options[AST_DIAL_OPTION_MUSIC], NULL);
00592 ast_channel_musicclass_set(chan, original_moh);
00593 }
00594
00595
00596 start = ast_tvnow();
00597
00598
00599 timeout = dial->actual_timeout;
00600
00601
00602 while ((dial->state != AST_DIAL_RESULT_UNANSWERED) && (dial->state != AST_DIAL_RESULT_ANSWERED) && (dial->state != AST_DIAL_RESULT_HANGUP) && (dial->state != AST_DIAL_RESULT_TIMEOUT)) {
00603 int pos = 0, count = 0;
00604 struct ast_frame *fr = NULL;
00605
00606
00607 pos = count = 0;
00608 if (chan)
00609 cs[pos++] = chan;
00610
00611
00612 AST_LIST_LOCK(&dial->channels);
00613 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
00614 if (channel->owner) {
00615 cs[pos++] = channel->owner;
00616 count++;
00617 }
00618 }
00619 AST_LIST_UNLOCK(&dial->channels);
00620
00621
00622 if (!count) {
00623 set_state(dial, AST_DIAL_RESULT_UNANSWERED);
00624 break;
00625 }
00626
00627
00628 if (dial->thread == AST_PTHREADT_STOP)
00629 break;
00630
00631
00632 who = ast_waitfor_n(cs, pos, &timeout);
00633
00634
00635 if (dial->thread == AST_PTHREADT_STOP)
00636 break;
00637
00638
00639 if (!timeout || !who) {
00640 timeout = handle_timeout_trip(dial, start);
00641 continue;
00642 }
00643
00644
00645 if (!chan || !IS_CALLER(chan, who))
00646 channel = find_relative_dial_channel(dial, who);
00647
00648
00649 if (!ast_strlen_zero(ast_channel_call_forward(who))) {
00650 handle_call_forward(dial, channel, chan);
00651 continue;
00652 }
00653
00654
00655 if (!(fr = ast_read(who))) {
00656
00657 if (chan && IS_CALLER(chan, who)) {
00658 set_state(dial, AST_DIAL_RESULT_HANGUP);
00659 break;
00660 }
00661 if (chan)
00662 ast_poll_channel_del(chan, channel->owner);
00663 ast_hangup(who);
00664 channel->owner = NULL;
00665 continue;
00666 }
00667
00668
00669 if (chan)
00670 handle_frame(dial, channel, fr, chan);
00671 else
00672 handle_frame_ownerless(dial, channel, fr);
00673
00674
00675 ast_frfree(fr);
00676 }
00677
00678
00679 if (dial->state == AST_DIAL_RESULT_ANSWERED) {
00680
00681 AST_LIST_LOCK(&dial->channels);
00682 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
00683 if (!channel->owner || channel->owner == who)
00684 continue;
00685 if (chan)
00686 ast_poll_channel_del(chan, channel->owner);
00687 ast_hangup(channel->owner);
00688 channel->owner = NULL;
00689 }
00690 AST_LIST_UNLOCK(&dial->channels);
00691
00692 if ((channel = find_relative_dial_channel(dial, who)) && (answer_exec = FIND_RELATIVE_OPTION(dial, channel, AST_DIAL_OPTION_ANSWER_EXEC))) {
00693 channel->is_running_app = 1;
00694 answer_exec_run(dial, channel, answer_exec->app, answer_exec->args);
00695 channel->is_running_app = 0;
00696 }
00697
00698 if (chan && dial->options[AST_DIAL_OPTION_MUSIC] &&
00699 !ast_strlen_zero(dial->options[AST_DIAL_OPTION_MUSIC])) {
00700 ast_moh_stop(chan);
00701 }
00702 } else if (dial->state == AST_DIAL_RESULT_HANGUP) {
00703
00704 AST_LIST_LOCK(&dial->channels);
00705 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
00706 if (!channel->owner)
00707 continue;
00708 if (chan)
00709 ast_poll_channel_del(chan, channel->owner);
00710 ast_hangup(channel->owner);
00711 channel->owner = NULL;
00712 }
00713 AST_LIST_UNLOCK(&dial->channels);
00714 }
00715
00716 return dial->state;
00717 }
00718
00719
00720 static void *async_dial(void *data)
00721 {
00722 struct ast_dial *dial = data;
00723 if (dial->callid) {
00724 ast_callid_threadassoc_add(dial->callid);
00725 }
00726
00727
00728 monitor_dial(dial, NULL);
00729
00730 return NULL;
00731 }
00732
00733
00734
00735
00736
00737 enum ast_dial_result ast_dial_run(struct ast_dial *dial, struct ast_channel *chan, int async)
00738 {
00739 enum ast_dial_result res = AST_DIAL_RESULT_TRYING;
00740
00741
00742 if (!dial || (!chan && !async)) {
00743 ast_debug(1, "invalid #1\n");
00744 return AST_DIAL_RESULT_INVALID;
00745 }
00746
00747
00748 if (AST_LIST_EMPTY(&dial->channels)) {
00749 ast_debug(1, "invalid #2\n");
00750 return AST_DIAL_RESULT_INVALID;
00751 }
00752
00753
00754 if (!begin_dial(dial, chan))
00755 return AST_DIAL_RESULT_FAILED;
00756
00757
00758 if (async) {
00759
00760 dial->callid = ast_read_threadstorage_callid();
00761 dial->state = AST_DIAL_RESULT_TRYING;
00762
00763 if (ast_pthread_create(&dial->thread, NULL, async_dial, dial)) {
00764
00765 ast_dial_hangup(dial);
00766 res = AST_DIAL_RESULT_FAILED;
00767 }
00768 } else {
00769 res = monitor_dial(dial, chan);
00770 }
00771
00772 return res;
00773 }
00774
00775
00776
00777
00778
00779 struct ast_channel *ast_dial_answered(struct ast_dial *dial)
00780 {
00781 if (!dial)
00782 return NULL;
00783
00784 return ((dial->state == AST_DIAL_RESULT_ANSWERED) ? AST_LIST_FIRST(&dial->channels)->owner : NULL);
00785 }
00786
00787
00788
00789
00790
00791 struct ast_channel *ast_dial_answered_steal(struct ast_dial *dial)
00792 {
00793 struct ast_channel *chan = NULL;
00794
00795 if (!dial)
00796 return NULL;
00797
00798 if (dial->state == AST_DIAL_RESULT_ANSWERED) {
00799 chan = AST_LIST_FIRST(&dial->channels)->owner;
00800 AST_LIST_FIRST(&dial->channels)->owner = NULL;
00801 }
00802
00803 return chan;
00804 }
00805
00806
00807
00808
00809
00810 enum ast_dial_result ast_dial_state(struct ast_dial *dial)
00811 {
00812 return dial->state;
00813 }
00814
00815
00816
00817
00818
00819 enum ast_dial_result ast_dial_join(struct ast_dial *dial)
00820 {
00821 pthread_t thread;
00822
00823
00824 if (dial->thread == AST_PTHREADT_NULL)
00825 return AST_DIAL_RESULT_FAILED;
00826
00827
00828 thread = dial->thread;
00829
00830
00831 ast_mutex_lock(&dial->lock);
00832
00833
00834 dial->thread = AST_PTHREADT_STOP;
00835
00836
00837 AST_LIST_LOCK(&dial->channels);
00838 if (AST_LIST_FIRST(&dial->channels)->is_running_app) {
00839 struct ast_channel *chan = AST_LIST_FIRST(&dial->channels)->owner;
00840 if (chan) {
00841 ast_channel_lock(chan);
00842 ast_softhangup(chan, AST_SOFTHANGUP_EXPLICIT);
00843 ast_channel_unlock(chan);
00844 }
00845 } else {
00846
00847 pthread_kill(thread, SIGURG);
00848 }
00849 AST_LIST_UNLOCK(&dial->channels);
00850
00851
00852 ast_mutex_unlock(&dial->lock);
00853
00854
00855 pthread_join(thread, NULL);
00856
00857
00858 dial->thread = AST_PTHREADT_NULL;
00859
00860 return dial->state;
00861 }
00862
00863
00864
00865
00866
00867 void ast_dial_hangup(struct ast_dial *dial)
00868 {
00869 struct ast_dial_channel *channel = NULL;
00870
00871 if (!dial)
00872 return;
00873
00874 AST_LIST_LOCK(&dial->channels);
00875 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
00876 if (channel->owner) {
00877 ast_hangup(channel->owner);
00878 channel->owner = NULL;
00879 }
00880 }
00881 AST_LIST_UNLOCK(&dial->channels);
00882
00883 return;
00884 }
00885
00886
00887
00888
00889
00890
00891 int ast_dial_destroy(struct ast_dial *dial)
00892 {
00893 int i = 0;
00894 struct ast_dial_channel *channel = NULL;
00895
00896 if (!dial)
00897 return -1;
00898
00899
00900 AST_LIST_LOCK(&dial->channels);
00901 AST_LIST_TRAVERSE_SAFE_BEGIN(&dial->channels, channel, list) {
00902
00903 for (i = 0; i < AST_DIAL_OPTION_MAX; i++) {
00904 if (!channel->options[i])
00905 continue;
00906 if (option_types[i].disable)
00907 option_types[i].disable(channel->options[i]);
00908 channel->options[i] = NULL;
00909 }
00910
00911 if (channel->owner) {
00912 ast_hangup(channel->owner);
00913 channel->owner = NULL;
00914 }
00915
00916 ast_free(channel->tech);
00917 ast_free(channel->device);
00918 AST_LIST_REMOVE_CURRENT(list);
00919 ast_free(channel);
00920 }
00921 AST_LIST_TRAVERSE_SAFE_END;
00922 AST_LIST_UNLOCK(&dial->channels);
00923
00924
00925 for (i = 0; i < AST_DIAL_OPTION_MAX; i++) {
00926 if (!dial->options[i])
00927 continue;
00928 if (option_types[i].disable)
00929 option_types[i].disable(dial->options[i]);
00930 dial->options[i] = NULL;
00931 }
00932
00933
00934 ast_mutex_destroy(&dial->lock);
00935
00936
00937 if (dial->callid) {
00938 ast_callid_unref(dial->callid);
00939 }
00940
00941
00942 ast_free(dial);
00943
00944 return 0;
00945 }
00946
00947
00948
00949
00950
00951
00952
00953 int ast_dial_option_global_enable(struct ast_dial *dial, enum ast_dial_option option, void *data)
00954 {
00955
00956 if (dial->options[option])
00957 return -1;
00958
00959
00960 if (option_types[option].enable)
00961 dial->options[option] = option_types[option].enable(data);
00962 else
00963 dial->options[option] = (void*)1;
00964
00965 return 0;
00966 }
00967
00968
00969
00970 static struct ast_dial_channel *find_dial_channel(struct ast_dial *dial, int num)
00971 {
00972 struct ast_dial_channel *channel = AST_LIST_LAST(&dial->channels);
00973
00974
00975 if (channel->num == num)
00976 return channel;
00977
00978
00979 AST_LIST_LOCK(&dial->channels);
00980 AST_LIST_TRAVERSE(&dial->channels, channel, list) {
00981 if (channel->num == num)
00982 break;
00983 }
00984 AST_LIST_UNLOCK(&dial->channels);
00985
00986 return channel;
00987 }
00988
00989
00990
00991
00992
00993
00994
00995
00996 int ast_dial_option_enable(struct ast_dial *dial, int num, enum ast_dial_option option, void *data)
00997 {
00998 struct ast_dial_channel *channel = NULL;
00999
01000
01001 if (!dial || AST_LIST_EMPTY(&dial->channels))
01002 return -1;
01003
01004 if (!(channel = find_dial_channel(dial, num)))
01005 return -1;
01006
01007
01008 if (channel->options[option])
01009 return -1;
01010
01011
01012 if (option_types[option].enable)
01013 channel->options[option] = option_types[option].enable(data);
01014 else
01015 channel->options[option] = (void*)1;
01016
01017 return 0;
01018 }
01019
01020
01021
01022
01023
01024
01025 int ast_dial_option_global_disable(struct ast_dial *dial, enum ast_dial_option option)
01026 {
01027
01028 if (!dial->options[option]) {
01029 return -1;
01030 }
01031
01032
01033 if (option_types[option].disable)
01034 option_types[option].disable(dial->options[option]);
01035
01036
01037 dial->options[option] = NULL;
01038
01039 return 0;
01040 }
01041
01042
01043
01044
01045
01046
01047
01048 int ast_dial_option_disable(struct ast_dial *dial, int num, enum ast_dial_option option)
01049 {
01050 struct ast_dial_channel *channel = NULL;
01051
01052
01053 if (!dial || AST_LIST_EMPTY(&dial->channels))
01054 return -1;
01055
01056 if (!(channel = find_dial_channel(dial, num)))
01057 return -1;
01058
01059
01060 if (!channel->options[option])
01061 return -1;
01062
01063
01064 if (option_types[option].disable)
01065 option_types[option].disable(channel->options[option]);
01066
01067
01068 channel->options[option] = NULL;
01069
01070 return 0;
01071 }
01072
01073 void ast_dial_set_state_callback(struct ast_dial *dial, ast_dial_state_callback callback)
01074 {
01075 dial->state_callback = callback;
01076 }
01077
01078 void ast_dial_set_user_data(struct ast_dial *dial, void *user_data)
01079 {
01080 dial->user_data = user_data;
01081 }
01082
01083 void *ast_dial_get_user_data(struct ast_dial *dial)
01084 {
01085 return dial->user_data;
01086 }
01087
01088
01089
01090
01091
01092
01093 void ast_dial_set_global_timeout(struct ast_dial *dial, int timeout)
01094 {
01095 dial->timeout = timeout;
01096
01097 if (dial->timeout > 0 && (dial->actual_timeout > dial->timeout || dial->actual_timeout == -1))
01098 dial->actual_timeout = dial->timeout;
01099
01100 return;
01101 }
01102
01103
01104
01105
01106
01107
01108
01109 void ast_dial_set_timeout(struct ast_dial *dial, int num, int timeout)
01110 {
01111 struct ast_dial_channel *channel = NULL;
01112
01113 if (!(channel = find_dial_channel(dial, num)))
01114 return;
01115
01116 channel->timeout = timeout;
01117
01118 if (channel->timeout > 0 && (dial->actual_timeout > channel->timeout || dial->actual_timeout == -1))
01119 dial->actual_timeout = channel->timeout;
01120
01121 return;
01122 }