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 <stdio.h>
00032 #include <string.h>
00033 #include <errno.h>
00034 #include <unistd.h>
00035 #include <sys/socket.h>
00036 #include <stdlib.h>
00037 #include <fcntl.h>
00038 #include <netdb.h>
00039 #include <netinet/in.h>
00040 #include <arpa/inet.h>
00041 #include <sys/signal.h>
00042
00043 #include "asterisk.h"
00044
00045 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 76653 $")
00046
00047 #include "asterisk/lock.h"
00048 #include "asterisk/channel.h"
00049 #include "asterisk/config.h"
00050 #include "asterisk/logger.h"
00051 #include "asterisk/module.h"
00052 #include "asterisk/pbx.h"
00053 #include "asterisk/options.h"
00054 #include "asterisk/lock.h"
00055 #include "asterisk/sched.h"
00056 #include "asterisk/io.h"
00057 #include "asterisk/rtp.h"
00058 #include "asterisk/acl.h"
00059 #include "asterisk/callerid.h"
00060 #include "asterisk/file.h"
00061 #include "asterisk/cli.h"
00062 #include "asterisk/app.h"
00063 #include "asterisk/musiconhold.h"
00064 #include "asterisk/manager.h"
00065 #include "asterisk/features.h"
00066 #include "asterisk/utils.h"
00067 #include "asterisk/causes.h"
00068 #include "asterisk/astdb.h"
00069 #include "asterisk/devicestate.h"
00070 #include "asterisk/monitor.h"
00071
00072 static const char desc[] = "Agent Proxy Channel";
00073 static const char channeltype[] = "Agent";
00074 static const char tdesc[] = "Call Agent Proxy Channel";
00075 static const char config[] = "agents.conf";
00076
00077 static const char app[] = "AgentLogin";
00078 static const char app2[] = "AgentCallbackLogin";
00079 static const char app3[] = "AgentMonitorOutgoing";
00080
00081 static const char synopsis[] = "Call agent login";
00082 static const char synopsis2[] = "Call agent callback login";
00083 static const char synopsis3[] = "Record agent's outgoing call";
00084
00085 static const char descrip[] =
00086 " AgentLogin([AgentNo][|options]):\n"
00087 "Asks the agent to login to the system. Always returns -1. While\n"
00088 "logged in, the agent can receive calls and will hear a 'beep'\n"
00089 "when a new call comes in. The agent can dump the call by pressing\n"
00090 "the star key.\n"
00091 "The option string may contain zero or more of the following characters:\n"
00092 " 's' -- silent login - do not announce the login ok segment after agent logged in/off\n";
00093
00094 static const char descrip2[] =
00095 " AgentCallbackLogin([AgentNo][|[options][|[exten]@context]]):\n"
00096 "Asks the agent to login to the system with callback.\n"
00097 "The agent's callback extension is called (optionally with the specified\n"
00098 "context).\n"
00099 "The option string may contain zero or more of the following characters:\n"
00100 " 's' -- silent login - do not announce the login ok segment agent logged in/off\n";
00101
00102 static const char descrip3[] =
00103 " AgentMonitorOutgoing([options]):\n"
00104 "Tries to figure out the id of the agent who is placing outgoing call based on\n"
00105 "comparison of the callerid of the current interface and the global variable \n"
00106 "placed by the AgentCallbackLogin application. That's why it should be used only\n"
00107 "with the AgentCallbackLogin app. Uses the monitoring functions in chan_agent \n"
00108 "instead of Monitor application. That have to be configured in the agents.conf file.\n"
00109 "\nReturn value:\n"
00110 "Normally the app returns 0 unless the options are passed. Also if the callerid or\n"
00111 "the agentid are not specified it'll look for n+101 priority.\n"
00112 "\nOptions:\n"
00113 " 'd' - make the app return -1 if there is an error condition and there is\n"
00114 " no extension n+101\n"
00115 " 'c' - change the CDR so that the source of the call is 'Agent/agent_id'\n"
00116 " 'n' - don't generate the warnings when there is no callerid or the\n"
00117 " agentid is not known.\n"
00118 " It's handy if you want to have one context for agent and non-agent calls.\n";
00119
00120 static const char mandescr_agents[] =
00121 "Description: Will list info about all possible agents.\n"
00122 "Variables: NONE\n";
00123
00124 static const char mandescr_agent_logoff[] =
00125 "Description: Sets an agent as no longer logged in.\n"
00126 "Variables: (Names marked with * are required)\n"
00127 " *Agent: Agent ID of the agent to log off\n"
00128 " Soft: Set to 'true' to not hangup existing calls\n";
00129
00130 static const char mandescr_agent_callback_login[] =
00131 "Description: Sets an agent as logged in with callback.\n"
00132 "Variables: (Names marked with * are required)\n"
00133 " *Agent: Agent ID of the agent to login\n"
00134 " *Exten: Extension to use for callback\n"
00135 " Context: Context to use for callback\n"
00136 " AckCall: Set to 'true' to require an acknowledgement by '#' when agent is called back\n"
00137 " WrapupTime: the minimum amount of time after disconnecting before the caller can receive a new call\n";
00138
00139 static char moh[80] = "default";
00140
00141 #define AST_MAX_AGENT 80
00142 #define AST_MAX_BUF 256
00143 #define AST_MAX_FILENAME_LEN 256
00144
00145
00146 static const char pa_family[] = "/Agents";
00147
00148 #define PA_MAX_LEN 2048
00149
00150 static int persistent_agents = 0;
00151 static void dump_agents(void);
00152
00153 static ast_group_t group;
00154 static int autologoff;
00155 static int wrapuptime;
00156 static int ackcall;
00157
00158 static int maxlogintries = 3;
00159 static char agentgoodbye[AST_MAX_FILENAME_LEN] = "vm-goodbye";
00160
00161 static int usecnt =0;
00162 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
00163
00164
00165 AST_MUTEX_DEFINE_STATIC(agentlock);
00166
00167 static int recordagentcalls = 0;
00168 static char recordformat[AST_MAX_BUF] = "";
00169 static char recordformatext[AST_MAX_BUF] = "";
00170 static int createlink = 0;
00171 static char urlprefix[AST_MAX_BUF] = "";
00172 static char savecallsin[AST_MAX_BUF] = "";
00173 static int updatecdr = 0;
00174 static char beep[AST_MAX_BUF] = "beep";
00175
00176 #define GETAGENTBYCALLERID "AGENTBYCALLERID"
00177
00178
00179
00180
00181 struct agent_pvt {
00182 ast_mutex_t lock;
00183 int dead;
00184 int pending;
00185 int abouttograb;
00186 int autologoff;
00187 int ackcall;
00188 time_t loginstart;
00189 time_t start;
00190 struct timeval lastdisc;
00191 int wrapuptime;
00192 ast_group_t group;
00193 int acknowledged;
00194 char moh[80];
00195 char agent[AST_MAX_AGENT];
00196 char password[AST_MAX_AGENT];
00197 char name[AST_MAX_AGENT];
00198 ast_mutex_t app_lock;
00199 volatile pthread_t owning_app;
00200 volatile int app_sleep_cond;
00201 struct ast_channel *owner;
00202 char loginchan[80];
00203 char logincallerid[80];
00204 struct ast_channel *chan;
00205 struct agent_pvt *next;
00206 };
00207
00208 static struct agent_pvt *agents = NULL;
00209
00210 #define CHECK_FORMATS(ast, p) do { \
00211 if (p->chan) {\
00212 if (ast->nativeformats != p->chan->nativeformats) { \
00213 ast_log(LOG_DEBUG, "Native formats changing from %d to %d\n", ast->nativeformats, p->chan->nativeformats); \
00214 \
00215 ast->nativeformats = p->chan->nativeformats; \
00216 ast_log(LOG_DEBUG, "Resetting read to %d and write to %d\n", ast->readformat, ast->writeformat);\
00217 ast_set_read_format(ast, ast->readformat); \
00218 ast_set_write_format(ast, ast->writeformat); \
00219 } \
00220 if (p->chan->readformat != ast->rawreadformat && !p->chan->generator) \
00221 ast_set_read_format(p->chan, ast->rawreadformat); \
00222 if (p->chan->writeformat != ast->rawwriteformat && !p->chan->generator) \
00223 ast_set_write_format(p->chan, ast->rawwriteformat); \
00224 } \
00225 } while(0)
00226
00227
00228
00229
00230
00231 #define CLEANUP(ast, p) do { \
00232 int x; \
00233 if (p->chan) { \
00234 for (x=0;x<AST_MAX_FDS;x++) {\
00235 if (x != AST_MAX_FDS - 2) \
00236 ast->fds[x] = p->chan->fds[x]; \
00237 } \
00238 ast->fds[AST_MAX_FDS - 3] = p->chan->fds[AST_MAX_FDS - 2]; \
00239 } \
00240 } while(0)
00241
00242 static struct ast_channel *agent_request(const char *type, int format, void *data, int *cause);
00243 static int agent_devicestate(void *data);
00244 static int agent_digit(struct ast_channel *ast, char digit);
00245 static int agent_call(struct ast_channel *ast, char *dest, int timeout);
00246 static int agent_hangup(struct ast_channel *ast);
00247 static int agent_answer(struct ast_channel *ast);
00248 static struct ast_frame *agent_read(struct ast_channel *ast);
00249 static int agent_write(struct ast_channel *ast, struct ast_frame *f);
00250 static int agent_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen);
00251 static int agent_sendtext(struct ast_channel *ast, const char *text);
00252 static int agent_indicate(struct ast_channel *ast, int condition);
00253 static int agent_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
00254 static struct ast_channel *agent_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge);
00255
00256 static const struct ast_channel_tech agent_tech = {
00257 .type = channeltype,
00258 .description = tdesc,
00259 .capabilities = -1,
00260 .requester = agent_request,
00261 .devicestate = agent_devicestate,
00262 .send_digit = agent_digit,
00263 .call = agent_call,
00264 .hangup = agent_hangup,
00265 .answer = agent_answer,
00266 .read = agent_read,
00267 .write = agent_write,
00268 .send_html = agent_sendhtml,
00269 .send_text = agent_sendtext,
00270 .exception = agent_read,
00271 .indicate = agent_indicate,
00272 .fixup = agent_fixup,
00273 .bridged_channel = agent_bridgedchannel,
00274 };
00275
00276
00277
00278
00279
00280
00281 static void agent_unlink(struct agent_pvt *agent)
00282 {
00283 struct agent_pvt *p, *prev;
00284 prev = NULL;
00285 p = agents;
00286
00287 while(p) {
00288 if (p == agent) {
00289
00290 if (prev)
00291
00292 prev->next = agent->next;
00293 else
00294
00295 agents = agent->next;
00296
00297 break;
00298 }
00299 prev = p;
00300 p = p->next;
00301 }
00302 }
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312 static struct agent_pvt *add_agent(char *agent, int pending)
00313 {
00314 int argc;
00315 char *argv[3];
00316 char *args;
00317 char *password = NULL;
00318 char *name = NULL;
00319 char *agt = NULL;
00320 struct agent_pvt *p, *prev;
00321
00322 args = ast_strdupa(agent);
00323
00324
00325 if ((argc = ast_app_separate_args(args, ',', argv, sizeof(argv) / sizeof(argv[0])))) {
00326 agt = argv[0];
00327 if (argc > 1) {
00328 password = argv[1];
00329 while (*password && *password < 33) password++;
00330 }
00331 if (argc > 2) {
00332 name = argv[2];
00333 while (*name && *name < 33) name++;
00334 }
00335 } else {
00336 ast_log(LOG_WARNING, "A blank agent line!\n");
00337 }
00338
00339
00340 prev=NULL;
00341 p = agents;
00342 while(p) {
00343 if (!pending && !strcmp(p->agent, agt))
00344 break;
00345 prev = p;
00346 p = p->next;
00347 }
00348 if (!p) {
00349
00350 p = malloc(sizeof(struct agent_pvt));
00351 if (p) {
00352 memset(p, 0, sizeof(struct agent_pvt));
00353 ast_copy_string(p->agent, agt, sizeof(p->agent));
00354 ast_mutex_init(&p->lock);
00355 ast_mutex_init(&p->app_lock);
00356 p->owning_app = (pthread_t) -1;
00357 p->app_sleep_cond = 1;
00358 p->group = group;
00359 p->pending = pending;
00360 p->next = NULL;
00361 if (prev)
00362 prev->next = p;
00363 else
00364 agents = p;
00365
00366 } else {
00367 return NULL;
00368 }
00369 }
00370
00371 ast_copy_string(p->password, password ? password : "", sizeof(p->password));
00372 ast_copy_string(p->name, name ? name : "", sizeof(p->name));
00373 ast_copy_string(p->moh, moh, sizeof(p->moh));
00374 p->ackcall = ackcall;
00375 p->autologoff = autologoff;
00376
00377
00378
00379 if (p->wrapuptime > wrapuptime) {
00380 struct timeval now = ast_tvnow();
00381
00382
00383
00384 if (p->lastdisc.tv_sec > (now.tv_sec + wrapuptime/1000)) {
00385 p->lastdisc.tv_sec = now.tv_sec + wrapuptime/1000;
00386 p->lastdisc.tv_usec = now.tv_usec;
00387 }
00388 }
00389 p->wrapuptime = wrapuptime;
00390
00391 if (pending)
00392 p->dead = 1;
00393 else
00394 p->dead = 0;
00395 return p;
00396 }
00397
00398
00399
00400
00401
00402
00403
00404 static int agent_cleanup(struct agent_pvt *p)
00405 {
00406 struct ast_channel *chan = p->owner;
00407 p->owner = NULL;
00408 chan->tech_pvt = NULL;
00409 p->app_sleep_cond = 1;
00410
00411 ast_mutex_unlock(&p->app_lock);
00412 if (chan)
00413 ast_channel_free(chan);
00414 if (p->dead) {
00415 ast_mutex_destroy(&p->lock);
00416 ast_mutex_destroy(&p->app_lock);
00417 free(p);
00418 }
00419 return 0;
00420 }
00421
00422 static int check_availability(struct agent_pvt *newlyavailable, int needlock);
00423
00424 static int agent_answer(struct ast_channel *ast)
00425 {
00426 ast_log(LOG_WARNING, "Huh? Agent is being asked to answer?\n");
00427 return -1;
00428 }
00429
00430 static int __agent_start_monitoring(struct ast_channel *ast, struct agent_pvt *p, int needlock)
00431 {
00432 char tmp[AST_MAX_BUF],tmp2[AST_MAX_BUF], *pointer;
00433 char filename[AST_MAX_BUF];
00434 int res = -1;
00435 if (!p)
00436 return -1;
00437 if (!ast->monitor) {
00438 snprintf(filename, sizeof(filename), "agent-%s-%s",p->agent, ast->uniqueid);
00439
00440 if ((pointer = strchr(filename, '.')))
00441 *pointer = '-';
00442 snprintf(tmp, sizeof(tmp), "%s%s",savecallsin ? savecallsin : "", filename);
00443 ast_monitor_start(ast, recordformat, tmp, needlock);
00444 ast_monitor_setjoinfiles(ast, 1);
00445 snprintf(tmp2, sizeof(tmp2), "%s%s.%s", urlprefix ? urlprefix : "", filename, recordformatext);
00446 #if 0
00447 ast_verbose("name is %s, link is %s\n",tmp, tmp2);
00448 #endif
00449 if (!ast->cdr)
00450 ast->cdr = ast_cdr_alloc();
00451 ast_cdr_setuserfield(ast, tmp2);
00452 res = 0;
00453 } else
00454 ast_log(LOG_ERROR, "Recording already started on that call.\n");
00455 return res;
00456 }
00457
00458 static int agent_start_monitoring(struct ast_channel *ast, int needlock)
00459 {
00460 return __agent_start_monitoring(ast, ast->tech_pvt, needlock);
00461 }
00462
00463 static struct ast_frame *agent_read(struct ast_channel *ast)
00464 {
00465 struct agent_pvt *p = ast->tech_pvt;
00466 struct ast_frame *f = NULL;
00467 static struct ast_frame null_frame = { AST_FRAME_NULL, };
00468 static struct ast_frame answer_frame = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
00469 ast_mutex_lock(&p->lock);
00470 CHECK_FORMATS(ast, p);
00471 if (p->chan) {
00472 ast_copy_flags(p->chan, ast, AST_FLAG_EXCEPTION);
00473 if (ast->fdno == AST_MAX_FDS - 3)
00474 p->chan->fdno = AST_MAX_FDS - 2;
00475 else
00476 p->chan->fdno = ast->fdno;
00477 f = ast_read(p->chan);
00478 } else
00479 f = &null_frame;
00480 if (!f) {
00481
00482 if (p->chan) {
00483 p->chan->_bridge = NULL;
00484
00485
00486 if (!ast_strlen_zero(p->loginchan)) {
00487 if (p->chan)
00488 ast_log(LOG_DEBUG, "Bridge on '%s' being cleared (2)\n", p->chan->name);
00489 ast_hangup(p->chan);
00490 if (p->wrapuptime && p->acknowledged)
00491 p->lastdisc = ast_tvadd(ast_tvnow(), ast_samp2tv(p->wrapuptime, 1000));
00492 }
00493 p->chan = NULL;
00494 p->acknowledged = 0;
00495 }
00496 } else {
00497
00498
00499 if (!p->ackcall && !p->acknowledged && p->chan && (p->chan->_state == AST_STATE_UP))
00500 p->acknowledged = 1;
00501 switch (f->frametype) {
00502 case AST_FRAME_CONTROL:
00503 if (f->subclass == AST_CONTROL_ANSWER) {
00504 if (p->ackcall) {
00505 if (option_verbose > 2)
00506 ast_verbose(VERBOSE_PREFIX_3 "%s answered, waiting for '#' to acknowledge\n", p->chan->name);
00507
00508 ast_frfree(f);
00509 f = &null_frame;
00510 } else {
00511 p->acknowledged = 1;
00512
00513
00514 ast_frfree(f);
00515 f = &answer_frame;
00516 }
00517 }
00518 break;
00519 case AST_FRAME_DTMF:
00520 if (!p->acknowledged && (f->subclass == '#')) {
00521 if (option_verbose > 2)
00522 ast_verbose(VERBOSE_PREFIX_3 "%s acknowledged\n", p->chan->name);
00523 p->acknowledged = 1;
00524 ast_frfree(f);
00525 f = &answer_frame;
00526 } else if (f->subclass == '*') {
00527
00528 ast_frfree(f);
00529 f = NULL;
00530 }
00531 break;
00532 case AST_FRAME_VOICE:
00533
00534 if (!p->acknowledged) {
00535 ast_frfree(f);
00536 f = &null_frame;
00537 }
00538 break;
00539 }
00540 }
00541
00542 CLEANUP(ast,p);
00543 if (p->chan && !p->chan->_bridge) {
00544 if (strcasecmp(p->chan->type, "Local")) {
00545 p->chan->_bridge = ast;
00546 if (p->chan)
00547 ast_log(LOG_DEBUG, "Bridge on '%s' being set to '%s' (3)\n", p->chan->name, p->chan->_bridge->name);
00548 }
00549 }
00550 ast_mutex_unlock(&p->lock);
00551 if (recordagentcalls && f == &answer_frame)
00552 agent_start_monitoring(ast,0);
00553 return f;
00554 }
00555
00556 static int agent_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen)
00557 {
00558 struct agent_pvt *p = ast->tech_pvt;
00559 int res = -1;
00560 ast_mutex_lock(&p->lock);
00561 if (p->chan)
00562 res = ast_channel_sendhtml(p->chan, subclass, data, datalen);
00563 ast_mutex_unlock(&p->lock);
00564 return res;
00565 }
00566
00567 static int agent_sendtext(struct ast_channel *ast, const char *text)
00568 {
00569 struct agent_pvt *p = ast->tech_pvt;
00570 int res = -1;
00571 ast_mutex_lock(&p->lock);
00572 if (p->chan)
00573 res = ast_sendtext(p->chan, text);
00574 ast_mutex_unlock(&p->lock);
00575 return res;
00576 }
00577
00578 static int agent_write(struct ast_channel *ast, struct ast_frame *f)
00579 {
00580 struct agent_pvt *p = ast->tech_pvt;
00581 int res = -1;
00582 CHECK_FORMATS(ast, p);
00583 ast_mutex_lock(&p->lock);
00584 if (p->chan) {
00585 if ((f->frametype != AST_FRAME_VOICE) ||
00586 (f->subclass == p->chan->writeformat)) {
00587 res = ast_write(p->chan, f);
00588 } else {
00589 ast_log(LOG_DEBUG, "Dropping one incompatible voice frame on '%s' to '%s'\n", ast->name, p->chan->name);
00590 res = 0;
00591 }
00592 } else
00593 res = 0;
00594 CLEANUP(ast, p);
00595 ast_mutex_unlock(&p->lock);
00596 return res;
00597 }
00598
00599 static int agent_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
00600 {
00601 struct agent_pvt *p = newchan->tech_pvt;
00602 ast_mutex_lock(&p->lock);
00603 if (p->owner != oldchan) {
00604 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, p->owner);
00605 ast_mutex_unlock(&p->lock);
00606 return -1;
00607 }
00608 p->owner = newchan;
00609 ast_mutex_unlock(&p->lock);
00610 return 0;
00611 }
00612
00613 static int agent_indicate(struct ast_channel *ast, int condition)
00614 {
00615 struct agent_pvt *p = ast->tech_pvt;
00616 int res = -1;
00617 ast_mutex_lock(&p->lock);
00618 if (p->chan)
00619 res = p->chan->tech->indicate ? p->chan->tech->indicate(p->chan, condition) : -1;
00620 else
00621 res = 0;
00622 ast_mutex_unlock(&p->lock);
00623 return res;
00624 }
00625
00626 static int agent_digit(struct ast_channel *ast, char digit)
00627 {
00628 struct agent_pvt *p = ast->tech_pvt;
00629 int res = -1;
00630 ast_mutex_lock(&p->lock);
00631 if (p->chan)
00632 res = p->chan->tech->send_digit(p->chan, digit);
00633 else
00634 res = 0;
00635 ast_mutex_unlock(&p->lock);
00636 return res;
00637 }
00638
00639 static int agent_call(struct ast_channel *ast, char *dest, int timeout)
00640 {
00641 struct agent_pvt *p = ast->tech_pvt;
00642 int res = -1;
00643 int newstate=0;
00644 ast_mutex_lock(&p->lock);
00645 p->acknowledged = 0;
00646 if (!p->chan) {
00647 if (p->pending) {
00648 ast_log(LOG_DEBUG, "Pretending to dial on pending agent\n");
00649 newstate = AST_STATE_DIALING;
00650 res = 0;
00651 } else {
00652 ast_log(LOG_NOTICE, "Whoa, they hung up between alloc and call... what are the odds of that?\n");
00653 res = -1;
00654 }
00655 ast_mutex_unlock(&p->lock);
00656 if (newstate)
00657 ast_setstate(ast, newstate);
00658 return res;
00659 } else if (!ast_strlen_zero(p->loginchan)) {
00660 time(&p->start);
00661
00662 if (option_verbose > 2)
00663 ast_verbose(VERBOSE_PREFIX_3 "outgoing agentcall, to agent '%s', on '%s'\n", p->agent, p->chan->name);
00664 ast_set_callerid(p->chan,
00665 ast->cid.cid_num, ast->cid.cid_name, NULL);
00666 ast_channel_inherit_variables(ast, p->chan);
00667 res = ast_call(p->chan, p->loginchan, 0);
00668 CLEANUP(ast,p);
00669 ast_mutex_unlock(&p->lock);
00670 return res;
00671 }
00672 ast_verbose( VERBOSE_PREFIX_3 "agent_call, call to agent '%s' call on '%s'\n", p->agent, p->chan->name);
00673 ast_log( LOG_DEBUG, "Playing beep, lang '%s'\n", p->chan->language);
00674 res = ast_streamfile(p->chan, beep, p->chan->language);
00675 ast_log( LOG_DEBUG, "Played beep, result '%d'\n", res);
00676 if (!res) {
00677 res = ast_waitstream(p->chan, "");
00678 ast_log( LOG_DEBUG, "Waited for stream, result '%d'\n", res);
00679 }
00680 if (!res) {
00681 res = ast_set_read_format(p->chan, ast_best_codec(p->chan->nativeformats));
00682 ast_log( LOG_DEBUG, "Set read format, result '%d'\n", res);
00683 if (res)
00684 ast_log(LOG_WARNING, "Unable to set read format to %s\n", ast_getformatname(ast_best_codec(p->chan->nativeformats)));
00685 } else {
00686
00687 p->chan = NULL;
00688 }
00689
00690 if (!res) {
00691 ast_set_write_format(p->chan, ast_best_codec(p->chan->nativeformats));
00692 ast_log( LOG_DEBUG, "Set write format, result '%d'\n", res);
00693 if (res)
00694 ast_log(LOG_WARNING, "Unable to set write format to %s\n", ast_getformatname(ast_best_codec(p->chan->nativeformats)));
00695 }
00696 if( !res )
00697 {
00698
00699 if (p->ackcall > 1)
00700 newstate = AST_STATE_RINGING;
00701 else {
00702 newstate = AST_STATE_UP;
00703 if (recordagentcalls)
00704 agent_start_monitoring(ast,0);
00705 p->acknowledged = 1;
00706 }
00707 res = 0;
00708 }
00709 CLEANUP(ast,p);
00710 ast_mutex_unlock(&p->lock);
00711 if (newstate)
00712 ast_setstate(ast, newstate);
00713 return res;
00714 }
00715
00716
00717 static void set_agentbycallerid(const char *callerid, const char *agent)
00718 {
00719 char buf[AST_MAX_BUF];
00720
00721
00722 if (ast_strlen_zero(callerid))
00723 return;
00724
00725 snprintf(buf, sizeof(buf), "%s_%s",GETAGENTBYCALLERID, callerid);
00726 pbx_builtin_setvar_helper(NULL, buf, agent);
00727 }
00728
00729 static int agent_hangup(struct ast_channel *ast)
00730 {
00731 struct agent_pvt *p = ast->tech_pvt;
00732 int howlong = 0;
00733 ast_mutex_lock(&p->lock);
00734 p->owner = NULL;
00735 ast->tech_pvt = NULL;
00736 p->app_sleep_cond = 1;
00737 p->acknowledged = 0;
00738
00739
00740
00741
00742
00743
00744
00745
00746 ast_mutex_lock(&usecnt_lock);
00747 usecnt--;
00748 ast_mutex_unlock(&usecnt_lock);
00749
00750 ast_log(LOG_DEBUG, "Hangup called for state %s\n", ast_state2str(ast->_state));
00751 if (p->start && (ast->_state != AST_STATE_UP)) {
00752 howlong = time(NULL) - p->start;
00753 p->start = 0;
00754 } else if (ast->_state == AST_STATE_RESERVED) {
00755 howlong = 0;
00756 } else
00757 p->start = 0;
00758 if (p->chan) {
00759 p->chan->_bridge = NULL;
00760
00761 if (!ast_strlen_zero(p->loginchan)) {
00762
00763 if (p->wrapuptime)
00764 p->lastdisc = ast_tvadd(ast_tvnow(), ast_samp2tv(p->wrapuptime, 1000));
00765 else
00766 p->lastdisc = ast_tv(0,0);
00767 if (p->chan) {
00768
00769 ast_hangup(p->chan);
00770 p->chan = NULL;
00771 }
00772 ast_log(LOG_DEBUG, "Hungup, howlong is %d, autologoff is %d\n", howlong, p->autologoff);
00773 if (howlong && p->autologoff && (howlong > p->autologoff)) {
00774 char agent[AST_MAX_AGENT] = "";
00775 long logintime = time(NULL) - p->loginstart;
00776 p->loginstart = 0;
00777 ast_log(LOG_NOTICE, "Agent '%s' didn't answer/confirm within %d seconds (waited %d)\n", p->name, p->autologoff, howlong);
00778 manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogoff",
00779 "Agent: %s\r\n"
00780 "Loginchan: %s\r\n"
00781 "Logintime: %ld\r\n"
00782 "Reason: Autologoff\r\n"
00783 "Uniqueid: %s\r\n",
00784 p->agent, p->loginchan, logintime, ast->uniqueid);
00785 snprintf(agent, sizeof(agent), "Agent/%s", p->agent);
00786 ast_queue_log("NONE", ast->uniqueid, agent, "AGENTCALLBACKLOGOFF", "%s|%ld|%s", p->loginchan, logintime, "Autologoff");
00787 set_agentbycallerid(p->logincallerid, NULL);
00788 ast_device_state_changed("Agent/%s", p->agent);
00789 p->loginchan[0] = '\0';
00790 p->logincallerid[0] = '\0';
00791 if (persistent_agents)
00792 dump_agents();
00793 } else if (!p->loginstart) {
00794 p->loginchan[0] = '\0';
00795 p->logincallerid[0] = '\0';
00796 if (persistent_agents)
00797 dump_agents();
00798 }
00799 } else if (p->dead) {
00800 ast_mutex_lock(&p->chan->lock);
00801 ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT);
00802 ast_mutex_unlock(&p->chan->lock);
00803 } else if (p->loginstart) {
00804 ast_mutex_lock(&p->chan->lock);
00805 ast_moh_start(p->chan, p->moh);
00806 ast_mutex_unlock(&p->chan->lock);
00807 }
00808 }
00809 ast_mutex_unlock(&p->lock);
00810
00811
00812 if<