chan_agent.c 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446
  1. /*
  2. * Asterisk -- A telephony toolkit for Linux.
  3. *
  4. * Implementation of Session Initiation Protocol
  5. *
  6. * Copyright (C) 1999, Mark Spencer
  7. *
  8. * Mark Spencer <markster@linux-support.net>
  9. *
  10. * This program is free software, distributed under the terms of
  11. * the GNU General Public License
  12. */
  13. #include <stdio.h>
  14. #include <pthread.h>
  15. #include <string.h>
  16. #include <asterisk/lock.h>
  17. #include <asterisk/channel.h>
  18. #include <asterisk/channel_pvt.h>
  19. #include <asterisk/config.h>
  20. #include <asterisk/logger.h>
  21. #include <asterisk/module.h>
  22. #include <asterisk/pbx.h>
  23. #include <asterisk/options.h>
  24. #include <asterisk/lock.h>
  25. #include <asterisk/sched.h>
  26. #include <asterisk/io.h>
  27. #include <asterisk/rtp.h>
  28. #include <asterisk/acl.h>
  29. #include <asterisk/callerid.h>
  30. #include <asterisk/file.h>
  31. #include <asterisk/cli.h>
  32. #include <asterisk/app.h>
  33. #include <asterisk/musiconhold.h>
  34. #include <asterisk/manager.h>
  35. #include <asterisk/parking.h>
  36. #include <sys/socket.h>
  37. #include <errno.h>
  38. #include <unistd.h>
  39. #include <stdlib.h>
  40. #include <fcntl.h>
  41. #include <netdb.h>
  42. #include <arpa/inet.h>
  43. #include <sys/signal.h>
  44. static char *desc = "Agent Proxy Channel";
  45. static char *type = "Agent";
  46. static char *tdesc = "Call Agent Proxy Channel";
  47. static char *config = "agents.conf";
  48. static char *app = "AgentLogin";
  49. static char *app2 = "AgentCallbackLogin";
  50. static char *synopsis = "Call agent login";
  51. static char *synopsis2 = "Call agent callback login";
  52. static char *descrip =
  53. " AgentLogin([AgentNo][|options]):\n"
  54. "Asks the agent to login to the system. Always returns -1. While\n"
  55. "logged in, the agent can receive calls and will hear a 'beep'\n"
  56. "when a new call comes in. The agent can dump the call by pressing\n"
  57. "the star key.\n"
  58. "The option string may contain zero or more of the following characters:\n"
  59. " 's' -- silent login - do not announce the login ok segment\n";
  60. static char *descrip2 =
  61. " AgentCallbackLogin([AgentNo][|[options][exten]@context]):\n"
  62. "Asks the agent to login to the system with callback. Always returns -1.\n"
  63. "The agent's callback extension is called (optionally with the specified\n"
  64. "context. \n";
  65. static char moh[80] = "default";
  66. #define AST_MAX_AGENT 80 /* Agent ID or Password max length */
  67. #define AST_MAX_BUF 256
  68. static int capability = -1;
  69. static unsigned int group;
  70. static int autologoff;
  71. static int wrapuptime;
  72. static int ackcall;
  73. static int usecnt =0;
  74. static ast_mutex_t usecnt_lock = AST_MUTEX_INITIALIZER;
  75. /* Protect the interface list (of sip_pvt's) */
  76. static ast_mutex_t agentlock = AST_MUTEX_INITIALIZER;
  77. static int recordagentcalls = 0;
  78. static char recordformat[AST_MAX_BUF];
  79. static char recordformatext[AST_MAX_BUF];
  80. static int createlink = 0;
  81. static char urlprefix[AST_MAX_BUF];
  82. static char savecallsin[AST_MAX_BUF];
  83. static struct agent_pvt {
  84. ast_mutex_t lock; /* Channel private lock */
  85. int dead; /* Poised for destruction? */
  86. int pending; /* Not a real agent -- just pending a match */
  87. int abouttograb; /* About to grab */
  88. int autologoff; /* Auto timeout time */
  89. int ackcall; /* ackcall */
  90. time_t start; /* When call started */
  91. struct timeval lastdisc; /* When last disconnected */
  92. int wrapuptime; /* Wrapup time in ms */
  93. unsigned int group; /* Group memberships */
  94. int acknowledged; /* Acknowledged */
  95. char moh[80]; /* Which music on hold */
  96. char agent[AST_MAX_AGENT]; /* Agent ID */
  97. char password[AST_MAX_AGENT]; /* Password for Agent login */
  98. char name[AST_MAX_AGENT];
  99. ast_mutex_t app_lock; /* Synchronization between owning applications */
  100. volatile pthread_t owning_app; /* Owning application thread id */
  101. volatile int app_sleep_cond; /* Sleep condition for the login app */
  102. struct ast_channel *owner; /* Agent */
  103. char loginchan[80];
  104. struct ast_channel *chan; /* Channel we use */
  105. struct agent_pvt *next; /* Agent */
  106. } *agents = NULL;
  107. #define CHECK_FORMATS(ast, p) do { \
  108. if (p->chan) {\
  109. if (ast->nativeformats != p->chan->nativeformats) { \
  110. ast_log(LOG_DEBUG, "Native formats changing from %d to %d\n", ast->nativeformats, p->chan->nativeformats); \
  111. /* Native formats changed, reset things */ \
  112. ast->nativeformats = p->chan->nativeformats; \
  113. ast_log(LOG_DEBUG, "Resetting read to %d and write to %d\n", ast->readformat, ast->writeformat);\
  114. ast_set_read_format(ast, ast->readformat); \
  115. ast_set_write_format(ast, ast->writeformat); \
  116. } \
  117. if (p->chan->readformat != ast->pvt->rawreadformat) \
  118. ast_set_read_format(p->chan, ast->pvt->rawreadformat); \
  119. if (p->chan->writeformat != ast->pvt->rawwriteformat) \
  120. ast_set_write_format(p->chan, ast->pvt->rawwriteformat); \
  121. } \
  122. } while(0)
  123. /* Cleanup moves all the relevant FD's from the 2nd to the first, but retains things
  124. properly for a timingfd XXX This might need more work if agents were logged in as agents or other
  125. totally impractical combinations XXX */
  126. #define CLEANUP(ast, p) do { \
  127. int x; \
  128. if (p->chan) { \
  129. for (x=0;x<AST_MAX_FDS;x++) {\
  130. if (x != AST_MAX_FDS - 2) \
  131. ast->fds[x] = p->chan->fds[x]; \
  132. } \
  133. ast->fds[AST_MAX_FDS - 3] = p->chan->fds[AST_MAX_FDS - 2]; \
  134. } \
  135. } while(0)
  136. static void agent_unlink(struct agent_pvt *agent)
  137. {
  138. struct agent_pvt *p, *prev;
  139. prev = NULL;
  140. p = agents;
  141. while(p) {
  142. if (p == agent) {
  143. if (prev)
  144. prev->next = agent->next;
  145. else
  146. agents = agent->next;
  147. break;
  148. }
  149. prev = p;
  150. p = p->next;
  151. }
  152. }
  153. static struct agent_pvt *add_agent(char *agent, int pending)
  154. {
  155. char tmp[AST_MAX_BUF];
  156. char *password=NULL, *name=NULL;
  157. struct agent_pvt *p, *prev;
  158. strncpy(tmp, agent, sizeof(tmp));
  159. if ((password = strchr(tmp, ','))) {
  160. *password = '\0';
  161. password++;
  162. while (*password < 33) password++;
  163. }
  164. if (password && (name = strchr(password, ','))) {
  165. *name = '\0';
  166. name++;
  167. while (*name < 33) name++;
  168. }
  169. prev=NULL;
  170. p = agents;
  171. while(p) {
  172. if (!pending && !strcmp(p->agent, tmp))
  173. break;
  174. prev = p;
  175. p = p->next;
  176. }
  177. if (!p) {
  178. p = malloc(sizeof(struct agent_pvt));
  179. if (p) {
  180. memset(p, 0, sizeof(struct agent_pvt));
  181. strncpy(p->agent, tmp, sizeof(p->agent) -1);
  182. ast_mutex_init( &p->lock );
  183. ast_mutex_init( &p->app_lock );
  184. p->owning_app = (pthread_t) -1;
  185. p->app_sleep_cond = 1;
  186. p->group = group;
  187. p->pending = pending;
  188. p->next = NULL;
  189. if (prev)
  190. prev->next = p;
  191. else
  192. agents = p;
  193. }
  194. }
  195. if (!p)
  196. return NULL;
  197. strncpy(p->password, password ? password : "", sizeof(p->password) - 1);
  198. strncpy(p->name, name ? name : "", sizeof(p->name) - 1);
  199. strncpy(p->moh, moh, sizeof(p->moh) - 1);
  200. p->ackcall = ackcall;
  201. p->autologoff = autologoff;
  202. p->wrapuptime = wrapuptime;
  203. if (pending)
  204. p->dead = 1;
  205. else
  206. p->dead = 0;
  207. return p;
  208. }
  209. static int agent_cleanup(struct agent_pvt *p)
  210. {
  211. struct ast_channel *chan = p->owner;
  212. p->owner = NULL;
  213. chan->pvt->pvt = NULL;
  214. p->app_sleep_cond = 1;
  215. /* Release ownership of the agent to other threads (presumably running the login app). */
  216. ast_mutex_unlock(&p->app_lock);
  217. if (chan)
  218. ast_channel_free(chan);
  219. if (p->dead)
  220. free(p);
  221. return 0;
  222. }
  223. static int check_availability(struct agent_pvt *newlyavailable, int needlock);
  224. static int agent_answer(struct ast_channel *ast)
  225. {
  226. ast_log(LOG_WARNING, "Huh? Agent is being asked to answer?\n");
  227. return -1;
  228. }
  229. static int agent_start_monitoring(struct ast_channel *ast, int needlock)
  230. {
  231. struct agent_pvt *p = ast->pvt->pvt;
  232. char tmp[AST_MAX_BUF],tmp2[AST_MAX_BUF], *pointer;
  233. char filename[AST_MAX_BUF];
  234. int res = -1;
  235. if (!p)
  236. return -1;
  237. if (!ast->monitor) {
  238. snprintf(filename, sizeof(filename), "agent-%s-%s",p->agent, ast->uniqueid);
  239. snprintf(tmp, sizeof(tmp), "%s%s",savecallsin ? savecallsin : "", filename);
  240. if ((pointer = strchr(tmp, '.')))
  241. *pointer = '-';
  242. ast_monitor_start(ast, recordformat, tmp, needlock);
  243. ast_monitor_setjoinfiles(ast, 1);
  244. snprintf(tmp2, sizeof(tmp2), "%s%s.%s", urlprefix ? urlprefix : "", filename, recordformatext);
  245. #if 0
  246. ast_verbose("name is %s, link is %s\n",tmp, tmp2);
  247. #endif
  248. if (!ast->cdr)
  249. ast->cdr = ast_cdr_alloc();
  250. ast_cdr_setuserfield(ast, tmp2);
  251. res = 0;
  252. } else
  253. ast_log(LOG_ERROR, "Recording already started on that call.\n");
  254. return res;
  255. }
  256. static struct ast_frame *agent_read(struct ast_channel *ast)
  257. {
  258. struct agent_pvt *p = ast->pvt->pvt;
  259. struct ast_frame *f = NULL;
  260. static struct ast_frame null_frame = { AST_FRAME_NULL, };
  261. static struct ast_frame answer_frame = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
  262. ast_mutex_lock(&p->lock);
  263. CHECK_FORMATS(ast, p);
  264. if (p->chan) {
  265. p->chan->exception = ast->exception;
  266. if (ast->fdno == AST_MAX_FDS - 3)
  267. p->chan->fdno = AST_MAX_FDS - 2;
  268. else
  269. p->chan->fdno = ast->fdno;
  270. f = ast_read(p->chan);
  271. } else
  272. f = &null_frame;
  273. if (!f) {
  274. /* If there's a channel, hang it up (if it's on a callback) make it NULL */
  275. if (p->chan) {
  276. /* Note that we don't hangup if it's not a callback because Asterisk will do it
  277. for us when the PBX instance that called login finishes */
  278. if (strlen(p->loginchan))
  279. ast_hangup(p->chan);
  280. p->chan = NULL;
  281. p->acknowledged = 0;
  282. }
  283. }
  284. if (f && (f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_ANSWER)) {
  285. /* TC */
  286. if (p->ackcall) {
  287. if (option_verbose > 2)
  288. ast_verbose(VERBOSE_PREFIX_3 "%s answered, waiting for '#' to acknowledge\n", p->chan->name);
  289. /* Don't pass answer along */
  290. ast_frfree(f);
  291. f = &null_frame;
  292. }
  293. else {
  294. p->acknowledged = 1;
  295. f = &answer_frame;
  296. }
  297. }
  298. if (f && (f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) {
  299. if (!p->acknowledged) {
  300. if (option_verbose > 2)
  301. ast_verbose(VERBOSE_PREFIX_3 "%s acknowledged\n", p->chan->name);
  302. p->acknowledged = 1;
  303. ast_frfree(f);
  304. f = &answer_frame;
  305. }
  306. }
  307. if (f && (f->frametype == AST_FRAME_DTMF) && (f->subclass == '*')) {
  308. /* * terminates call */
  309. ast_frfree(f);
  310. f = NULL;
  311. }
  312. CLEANUP(ast,p);
  313. ast_mutex_unlock(&p->lock);
  314. if (recordagentcalls && f == &answer_frame)
  315. agent_start_monitoring(ast,0);
  316. return f;
  317. }
  318. static int agent_write(struct ast_channel *ast, struct ast_frame *f)
  319. {
  320. struct agent_pvt *p = ast->pvt->pvt;
  321. int res = -1;
  322. CHECK_FORMATS(ast, p);
  323. ast_mutex_lock(&p->lock);
  324. if (p->chan) {
  325. if ((f->frametype != AST_FRAME_VOICE) ||
  326. (f->subclass == p->chan->writeformat)) {
  327. res = ast_write(p->chan, f);
  328. } else {
  329. ast_log(LOG_DEBUG, "Dropping one incompatible voice frame on '%s' to '%s'\n", ast->name, p->chan->name);
  330. res = 0;
  331. }
  332. } else
  333. res = 0;
  334. CLEANUP(ast, p);
  335. ast_mutex_unlock(&p->lock);
  336. return res;
  337. }
  338. static int agent_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
  339. {
  340. struct agent_pvt *p = newchan->pvt->pvt;
  341. ast_mutex_lock(&p->lock);
  342. if (p->owner != oldchan) {
  343. ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, p->owner);
  344. ast_mutex_unlock(&p->lock);
  345. return -1;
  346. }
  347. p->owner = newchan;
  348. ast_mutex_unlock(&p->lock);
  349. return 0;
  350. }
  351. static int agent_indicate(struct ast_channel *ast, int condition)
  352. {
  353. struct agent_pvt *p = ast->pvt->pvt;
  354. int res = -1;
  355. ast_mutex_lock(&p->lock);
  356. if (p->chan)
  357. res = ast_indicate(p->chan, condition);
  358. else
  359. res = 0;
  360. ast_mutex_unlock(&p->lock);
  361. return res;
  362. }
  363. static int agent_digit(struct ast_channel *ast, char digit)
  364. {
  365. struct agent_pvt *p = ast->pvt->pvt;
  366. int res = -1;
  367. ast_mutex_lock(&p->lock);
  368. if (p->chan)
  369. res = p->chan->pvt->send_digit(p->chan, digit);
  370. else
  371. res = 0;
  372. ast_mutex_unlock(&p->lock);
  373. return res;
  374. }
  375. static int agent_call(struct ast_channel *ast, char *dest, int timeout)
  376. {
  377. struct agent_pvt *p = ast->pvt->pvt;
  378. int res = -1;
  379. ast_mutex_lock(&p->lock);
  380. p->acknowledged = 0;
  381. if (!p->chan) {
  382. if (p->pending) {
  383. ast_log(LOG_DEBUG, "Pretending to dial on pending agent\n");
  384. ast_setstate(ast, AST_STATE_DIALING);
  385. res = 0;
  386. } else {
  387. ast_log(LOG_NOTICE, "Whoa, they hung up between alloc and call... what are the odds of that?\n");
  388. res = -1;
  389. }
  390. ast_mutex_unlock(&p->lock);
  391. return res;
  392. } else if (strlen(p->loginchan)) {
  393. time(&p->start);
  394. /* Call on this agent */
  395. if (option_verbose > 2)
  396. ast_verbose(VERBOSE_PREFIX_3 "outgoing agentcall, to agent '%s', on '%s'\n", p->agent, p->chan->name);
  397. if (p->chan->callerid)
  398. free(p->chan->callerid);
  399. if (ast->callerid)
  400. p->chan->callerid = strdup(ast->callerid);
  401. else
  402. p->chan->callerid = NULL;
  403. res = ast_call(p->chan, p->loginchan, 0);
  404. CLEANUP(ast,p);
  405. ast_mutex_unlock(&p->lock);
  406. return res;
  407. }
  408. ast_verbose( VERBOSE_PREFIX_3 "agent_call, call to agent '%s' call on '%s'\n", p->agent, p->chan->name);
  409. ast_log( LOG_DEBUG, "Playing beep, lang '%s'\n", p->chan->language);
  410. res = ast_streamfile(p->chan, "beep", p->chan->language);
  411. ast_log( LOG_DEBUG, "Played beep, result '%d'\n", res);
  412. if (!res) {
  413. res = ast_waitstream(p->chan, "");
  414. ast_log( LOG_DEBUG, "Waited for stream, result '%d'\n", res);
  415. }
  416. if (!res) {
  417. res = ast_set_read_format(p->chan, ast_best_codec(p->chan->nativeformats));
  418. ast_log( LOG_DEBUG, "Set read format, result '%d'\n", res);
  419. if (res)
  420. ast_log(LOG_WARNING, "Unable to set read format to %s\n", ast_getformatname(ast_best_codec(p->chan->nativeformats)));
  421. } else {
  422. // Agent hung-up
  423. p->chan = NULL;
  424. }
  425. if (!res) {
  426. ast_set_write_format(p->chan, ast_best_codec(p->chan->nativeformats));
  427. ast_log( LOG_DEBUG, "Set write format, result '%d'\n", res);
  428. if (res)
  429. ast_log(LOG_WARNING, "Unable to set write format to %s\n", ast_getformatname(ast_best_codec(p->chan->nativeformats)));
  430. }
  431. if( !res )
  432. {
  433. /* Call is immediately up, or might need ack */
  434. if (p->ackcall > 1)
  435. ast_setstate(ast, AST_STATE_RINGING);
  436. else {
  437. ast_setstate(ast, AST_STATE_UP);
  438. if (recordagentcalls)
  439. agent_start_monitoring(ast,0);
  440. p->acknowledged = 1;
  441. }
  442. res = 0;
  443. }
  444. CLEANUP(ast,p);
  445. ast_mutex_unlock(&p->lock);
  446. return res;
  447. }
  448. static int agent_hangup(struct ast_channel *ast)
  449. {
  450. struct agent_pvt *p = ast->pvt->pvt;
  451. int howlong = 0;
  452. ast_mutex_lock(&p->lock);
  453. p->owner = NULL;
  454. ast->pvt->pvt = NULL;
  455. p->app_sleep_cond = 1;
  456. p->acknowledged = 0;
  457. if (p->start && (ast->_state != AST_STATE_UP))
  458. howlong = time(NULL) - p->start;
  459. time(&p->start);
  460. if (p->chan) {
  461. /* If they're dead, go ahead and hang up on the agent now */
  462. if (strlen(p->loginchan)) {
  463. if (p->chan) {
  464. /* Recognize the hangup and pass it along immediately */
  465. ast_hangup(p->chan);
  466. p->chan = NULL;
  467. }
  468. ast_log(LOG_DEBUG, "Hungup, howlong is %d, autologoff is %d\n", howlong, p->autologoff);
  469. if (howlong && p->autologoff && (howlong > p->autologoff)) {
  470. ast_log(LOG_NOTICE, "Agent '%s' didn't answer/confirm within %d seconds (waited %d)\n", p->name, p->autologoff, howlong);
  471. strcpy(p->loginchan, "");
  472. }
  473. } else if (p->dead) {
  474. ast_mutex_lock(&p->chan->lock);
  475. ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT);
  476. ast_mutex_unlock(&p->chan->lock);
  477. } else {
  478. ast_mutex_lock(&p->chan->lock);
  479. ast_moh_start(p->chan, p->moh);
  480. ast_mutex_unlock(&p->chan->lock);
  481. }
  482. }
  483. #if 0
  484. ast_mutex_unlock(&p->lock);
  485. /* Release ownership of the agent to other threads (presumably running the login app). */
  486. ast_mutex_unlock(&p->app_lock);
  487. } else if (p->dead) {
  488. /* Go ahead and lose it */
  489. ast_mutex_unlock(&p->lock);
  490. /* Release ownership of the agent to other threads (presumably running the login app). */
  491. ast_mutex_unlock(&p->app_lock);
  492. } else {
  493. ast_mutex_unlock(&p->lock);
  494. /* Release ownership of the agent to other threads (presumably running the login app). */
  495. ast_mutex_unlock(&p->app_lock);
  496. }
  497. #endif
  498. ast_mutex_unlock(&p->lock);
  499. if (p->pending) {
  500. ast_mutex_lock(&agentlock);
  501. agent_unlink(p);
  502. ast_mutex_unlock(&agentlock);
  503. }
  504. if (p->abouttograb) {
  505. /* Let the "about to grab" thread know this isn't valid anymore, and let it
  506. kill it later */
  507. p->abouttograb = 0;
  508. } else if (p->dead) {
  509. free(p);
  510. } else {
  511. if (p->chan) {
  512. /* Not dead -- check availability now */
  513. ast_mutex_lock(&p->lock);
  514. /* Store last disconnect time */
  515. gettimeofday(&p->lastdisc, NULL);
  516. ast_mutex_unlock(&p->lock);
  517. }
  518. /* Release ownership of the agent to other threads (presumably running the login app). */
  519. ast_mutex_unlock(&p->app_lock);
  520. }
  521. return 0;
  522. }
  523. static int agent_cont_sleep( void *data )
  524. {
  525. struct agent_pvt *p;
  526. struct timeval tv;
  527. int res;
  528. p = (struct agent_pvt *)data;
  529. ast_mutex_lock(&p->lock);
  530. res = p->app_sleep_cond;
  531. if (p->lastdisc.tv_sec) {
  532. gettimeofday(&tv, NULL);
  533. if ((tv.tv_sec - p->lastdisc.tv_sec) * 1000 +
  534. (tv.tv_usec - p->lastdisc.tv_usec) / 1000 > p->wrapuptime)
  535. res = 1;
  536. }
  537. ast_mutex_unlock(&p->lock);
  538. #if 0
  539. if( !res )
  540. ast_log( LOG_DEBUG, "agent_cont_sleep() returning %d\n", res );
  541. #endif
  542. return res;
  543. }
  544. static int agent_ack_sleep( void *data )
  545. {
  546. struct agent_pvt *p;
  547. int res=0;
  548. int to = 1000;
  549. struct ast_frame *f;
  550. /* Wait a second and look for something */
  551. p = (struct agent_pvt *)data;
  552. if (p->chan) {
  553. for(;;) {
  554. to = ast_waitfor(p->chan, to);
  555. if (to < 0) {
  556. res = -1;
  557. break;
  558. }
  559. if (!to) {
  560. res = 0;
  561. break;
  562. }
  563. f = ast_read(p->chan);
  564. if (!f) {
  565. res = -1;
  566. break;
  567. }
  568. if (f->frametype == AST_FRAME_DTMF)
  569. res = f->subclass;
  570. else
  571. res = 0;
  572. ast_frfree(f);
  573. ast_mutex_lock(&p->lock);
  574. if (!p->app_sleep_cond) {
  575. ast_mutex_unlock(&p->lock);
  576. res = 0;
  577. break;
  578. } else if (res == '#') {
  579. ast_mutex_unlock(&p->lock);
  580. res = 1;
  581. break;
  582. }
  583. ast_mutex_unlock(&p->lock);
  584. res = 0;
  585. }
  586. } else
  587. res = -1;
  588. return res;
  589. }
  590. static struct ast_channel *agent_new(struct agent_pvt *p, int state)
  591. {
  592. struct ast_channel *tmp;
  593. struct ast_frame null_frame = { AST_FRAME_NULL };
  594. #if 0
  595. if (!p->chan) {
  596. ast_log(LOG_WARNING, "No channel? :(\n");
  597. return NULL;
  598. }
  599. #endif
  600. tmp = ast_channel_alloc(0);
  601. if (tmp) {
  602. if (p->chan) {
  603. tmp->nativeformats = p->chan->nativeformats;
  604. tmp->writeformat = p->chan->writeformat;
  605. tmp->pvt->rawwriteformat = p->chan->writeformat;
  606. tmp->readformat = p->chan->readformat;
  607. tmp->pvt->rawreadformat = p->chan->readformat;
  608. strncpy(tmp->language, p->chan->language, sizeof(tmp->language)-1);
  609. strncpy(tmp->context, p->chan->context, sizeof(tmp->context)-1);
  610. strncpy(tmp->exten, p->chan->exten, sizeof(tmp->exten)-1);
  611. } else {
  612. tmp->nativeformats = AST_FORMAT_SLINEAR;
  613. tmp->writeformat = AST_FORMAT_SLINEAR;
  614. tmp->pvt->rawwriteformat = AST_FORMAT_SLINEAR;
  615. tmp->readformat = AST_FORMAT_SLINEAR;
  616. tmp->pvt->rawreadformat = AST_FORMAT_SLINEAR;
  617. }
  618. if (p->pending)
  619. snprintf(tmp->name, sizeof(tmp->name), "Agent/P%s-%d", p->agent, rand() & 0xffff);
  620. else
  621. snprintf(tmp->name, sizeof(tmp->name), "Agent/%s", p->agent);
  622. tmp->type = type;
  623. ast_setstate(tmp, state);
  624. tmp->pvt->pvt = p;
  625. tmp->pvt->send_digit = agent_digit;
  626. tmp->pvt->call = agent_call;
  627. tmp->pvt->hangup = agent_hangup;
  628. tmp->pvt->answer = agent_answer;
  629. tmp->pvt->read = agent_read;
  630. tmp->pvt->write = agent_write;
  631. tmp->pvt->exception = agent_read;
  632. tmp->pvt->indicate = agent_indicate;
  633. tmp->pvt->fixup = agent_fixup;
  634. p->owner = tmp;
  635. ast_mutex_lock(&usecnt_lock);
  636. usecnt++;
  637. ast_mutex_unlock(&usecnt_lock);
  638. ast_update_use_count();
  639. tmp->priority = 1;
  640. /* Wake up and wait for other applications (by definition the login app)
  641. * to release this channel). Takes ownership of the agent channel
  642. * to this thread only.
  643. * For signalling the other thread, ast_queue_frame is used until we
  644. * can safely use signals for this purpose. The pselect() needs to be
  645. * implemented in the kernel for this.
  646. */
  647. p->app_sleep_cond = 0;
  648. if( ast_mutex_trylock(&p->app_lock) )
  649. {
  650. if (p->chan) {
  651. ast_queue_frame(p->chan, &null_frame, 1);
  652. ast_mutex_unlock(&p->lock); /* For other thread to read the condition. */
  653. ast_mutex_lock(&p->app_lock);
  654. ast_mutex_lock(&p->lock);
  655. }
  656. if( !p->chan )
  657. {
  658. ast_log(LOG_WARNING, "Agent disconnected while we were connecting the call\n");
  659. p->owner = NULL;
  660. tmp->pvt->pvt = NULL;
  661. p->app_sleep_cond = 1;
  662. ast_channel_free( tmp );
  663. ast_mutex_unlock(&p->lock); /* For other thread to read the condition. */
  664. ast_mutex_unlock(&p->app_lock);
  665. return NULL;
  666. }
  667. }
  668. p->owning_app = pthread_self();
  669. /* After the above step, there should not be any blockers. */
  670. if (p->chan) {
  671. if (p->chan->blocking) {
  672. ast_log( LOG_ERROR, "A blocker exists after agent channel ownership acquired\n" );
  673. CRASH;
  674. }
  675. ast_moh_stop(p->chan);
  676. }
  677. } else
  678. ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
  679. return tmp;
  680. }
  681. static int read_agent_config(void)
  682. {
  683. struct ast_config *cfg;
  684. struct ast_variable *v;
  685. struct agent_pvt *p, *pl, *pn;
  686. group = 0;
  687. autologoff = 0;
  688. wrapuptime = 0;
  689. ackcall = 1;
  690. cfg = ast_load(config);
  691. if (!cfg) {
  692. ast_log(LOG_NOTICE, "No agent configuration found -- agent support disabled\n");
  693. return 0;
  694. }
  695. ast_mutex_lock(&agentlock);
  696. p = agents;
  697. while(p) {
  698. p->dead = 1;
  699. p = p->next;
  700. }
  701. strcpy(moh, "default");
  702. /* set the default recording values */
  703. recordagentcalls = 0;
  704. createlink = 0;
  705. strcpy(recordformat, "wav");
  706. strcpy(recordformatext, "wav");
  707. strcpy(urlprefix, "");
  708. strcpy(savecallsin, "");
  709. v = ast_variable_browse(cfg, "agents");
  710. while(v) {
  711. /* Create the interface list */
  712. if (!strcasecmp(v->name, "agent")) {
  713. add_agent(v->value, 0);
  714. } else if (!strcasecmp(v->name, "group")) {
  715. group = ast_get_group(v->value);
  716. } else if (!strcasecmp(v->name, "autologoff")) {
  717. autologoff = atoi(v->value);
  718. if (autologoff < 0)
  719. autologoff = 0;
  720. } else if (!strcasecmp(v->name, "ackcall")) {
  721. if (!strcasecmp(v->value, "always"))
  722. ackcall = 2;
  723. else if (ast_true(v->value))
  724. ackcall = 1;
  725. else
  726. ackcall = 0;
  727. } else if (!strcasecmp(v->name, "wrapuptime")) {
  728. wrapuptime = atoi(v->value);
  729. if (wrapuptime < 0)
  730. wrapuptime = 0;
  731. } else if (!strcasecmp(v->name, "musiconhold")) {
  732. strncpy(moh, v->value, sizeof(moh) - 1);
  733. } else if (!strcasecmp(v->name, "recordagentcalls")) {
  734. recordagentcalls = ast_true(v->value);
  735. } else if (!strcasecmp(v->name, "createlink")) {
  736. createlink = ast_true(v->value);
  737. } else if (!strcasecmp(v->name, "recordformat")) {
  738. strncpy(recordformat, v->value, sizeof(recordformat) - 1);
  739. if (!strcasecmp(v->value, "wav49"))
  740. strcpy(recordformatext, "WAV");
  741. else
  742. strncpy(recordformatext, v->value, sizeof(recordformat) - 1);
  743. } else if (!strcasecmp(v->name, "urlprefix")) {
  744. strncpy(urlprefix, v->value, sizeof(urlprefix) - 2);
  745. if (urlprefix[strlen(urlprefix) - 1] != '/')
  746. strcat(urlprefix, "/");
  747. } else if (!strcasecmp(v->name, "savecallsin")) {
  748. if (v->value[0] == '/')
  749. strncpy(savecallsin, v->value, sizeof(savecallsin) - 2);
  750. else
  751. snprintf(savecallsin, sizeof(savecallsin) - 2, "/%s", v->value);
  752. if (savecallsin[strlen(savecallsin) - 1] != '/')
  753. strcat(savecallsin, "/");
  754. }
  755. v = v->next;
  756. }
  757. p = agents;
  758. pl = NULL;
  759. while(p) {
  760. pn = p->next;
  761. if (p->dead) {
  762. /* Unlink */
  763. if (pl)
  764. pl->next = p->next;
  765. else
  766. agents = p->next;
  767. /* Destroy if appropriate */
  768. if (!p->owner) {
  769. if (!p->chan) {
  770. free(p);
  771. } else {
  772. /* Cause them to hang up */
  773. ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT);
  774. }
  775. }
  776. } else
  777. pl = p;
  778. p = pn;
  779. }
  780. ast_mutex_unlock(&agentlock);
  781. ast_destroy(cfg);
  782. return 0;
  783. }
  784. static int check_availability(struct agent_pvt *newlyavailable, int needlock)
  785. {
  786. struct ast_channel *chan=NULL, *parent=NULL;
  787. struct agent_pvt *p;
  788. int res;
  789. ast_log(LOG_DEBUG, "Checking availability of '%s'\n", newlyavailable->agent);
  790. if (needlock)
  791. ast_mutex_lock(&agentlock);
  792. p = agents;
  793. while(p) {
  794. if (p == newlyavailable) {
  795. p = p->next;
  796. continue;
  797. }
  798. ast_mutex_lock(&p->lock);
  799. if (!p->abouttograb && p->pending && ((p->group && (newlyavailable->group & p->group)) || !strcmp(p->agent, newlyavailable->agent))) {
  800. ast_log(LOG_DEBUG, "Call '%s' looks like a winner for agent '%s'\n", p->owner->name, newlyavailable->agent);
  801. /* We found a pending call, time to merge */
  802. chan = agent_new(newlyavailable, AST_STATE_DOWN);
  803. parent = p->owner;
  804. p->abouttograb = 1;
  805. ast_mutex_unlock(&p->lock);
  806. break;
  807. }
  808. ast_mutex_unlock(&p->lock);
  809. p = p->next;
  810. }
  811. if (needlock)
  812. ast_mutex_unlock(&agentlock);
  813. if (parent && chan) {
  814. if (newlyavailable->ackcall > 1) {
  815. /* Don't do beep here */
  816. res = 0;
  817. } else {
  818. ast_log( LOG_DEBUG, "Playing beep, lang '%s'\n", newlyavailable->chan->language);
  819. res = ast_streamfile(newlyavailable->chan, "beep", newlyavailable->chan->language);
  820. ast_log( LOG_DEBUG, "Played beep, result '%d'\n", res);
  821. if (!res) {
  822. res = ast_waitstream(newlyavailable->chan, "");
  823. ast_log( LOG_DEBUG, "Waited for stream, result '%d'\n", res);
  824. }
  825. }
  826. if (!res) {
  827. /* Note -- parent may have disappeared */
  828. if (p->abouttograb) {
  829. newlyavailable->acknowledged = 1;
  830. ast_setstate(parent, AST_STATE_UP);
  831. ast_setstate(chan, AST_STATE_UP);
  832. strncpy(parent->context, chan->context, sizeof(parent->context) - 1);
  833. /* Go ahead and mark the channel as a zombie so that masquerade will
  834. destroy it for us, and we need not call ast_hangup */
  835. ast_mutex_lock(&parent->lock);
  836. chan->zombie = 1;
  837. ast_channel_masquerade(parent, chan);
  838. ast_mutex_unlock(&parent->lock);
  839. p->abouttograb = 0;
  840. } else {
  841. ast_log(LOG_DEBUG, "Sneaky, parent disappeared in the mean time...\n");
  842. agent_cleanup(newlyavailable);
  843. }
  844. } else {
  845. ast_log(LOG_DEBUG, "Ugh... Agent hung up at exactly the wrong time\n");
  846. agent_cleanup(newlyavailable);
  847. }
  848. }
  849. return 0;
  850. }
  851. static int check_beep(struct agent_pvt *newlyavailable, int needlock)
  852. {
  853. struct agent_pvt *p;
  854. int res=0;
  855. ast_log(LOG_DEBUG, "Checking beep availability of '%s'\n", newlyavailable->agent);
  856. if (needlock)
  857. ast_mutex_lock(&agentlock);
  858. p = agents;
  859. while(p) {
  860. if (p == newlyavailable) {
  861. p = p->next;
  862. continue;
  863. }
  864. ast_mutex_lock(&p->lock);
  865. if (!p->abouttograb && p->pending && ((p->group && (newlyavailable->group & p->group)) || !strcmp(p->agent, newlyavailable->agent))) {
  866. ast_log(LOG_DEBUG, "Call '%s' looks like a would-be winner for agent '%s'\n", p->owner->name, newlyavailable->agent);
  867. ast_mutex_unlock(&p->lock);
  868. break;
  869. }
  870. ast_mutex_unlock(&p->lock);
  871. p = p->next;
  872. }
  873. if (needlock)
  874. ast_mutex_unlock(&agentlock);
  875. if (p) {
  876. ast_mutex_unlock(&newlyavailable->lock);
  877. ast_log( LOG_DEBUG, "Playing beep, lang '%s'\n", newlyavailable->chan->language);
  878. res = ast_streamfile(newlyavailable->chan, "beep", newlyavailable->chan->language);
  879. ast_log( LOG_DEBUG, "Played beep, result '%d'\n", res);
  880. if (!res) {
  881. res = ast_waitstream(newlyavailable->chan, "");
  882. ast_log( LOG_DEBUG, "Waited for stream, result '%d'\n", res);
  883. }
  884. ast_mutex_lock(&newlyavailable->lock);
  885. }
  886. return res;
  887. }
  888. static struct ast_channel *agent_request(char *type, int format, void *data)
  889. {
  890. struct agent_pvt *p;
  891. struct ast_channel *chan = NULL;
  892. char *s;
  893. unsigned int groupmatch;
  894. int waitforagent=0;
  895. int hasagent = 0;
  896. s = data;
  897. if ((s[0] == '@') && (sscanf(s + 1, "%d", &groupmatch) == 1)) {
  898. groupmatch = (1 << groupmatch);
  899. } else if ((s[0] == ':') && (sscanf(s + 1, "%d", &groupmatch) == 1)) {
  900. groupmatch = (1 << groupmatch);
  901. waitforagent = 1;
  902. } else {
  903. groupmatch = 0;
  904. }
  905. /* Check actual logged in agents first */
  906. ast_mutex_lock(&agentlock);
  907. p = agents;
  908. while(p) {
  909. ast_mutex_lock(&p->lock);
  910. if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent)) &&
  911. !strlen(p->loginchan)) {
  912. if (p->chan)
  913. hasagent++;
  914. if (!p->lastdisc.tv_sec) {
  915. /* Agent must be registered, but not have any active call, and not be in a waiting state */
  916. if (!p->owner && p->chan) {
  917. /* Fixed agent */
  918. chan = agent_new(p, AST_STATE_DOWN);
  919. }
  920. if (chan) {
  921. ast_mutex_unlock(&p->lock);
  922. break;
  923. }
  924. }
  925. }
  926. ast_mutex_unlock(&p->lock);
  927. p = p->next;
  928. }
  929. if (!p) {
  930. p = agents;
  931. while(p) {
  932. ast_mutex_lock(&p->lock);
  933. if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) {
  934. if (p->chan || strlen(p->loginchan))
  935. hasagent++;
  936. if (!p->lastdisc.tv_sec) {
  937. /* Agent must be registered, but not have any active call, and not be in a waiting state */
  938. if (!p->owner && p->chan) {
  939. /* Could still get a fixed agent */
  940. chan = agent_new(p, AST_STATE_DOWN);
  941. } else if (!p->owner && strlen(p->loginchan)) {
  942. /* Adjustable agent */
  943. p->chan = ast_request("Local", format, p->loginchan);
  944. if (p->chan)
  945. chan = agent_new(p, AST_STATE_DOWN);
  946. }
  947. if (chan) {
  948. ast_mutex_unlock(&p->lock);
  949. break;
  950. }
  951. }
  952. }
  953. ast_mutex_unlock(&p->lock);
  954. p = p->next;
  955. }
  956. }
  957. if (!chan && waitforagent) {
  958. /* No agent available -- but we're requesting to wait for one.
  959. Allocate a place holder */
  960. if (hasagent) {
  961. ast_log(LOG_DEBUG, "Creating place holder for '%s'\n", s);
  962. p = add_agent(data, 1);
  963. p->group = groupmatch;
  964. chan = agent_new(p, AST_STATE_DOWN);
  965. if (!chan) {
  966. ast_log(LOG_WARNING, "Weird... Fix this to drop the unused pending agent\n");
  967. }
  968. } else
  969. ast_log(LOG_DEBUG, "Not creating place holder for '%s' since nobody logged in\n", s);
  970. }
  971. ast_mutex_unlock(&agentlock);
  972. return chan;
  973. }
  974. static int powerof(unsigned int v)
  975. {
  976. int x;
  977. for (x=0;x<32;x++) {
  978. if (v & (1 << x)) return x;
  979. }
  980. return 0;
  981. }
  982. static int agents_show(int fd, int argc, char **argv)
  983. {
  984. struct agent_pvt *p;
  985. char username[AST_MAX_BUF];
  986. char location[AST_MAX_BUF];
  987. char talkingto[AST_MAX_BUF];
  988. char moh[AST_MAX_BUF];
  989. if (argc != 2)
  990. return RESULT_SHOWUSAGE;
  991. ast_mutex_lock(&agentlock);
  992. p = agents;
  993. while(p) {
  994. ast_mutex_lock(&p->lock);
  995. if (p->pending) {
  996. if (p->group)
  997. ast_cli(fd, "-- Pending call to group %d\n", powerof(p->group));
  998. else
  999. ast_cli(fd, "-- Pending call to agent %s\n", p->agent);
  1000. } else {
  1001. if (strlen(p->name))
  1002. snprintf(username, sizeof(username), "(%s) ", p->name);
  1003. else
  1004. strcpy(username, "");
  1005. if (p->chan) {
  1006. snprintf(location, sizeof(location), "logged in on %s", p->chan->name);
  1007. if (p->owner && p->owner->bridge) {
  1008. snprintf(talkingto, sizeof(talkingto), " talking to %s", p->owner->bridge->name);
  1009. } else {
  1010. strcpy(talkingto, " is idle");
  1011. }
  1012. } else if (strlen(p->loginchan)) {
  1013. snprintf(location, sizeof(location) - 20, "available at '%s'", p->loginchan);
  1014. strcpy(talkingto, "");
  1015. if (p->acknowledged)
  1016. strcat(location, " (Confirmed)");
  1017. } else {
  1018. strcpy(location, "not logged in");
  1019. strcpy(talkingto, "");
  1020. }
  1021. if (strlen(p->moh))
  1022. snprintf(moh, sizeof(moh), " (musiconhold is '%s')", p->moh);
  1023. ast_cli(fd, "%-12.12s %s%s%s%s\n", p->agent,
  1024. username, location, talkingto, moh);
  1025. }
  1026. ast_mutex_unlock(&p->lock);
  1027. p = p->next;
  1028. }
  1029. ast_mutex_unlock(&agentlock);
  1030. return RESULT_SUCCESS;
  1031. }
  1032. static char show_agents_usage[] =
  1033. "Usage: show agents\n"
  1034. " Provides summary information on agents.\n";
  1035. static struct ast_cli_entry cli_show_agents = {
  1036. { "show", "agents", NULL }, agents_show,
  1037. "Show status of agents", show_agents_usage, NULL };
  1038. STANDARD_LOCAL_USER;
  1039. LOCAL_USER_DECL;
  1040. static int __login_exec(struct ast_channel *chan, void *data, int callbackmode)
  1041. {
  1042. int res=0;
  1043. int tries = 0;
  1044. struct agent_pvt *p;
  1045. struct localuser *u;
  1046. struct timeval tv;
  1047. char user[AST_MAX_AGENT];
  1048. char pass[AST_MAX_AGENT];
  1049. char xpass[AST_MAX_AGENT] = "";
  1050. char *errmsg;
  1051. char info[512];
  1052. char *opt_user = NULL;
  1053. char *options = NULL;
  1054. char *context = NULL;
  1055. char *exten = NULL;
  1056. int play_announcement;
  1057. char *filename = "agent-loginok";
  1058. LOCAL_USER_ADD(u);
  1059. /* Parse the arguments XXX Check for failure XXX */
  1060. strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION-1);
  1061. opt_user = info;
  1062. if( opt_user ) {
  1063. options = strchr(opt_user, '|');
  1064. if (options) {
  1065. *options = '\0';
  1066. options++;
  1067. if (callbackmode) {
  1068. context = strchr(options, '@');
  1069. if (context) {
  1070. *context = '\0';
  1071. context++;
  1072. }
  1073. exten = options;
  1074. while(*exten && ((*exten < '0') || (*exten > '9'))) exten++;
  1075. if (!*exten)
  1076. exten = NULL;
  1077. }
  1078. }
  1079. }
  1080. if (chan->_state != AST_STATE_UP)
  1081. res = ast_answer(chan);
  1082. if (!res) {
  1083. if( opt_user && strlen(opt_user))
  1084. strncpy( user, opt_user, AST_MAX_AGENT );
  1085. else
  1086. res = ast_app_getdata(chan, "agent-user", user, sizeof(user) - 1, 0);
  1087. }
  1088. while (!res && (tries < 3)) {
  1089. /* Check for password */
  1090. ast_mutex_lock(&agentlock);
  1091. p = agents;
  1092. while(p) {
  1093. if (!strcmp(p->agent, user) && !p->pending)
  1094. strncpy(xpass, p->password, sizeof(xpass) - 1);
  1095. p = p->next;
  1096. }
  1097. ast_mutex_unlock(&agentlock);
  1098. if (!res) {
  1099. if (strlen(xpass))
  1100. res = ast_app_getdata(chan, "agent-pass", pass, sizeof(pass) - 1, 0);
  1101. else
  1102. strcpy(pass, "");
  1103. }
  1104. errmsg = "agent-incorrect";
  1105. #if 0
  1106. ast_log(LOG_NOTICE, "user: %s, pass: %s\n", user, pass);
  1107. #endif
  1108. /* Check again for accuracy */
  1109. ast_mutex_lock(&agentlock);
  1110. p = agents;
  1111. while(p) {
  1112. ast_mutex_lock(&p->lock);
  1113. if (!strcmp(p->agent, user) &&
  1114. !strcmp(p->password, pass) && !p->pending) {
  1115. if (!p->chan) {
  1116. if (callbackmode) {
  1117. char tmpchan[AST_MAX_BUF] = "";
  1118. int pos = 0;
  1119. /* Retrieve login chan */
  1120. for (;;) {
  1121. if (exten) {
  1122. strncpy(tmpchan, exten, sizeof(tmpchan) - 1);
  1123. res = 0;
  1124. } else
  1125. res = ast_app_getdata(chan, "agent-newlocation", tmpchan+pos, sizeof(tmpchan) - 2, 0);
  1126. if (!strlen(tmpchan) || ast_exists_extension(chan, context && strlen(context) ? context : "default", tmpchan,
  1127. 1, NULL))
  1128. break;
  1129. if (exten) {
  1130. ast_log(LOG_WARNING, "Extension '%s' is not valid for automatic login of agent '%s'\n", exten, p->agent);
  1131. exten = NULL;
  1132. pos = 0;
  1133. } else {
  1134. res = ast_streamfile(chan, "invalid", chan->language);
  1135. if (!res)
  1136. res = ast_waitstream(chan, AST_DIGIT_ANY);
  1137. if (res > 0) {
  1138. tmpchan[0] = res;
  1139. tmpchan[1] = '\0';
  1140. pos = 1;
  1141. } else {
  1142. tmpchan[0] = '\0';
  1143. pos = 0;
  1144. }
  1145. }
  1146. }
  1147. if (!res) {
  1148. if (context && strlen(context) && strlen(tmpchan))
  1149. snprintf(p->loginchan, sizeof(p->loginchan), "%s@%s", tmpchan, context);
  1150. else
  1151. strncpy(p->loginchan, tmpchan, sizeof(p->loginchan) - 1);
  1152. if (!strlen(p->loginchan))
  1153. filename = "agent-loggedoff";
  1154. p->acknowledged = 0;
  1155. }
  1156. } else {
  1157. strcpy(p->loginchan, "");
  1158. p->acknowledged = 0;
  1159. }
  1160. play_announcement = 1;
  1161. if( options )
  1162. if( strchr( options, 's' ) )
  1163. play_announcement = 0;
  1164. ast_mutex_unlock(&p->lock);
  1165. ast_mutex_unlock(&agentlock);
  1166. if( !res && play_announcement )
  1167. res = ast_streamfile(chan, filename, chan->language);
  1168. if (!res)
  1169. ast_waitstream(chan, "");
  1170. ast_mutex_lock(&agentlock);
  1171. ast_mutex_lock(&p->lock);
  1172. if (!res) {
  1173. res = ast_set_read_format(chan, ast_best_codec(chan->nativeformats));
  1174. if (res)
  1175. ast_log(LOG_WARNING, "Unable to set read format to %d\n", ast_best_codec(chan->nativeformats));
  1176. }
  1177. if (!res) {
  1178. ast_set_write_format(chan, ast_best_codec(chan->nativeformats));
  1179. if (res)
  1180. ast_log(LOG_WARNING, "Unable to set write format to %d\n", ast_best_codec(chan->nativeformats));
  1181. }
  1182. /* Check once more just in case */
  1183. if (p->chan)
  1184. res = -1;
  1185. if (callbackmode && !res) {
  1186. /* Just say goodbye and be done with it */
  1187. ast_mutex_unlock(&agentlock);
  1188. if (!res)
  1189. res = ast_safe_sleep(chan, 500);
  1190. res = ast_streamfile(chan, "vm-goodbye", chan->language);
  1191. if (!res)
  1192. res = ast_waitstream(chan, "");
  1193. if (!res)
  1194. res = ast_safe_sleep(chan, 1000);
  1195. ast_mutex_unlock(&p->lock);
  1196. } else if (!res) {
  1197. #ifdef HONOR_MUSIC_CLASS
  1198. /* check if the moh class was changed with setmusiconhold */
  1199. if (*(chan->musicclass))
  1200. strncpy(p->moh, chan->musicclass, sizeof(p->moh) - 1);
  1201. #endif
  1202. ast_moh_start(chan, p->moh);
  1203. manager_event(EVENT_FLAG_AGENT, "Agentlogin",
  1204. "Agent: %s\r\n"
  1205. "Channel: %s\r\n",
  1206. p->agent, chan->name);
  1207. if (option_verbose > 2)
  1208. ast_verbose(VERBOSE_PREFIX_3 "Agent '%s' logged in (format %s/%s)\n", p->agent,
  1209. ast_getformatname(chan->readformat), ast_getformatname(chan->writeformat));
  1210. /* Login this channel and wait for it to
  1211. go away */
  1212. p->chan = chan;
  1213. if (p->ackcall > 1)
  1214. check_beep(p, 0);
  1215. else
  1216. check_availability(p, 0);
  1217. ast_mutex_unlock(&p->lock);
  1218. ast_mutex_unlock(&agentlock);
  1219. while (res >= 0) {
  1220. ast_mutex_lock(&p->lock);
  1221. if (p->chan != chan)
  1222. res = -1;
  1223. ast_mutex_unlock(&p->lock);
  1224. /* Yield here so other interested threads can kick in. */
  1225. sched_yield();
  1226. if (res)
  1227. break;
  1228. ast_mutex_lock(&agentlock);
  1229. ast_mutex_lock(&p->lock);
  1230. if (p->lastdisc.tv_sec) {
  1231. gettimeofday(&tv, NULL);
  1232. if ((tv.tv_sec - p->lastdisc.tv_sec) * 1000 +
  1233. (tv.tv_usec - p->lastdisc.tv_usec) / 1000 > p->wrapuptime) {
  1234. ast_log(LOG_DEBUG, "Wrapup time expired!\n");
  1235. memset(&p->lastdisc, 0, sizeof(p->lastdisc));
  1236. if (p->ackcall > 1)
  1237. check_beep(p, 0);
  1238. else
  1239. check_availability(p, 0);
  1240. }
  1241. }
  1242. ast_mutex_unlock(&p->lock);
  1243. ast_mutex_unlock(&agentlock);
  1244. /* Synchronize channel ownership between call to agent and itself. */
  1245. ast_mutex_lock( &p->app_lock );
  1246. ast_mutex_lock(&p->lock);
  1247. p->owning_app = pthread_self();
  1248. ast_mutex_unlock(&p->lock);
  1249. if (p->ackcall > 1)
  1250. res = agent_ack_sleep(p);
  1251. else
  1252. res = ast_safe_sleep_conditional( chan, 1000,
  1253. agent_cont_sleep, p );
  1254. ast_mutex_unlock( &p->app_lock );
  1255. if ((p->ackcall > 1) && (res == 1)) {
  1256. ast_mutex_lock(&agentlock);
  1257. ast_mutex_lock(&p->lock);
  1258. check_availability(p, 0);
  1259. ast_mutex_unlock(&p->lock);
  1260. ast_mutex_unlock(&agentlock);
  1261. res = 0;
  1262. }
  1263. sched_yield();
  1264. }
  1265. ast_mutex_lock(&p->lock);
  1266. if (res && p->owner)
  1267. ast_log(LOG_WARNING, "Huh? We broke out when there was still an owner?\n");
  1268. /* Log us off if appropriate */
  1269. if (p->chan == chan)
  1270. p->chan = NULL;
  1271. p->acknowledged = 0;
  1272. ast_mutex_unlock(&p->lock);
  1273. if (option_verbose > 2)
  1274. ast_verbose(VERBOSE_PREFIX_3 "Agent '%s' logged out\n", p->agent);
  1275. manager_event(EVENT_FLAG_AGENT, "Agentlogoff",
  1276. "Agent: %s\r\n",
  1277. p->agent);
  1278. /* If there is no owner, go ahead and kill it now */
  1279. if (p->dead && !p->owner)
  1280. free(p);
  1281. }
  1282. else {
  1283. ast_mutex_unlock(&p->lock);
  1284. p = NULL;
  1285. }
  1286. res = -1;
  1287. } else {
  1288. ast_mutex_unlock(&p->lock);
  1289. errmsg = "agent-alreadyon";
  1290. p = NULL;
  1291. }
  1292. break;
  1293. }
  1294. ast_mutex_unlock(&p->lock);
  1295. p = p->next;
  1296. }
  1297. if (!p)
  1298. ast_mutex_unlock(&agentlock);
  1299. if (!res)
  1300. res = ast_app_getdata(chan, errmsg, user, sizeof(user) - 1, 0);
  1301. }
  1302. LOCAL_USER_REMOVE(u);
  1303. /* Always hangup */
  1304. return -1;
  1305. }
  1306. static int login_exec(struct ast_channel *chan, void *data)
  1307. {
  1308. return __login_exec(chan, data, 0);
  1309. }
  1310. static int callback_exec(struct ast_channel *chan, void *data)
  1311. {
  1312. return __login_exec(chan, data, 1);
  1313. }
  1314. int load_module()
  1315. {
  1316. /* Make sure we can register our sip channel type */
  1317. if (ast_channel_register(type, tdesc, capability, agent_request)) {
  1318. ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
  1319. return -1;
  1320. }
  1321. ast_register_application(app, login_exec, synopsis, descrip);
  1322. ast_register_application(app2, callback_exec, synopsis2, descrip2);
  1323. ast_cli_register(&cli_show_agents);
  1324. /* Read in the config */
  1325. read_agent_config();
  1326. return 0;
  1327. }
  1328. int reload()
  1329. {
  1330. read_agent_config();
  1331. return 0;
  1332. }
  1333. int unload_module()
  1334. {
  1335. struct agent_pvt *p;
  1336. /* First, take us out of the channel loop */
  1337. ast_cli_unregister(&cli_show_agents);
  1338. ast_unregister_application(app);
  1339. ast_unregister_application(app2);
  1340. ast_channel_unregister(type);
  1341. if (!ast_mutex_lock(&agentlock)) {
  1342. /* Hangup all interfaces if they have an owner */
  1343. p = agents;
  1344. while(p) {
  1345. if (p->owner)
  1346. ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
  1347. p = p->next;
  1348. }
  1349. agents = NULL;
  1350. ast_mutex_unlock(&agentlock);
  1351. } else {
  1352. ast_log(LOG_WARNING, "Unable to lock the monitor\n");
  1353. return -1;
  1354. }
  1355. return 0;
  1356. }
  1357. int usecount()
  1358. {
  1359. int res;
  1360. ast_mutex_lock(&usecnt_lock);
  1361. res = usecnt;
  1362. ast_mutex_unlock(&usecnt_lock);
  1363. return res;
  1364. }
  1365. char *key()
  1366. {
  1367. return ASTERISK_GPL_KEY;
  1368. }
  1369. char *description()
  1370. {
  1371. return desc;
  1372. }