Review Board 1.7.16


Remove dead code in chan_agent

Review Request #267 - Created May 29, 2009 and submitted

Eliel SardaƱons
Reviewers
asterisk-dev
Asterisk
AgentCallbacklogin was deprecated, but a lot of code regarding that functionality wasn't removed.
Agents are dump in the astdb only if there are logged in with AgentCallbacklogin (not used code).
ackcall could have three values:
ackcall=yes, ackcall=always and ackcall=no Now it is not needed anymore leave always for backward compatibility but make 'yes' work like 'always'.
It is not needed anymore to load agents from the astdb because we are not saving them.
loginchan is being used only by AgentCallbacklogin, is the user is logged with AgentLogin then loginchan is NULL.
Login an agent, receive a call from a queue with and without the ackcall option setted.

Diff revision 1 (Latest)

  1. /trunk/channels/chan_agent.c: Loading...
  2. /trunk/configs/agents.conf.sample: Loading...
/trunk/channels/chan_agent.c
Revision 197925 New Change
[20] 209 lines
[+20] [+] static char moh[80] = "default";
210
#define AST_MAX_FILENAME_LEN	256
210
#define AST_MAX_FILENAME_LEN	256
211

    
   
211

   
212
static const char pa_family[] = "Agents";          /*!< Persistent Agents astdb family */
212
static const char pa_family[] = "Agents";          /*!< Persistent Agents astdb family */
213
#define PA_MAX_LEN 2048                             /*!< The maximum length of each persistent member agent database entry */
213
#define PA_MAX_LEN 2048                             /*!< The maximum length of each persistent member agent database entry */
214

    
   
214

   
215
static int persistent_agents = 0;                   /*!< queues.conf [general] option */

   
216
static void dump_agents(void);

   
217

    
   

   
218
#define DEFAULT_ACCEPTDTMF '#'
215
#define DEFAULT_ACCEPTDTMF '#'
219
#define DEFAULT_ENDDTMF '*'
216
#define DEFAULT_ENDDTMF '*'
220

    
   
217

   
221
static ast_group_t group;
218
static ast_group_t group;
222
static int autologoff;
219
static int autologoff;
[+20] [20] 50 lines
[+20] [+] struct agent_pvt {
273
	ast_mutex_t app_lock;          /**< Synchronization between owning applications */
270
	ast_mutex_t app_lock;          /**< Synchronization between owning applications */
274
	int app_lock_flag;
271
	int app_lock_flag;
275
	ast_cond_t app_complete_cond;
272
	ast_cond_t app_complete_cond;
276
	volatile int app_sleep_cond;   /**< Sleep condition for the login app */
273
	volatile int app_sleep_cond;   /**< Sleep condition for the login app */
277
	struct ast_channel *owner;     /**< Agent */
274
	struct ast_channel *owner;     /**< Agent */
278
	char loginchan[80];            /**< channel they logged in from */

   
279
	char logincallerid[80];        /**< Caller ID they had when they logged in */
275
	char logincallerid[80];        /**< Caller ID they had when they logged in */
280
	struct ast_channel *chan;      /**< Channel we use */
276
	struct ast_channel *chan;      /**< Channel we use */
281
	unsigned int flags;            /**< Flags show if settings were applied with channel vars */
277
	unsigned int flags;            /**< Flags show if settings were applied with channel vars */
282
	AST_LIST_ENTRY(agent_pvt) list;	/**< Next Agent in the linked list. */
278
	AST_LIST_ENTRY(agent_pvt) list;	/**< Next Agent in the linked list. */
283
};
279
};
[+20] [20] 33 lines
[+20] [+] static AST_LIST_HEAD_STATIC(agents, agent_pvt); /*!< Holds the list of agents (loaded form agents.conf). */
317
} while(0)
313
} while(0)
318

    
   
314

   
319
/*--- Forward declarations */
315
/*--- Forward declarations */
320
static struct ast_channel *agent_request(const char *type, int format, void *data, int *cause);
316
static struct ast_channel *agent_request(const char *type, int format, void *data, int *cause);
321
static int agent_devicestate(void *data);
317
static int agent_devicestate(void *data);
322
static void agent_logoff_maintenance(struct agent_pvt *p, char *loginchan, long logintime, const char *uniqueid, char *logcommand);

   
323
static int agent_digit_begin(struct ast_channel *ast, char digit);
318
static int agent_digit_begin(struct ast_channel *ast, char digit);
324
static int agent_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
319
static int agent_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
325
static int agent_call(struct ast_channel *ast, char *dest, int timeout);
320
static int agent_call(struct ast_channel *ast, char *dest, int timeout);
326
static int agent_hangup(struct ast_channel *ast);
321
static int agent_hangup(struct ast_channel *ast);
327
static int agent_answer(struct ast_channel *ast);
322
static int agent_answer(struct ast_channel *ast);
328
static struct ast_frame *agent_read(struct ast_channel *ast);
323
static struct ast_frame *agent_read(struct ast_channel *ast);
329
static int agent_write(struct ast_channel *ast, struct ast_frame *f);
324
static int agent_write(struct ast_channel *ast, struct ast_frame *f);
330
static int agent_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen);
325
static int agent_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen);
331
static int agent_sendtext(struct ast_channel *ast, const char *text);
326
static int agent_sendtext(struct ast_channel *ast, const char *text);
332
static int agent_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);
327
static int agent_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);
333
static int agent_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
328
static int agent_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
334
static struct ast_channel *agent_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge);
329
static struct ast_channel *agent_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge);
335
static void set_agentbycallerid(const char *callerid, const char *agent);

   
336
static char *complete_agent_logoff_cmd(const char *line, const char *word, int pos, int state);
330
static char *complete_agent_logoff_cmd(const char *line, const char *word, int pos, int state);
337
static struct ast_channel* agent_get_base_channel(struct ast_channel *chan);
331
static struct ast_channel* agent_get_base_channel(struct ast_channel *chan);
338
static int agent_set_base_channel(struct ast_channel *chan, struct ast_channel *base);
332
static int agent_set_base_channel(struct ast_channel *chan, struct ast_channel *base);
339
static int agent_logoff(const char *agent, int soft);
333
static int agent_logoff(const char *agent, int soft);
340

    
   
334

   
[+20] [20] 196 lines
[+20] [+] static int agent_start_monitoring(struct ast_channel *ast, int needlock)
537
static struct ast_frame *agent_read(struct ast_channel *ast)
531
static struct ast_frame *agent_read(struct ast_channel *ast)
538
{
532
{
539
	struct agent_pvt *p = ast->tech_pvt;
533
	struct agent_pvt *p = ast->tech_pvt;
540
	struct ast_frame *f = NULL;
534
	struct ast_frame *f = NULL;
541
	static struct ast_frame answer_frame = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
535
	static struct ast_frame answer_frame = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
542
	const char *status;

   
543
	int cur_time = time(NULL);
536
	int cur_time = time(NULL);
544
	ast_mutex_lock(&p->lock);
537
	ast_mutex_lock(&p->lock);
545
	CHECK_FORMATS(ast, p);
538
	CHECK_FORMATS(ast, p);
546
	if (!p->start) {
539
	if (!p->start) {
547
		p->start = cur_time;
540
		p->start = cur_time;
548
	}
541
	}
549
	if (p->chan) {
542
	if (p->chan) {
550
		ast_copy_flags(p->chan, ast, AST_FLAG_EXCEPTION);
543
		ast_copy_flags(p->chan, ast, AST_FLAG_EXCEPTION);
551
		p->chan->fdno = (ast->fdno == AST_AGENT_FD) ? AST_TIMING_FD : ast->fdno;
544
		p->chan->fdno = (ast->fdno == AST_AGENT_FD) ? AST_TIMING_FD : ast->fdno;
552
		f = ast_read(p->chan);
545
		f = ast_read(p->chan);
553
	} else
546
	} else
554
		f = &ast_null_frame;
547
		f = &ast_null_frame;
555
	if (!f) {
548
	if (!f) {
556
		/* If there's a channel, hang it up (if it's on a callback) make it NULL */
549
		/* If there's a channel, make it NULL */
557
		if (p->chan) {
550
		if (p->chan) {
558
			p->chan->_bridge = NULL;
551
			p->chan->_bridge = NULL;
559
			/* Note that we don't hangup if it's not a callback because Asterisk will do it

   
560
			   for us when the PBX instance that called login finishes */

   
561
			if (!ast_strlen_zero(p->loginchan)) {

   
562
				if (p->chan)

   
563
					ast_debug(1, "Bridge on '%s' being cleared (2)\n", p->chan->name);

   
564
				if (p->owner->_state != AST_STATE_UP) {

   
565
					int howlong = cur_time - p->start;

   
566
					if (p->autologoff && howlong >= p->autologoff) {

   
567
						p->loginstart = 0;

   
568
							ast_log(LOG_NOTICE, "Agent '%s' didn't answer/confirm within %d seconds (waited %d)\n", p->name, p->autologoff, howlong);

   
569
						agent_logoff_maintenance(p, p->loginchan, (cur_time = p->loginstart), ast->uniqueid, "Autologoff");

   
570
					}

   
571
				}

   
572
				status = pbx_builtin_getvar_helper(p->chan, "CHANLOCALSTATUS");

   
573
				if (autologoffunavail && status && !strcasecmp(status, "CHANUNAVAIL")) {

   
574
					long logintime = cur_time - p->loginstart;

   
575
					p->loginstart = 0;

   
576
					ast_log(LOG_NOTICE, "Agent read: '%s' is not available now, auto logoff\n", p->name);

   
577
					agent_logoff_maintenance(p, p->loginchan, logintime, ast->uniqueid, "Chanunavail");

   
578
				}

   
579
				ast_hangup(p->chan);

   
580
				if (p->wrapuptime && p->acknowledged)

   
581
					p->lastdisc = ast_tvadd(ast_tvnow(), ast_samp2tv(p->wrapuptime, 1000));

   
582
			}

   
583
			p->chan = NULL;
552
			p->chan = NULL;
584
			ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "Agent/%s", p->agent);
553
			ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "Agent/%s", p->agent);
585
			p->acknowledged = 0;
554
			p->acknowledged = 0;
586
		}
555
		}
587
	} else {
556
	} else {
[+20] [20] 5 lines
[+20] static struct ast_frame *agent_read(struct ast_channel *ast)
593

    
   
562

   
594
		if (!p->acknowledged) {
563
		if (!p->acknowledged) {
595
			int howlong = cur_time - p->start;
564
			int howlong = cur_time - p->start;
596
			if (p->autologoff && (howlong >= p->autologoff)) {
565
			if (p->autologoff && (howlong >= p->autologoff)) {
597
				ast_log(LOG_NOTICE, "Agent '%s' didn't answer/confirm within %d seconds (waited %d)\n", p->name, p->autologoff, howlong);
566
				ast_log(LOG_NOTICE, "Agent '%s' didn't answer/confirm within %d seconds (waited %d)\n", p->name, p->autologoff, howlong);
598
				agent_logoff_maintenance(p, p->loginchan, (cur_time - p->loginstart), ast->uniqueid, "Autologoff");

   
599
				agent_logoff(p->agent, 0);
567
				agent_logoff(p->agent, 0);
600
			}
568
			}
601
		}
569
		}
602
		switch (f->frametype) {
570
		switch (f->frametype) {
603
		case AST_FRAME_CONTROL:
571
		case AST_FRAME_CONTROL:
[+20] [20] 178 lines
[+20] [+] static int agent_call(struct ast_channel *ast, char *dest, int timeout)
782
		}
750
		}
783
		ast_mutex_unlock(&p->lock);
751
		ast_mutex_unlock(&p->lock);
784
		if (newstate)
752
		if (newstate)
785
			ast_setstate(ast, newstate);
753
			ast_setstate(ast, newstate);
786
		return res;
754
		return res;
787
	} else if (!ast_strlen_zero(p->loginchan)) {

   
788
		time(&p->start);

   
789
		/* Call on this agent */

   
790
		ast_verb(3, "outgoing agentcall, to agent '%s', on '%s'\n", p->agent, p->chan->name);

   
791
		ast_channel_set_connected_line(p->chan, &ast->connected);

   
792
		ast_channel_inherit_variables(ast, p->chan);

   
793
		res = ast_call(p->chan, p->loginchan, 0);

   
794
		CLEANUP(ast,p);

   
795
		ast_mutex_unlock(&p->lock);

   
796
		return res;

   
797
	}
755
	}
798
	ast_verb(3, "agent_call, call to agent '%s' call on '%s'\n", p->agent, p->chan->name);
756
	ast_verb(3, "agent_call, call to agent '%s' call on '%s'\n", p->agent, p->chan->name);
799
	ast_debug(3, "Playing beep, lang '%s'\n", p->chan->language);
757
	ast_debug(3, "Playing beep, lang '%s'\n", p->chan->language);
800
	res = ast_streamfile(p->chan, beep, p->chan->language);
758
	res = ast_streamfile(p->chan, beep, p->chan->language);
801
	ast_debug(3, "Played beep, result '%d'\n", res);
759
	ast_debug(3, "Played beep, result '%d'\n", res);
[+20] [20] 18 lines
[+20] static int agent_call(struct ast_channel *ast, char *dest, int timeout)
820
		if (res)
778
		if (res)
821
			ast_log(LOG_WARNING, "Unable to set write format to %s\n", ast_getformatname(ast_best_codec(p->chan->nativeformats)));
779
			ast_log(LOG_WARNING, "Unable to set write format to %s\n", ast_getformatname(ast_best_codec(p->chan->nativeformats)));
822
	}
780
	}
823
	if(!res) {
781
	if(!res) {
824
		/* Call is immediately up, or might need ack */
782
		/* Call is immediately up, or might need ack */
825
		if (p->ackcall > 1)
783
		if (p->ackcall) {
826
			newstate = AST_STATE_RINGING;
784
			newstate = AST_STATE_RINGING;
827
		else {
785
		} else {
828
			newstate = AST_STATE_UP;
786
			newstate = AST_STATE_UP;
829
			if (recordagentcalls)
787
			if (recordagentcalls)
830
				agent_start_monitoring(ast, 0);
788
				agent_start_monitoring(ast, 0);
831
			p->acknowledged = 1;
789
			p->acknowledged = 1;
832
		}
790
		}
[+20] [20] 4 lines
[+20] static int agent_call(struct ast_channel *ast, char *dest, int timeout)
837
	if (newstate)
795
	if (newstate)
838
		ast_setstate(ast, newstate);
796
		ast_setstate(ast, newstate);
839
	return res;
797
	return res;
840
}
798
}
841

    
   
799

   
842
/*! \brief store/clear the global variable that stores agentid based on the callerid */

   
843
static void set_agentbycallerid(const char *callerid, const char *agent)

   
844
{

   
845
	char buf[AST_MAX_BUF];

   
846

    
   

   
847
	/* if there is no Caller ID, nothing to do */

   
848
	if (ast_strlen_zero(callerid))

   
849
		return;

   
850

    
   

   
851
	snprintf(buf, sizeof(buf), "%s_%s", GETAGENTBYCALLERID, callerid);

   
852
	pbx_builtin_setvar_helper(NULL, buf, agent);

   
853
}

   
854

    
   

   
855
/*! \brief return the channel or base channel if one exists.  This function assumes the channel it is called on is already locked */
800
/*! \brief return the channel or base channel if one exists.  This function assumes the channel it is called on is already locked */
856
struct ast_channel* agent_get_base_channel(struct ast_channel *chan)
801
struct ast_channel* agent_get_base_channel(struct ast_channel *chan)
857
{
802
{
858
	struct agent_pvt *p = NULL;
803
	struct agent_pvt *p = NULL;
859
	struct ast_channel *base = chan;
804
	struct ast_channel *base = chan;
[+20] [20] 28 lines
[+20] [+] int agent_set_base_channel(struct ast_channel *chan, struct ast_channel *base)
888

    
   
833

   
889
static int agent_hangup(struct ast_channel *ast)
834
static int agent_hangup(struct ast_channel *ast)
890
{
835
{
891
	struct agent_pvt *p = ast->tech_pvt;
836
	struct agent_pvt *p = ast->tech_pvt;
892
	int howlong = 0;
837
	int howlong = 0;
893
	const char *status;
838

   
894
	ast_mutex_lock(&p->lock);
839
	ast_mutex_lock(&p->lock);
895
	p->owner = NULL;
840
	p->owner = NULL;
896
	ast->tech_pvt = NULL;
841
	ast->tech_pvt = NULL;
897
	p->app_sleep_cond = 1;
842
	p->app_sleep_cond = 1;
898
	p->acknowledged = 0;
843
	p->acknowledged = 0;
[+20] [20] 14 lines
[+20] static int agent_hangup(struct ast_channel *ast)
913
	else
858
	else
914
		p->start = 0; 
859
		p->start = 0; 
915
	if (p->chan) {
860
	if (p->chan) {
916
		p->chan->_bridge = NULL;
861
		p->chan->_bridge = NULL;
917
		/* If they're dead, go ahead and hang up on the agent now */
862
		/* If they're dead, go ahead and hang up on the agent now */
918
		if (!ast_strlen_zero(p->loginchan)) {
863
		if (p->dead) {
919
			/* Store last disconnect time */

   
920
			if (p->wrapuptime)

   
921
				p->lastdisc = ast_tvadd(ast_tvnow(), ast_samp2tv(p->wrapuptime, 1000));

   
922
			else

   
923
				p->lastdisc = ast_tv(0,0);

   
924
			if (p->chan) {

   
925
				status = pbx_builtin_getvar_helper(p->chan, "CHANLOCALSTATUS");

   
926
				if (autologoffunavail && status && !strcasecmp(status, "CHANUNAVAIL")) {

   
927
					long logintime = time(NULL) - p->loginstart;

   
928
					p->loginstart = 0;

   
929
					ast_log(LOG_NOTICE, "Agent hangup: '%s' is not available now, auto logoff\n", p->name);

   
930
					agent_logoff_maintenance(p, p->loginchan, logintime, ast->uniqueid, "Chanunavail");

   
931
				}

   
932
				/* Recognize the hangup and pass it along immediately */

   
933
				ast_hangup(p->chan);

   
934
				p->chan = NULL;

   
935
				ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "Agent/%s", p->agent);

   
936
			}

   
937
			ast_debug(1, "Hungup, howlong is %d, autologoff is %d\n", howlong, p->autologoff);

   
938
			if ((p->deferlogoff) || (howlong && p->autologoff && (howlong > p->autologoff))) {

   
939
				long logintime = time(NULL) - p->loginstart;

   
940
				p->loginstart = 0;

   
941
				if (!p->deferlogoff)

   
942
					ast_log(LOG_NOTICE, "Agent '%s' didn't answer/confirm within %d seconds (waited %d)\n", p->name, p->autologoff, howlong);

   
943
				p->deferlogoff = 0;

   
944
				agent_logoff_maintenance(p, p->loginchan, logintime, ast->uniqueid, "Autologoff");

   
945
				if (persistent_agents)

   
946
					dump_agents();

   
947
			}

   
948
		} else if (p->dead) {

   
949
			ast_channel_lock(p->chan);
864
			ast_channel_lock(p->chan);
950
			ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT);
865
			ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT);
951
			ast_channel_unlock(p->chan);
866
			ast_channel_unlock(p->chan);
952
		} else if (p->loginstart) {
867
		} else if (p->loginstart) {
953
			ast_channel_lock(p->chan);
868
			ast_channel_lock(p->chan);
[+20] [20] 5 lines
[+20] static int agent_hangup(struct ast_channel *ast)
959
	}
874
	}
960
	ast_mutex_unlock(&p->lock);
875
	ast_mutex_unlock(&p->lock);
961

    
   
876

   
962
	/* Only register a device state change if the agent is still logged in */
877
	/* Only register a device state change if the agent is still logged in */
963
	if (!p->loginstart) {
878
	if (!p->loginstart) {
964
		p->loginchan[0] = '\0';

   
965
		p->logincallerid[0] = '\0';
879
		p->logincallerid[0] = '\0';
966
		if (persistent_agents)

   
967
			dump_agents();

   
968
	} else {
880
	} else {
969
		ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Agent/%s", p->agent);
881
		ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Agent/%s", p->agent);
970
	}
882
	}
971

    
   
883

   
972
	if (p->pending) {
884
	if (p->pending) {
[+20] [20] 17 lines
[+20] static int agent_hangup(struct ast_channel *ast)
990
			/* Store last disconnect time */
902
			/* Store last disconnect time */
991
			p->lastdisc = ast_tvadd(ast_tvnow(), ast_samp2tv(p->wrapuptime, 1000));
903
			p->lastdisc = ast_tvadd(ast_tvnow(), ast_samp2tv(p->wrapuptime, 1000));
992
			ast_mutex_unlock(&p->lock);
904
			ast_mutex_unlock(&p->lock);
993
		}
905
		}
994
		/* Release ownership of the agent to other threads (presumably running the login app). */
906
		/* Release ownership of the agent to other threads (presumably running the login app). */
995
		if (ast_strlen_zero(p->loginchan)) {

   
996
			p->app_lock_flag = 0;
907
		p->app_lock_flag = 0;
997
			ast_cond_signal(&p->app_complete_cond);
908
		ast_cond_signal(&p->app_complete_cond);
998
		}
909
	}
999
	}

   
1000
	return 0;
910
	return 0;
1001
}
911
}
1002

    
   
912

   
1003
static int agent_cont_sleep( void *data )
913
static int agent_cont_sleep( void *data )
1004
{
914
{
[+20] [20] 125 lines
[+20] [+] static struct ast_channel *agent_new(struct agent_pvt *p, int state)
1130
	p->app_sleep_cond = 0;
1040
	p->app_sleep_cond = 0;
1131

    
   
1041

   
1132
	alreadylocked = p->app_lock_flag;
1042
	alreadylocked = p->app_lock_flag;
1133
	p->app_lock_flag = 1;
1043
	p->app_lock_flag = 1;
1134

    
   
1044

   
1135
	if(ast_strlen_zero(p->loginchan) && alreadylocked) {
1045
	if (alreadylocked) {
1136
		if (p->chan) {
1046
		if (p->chan) {
1137
			ast_queue_frame(p->chan, &ast_null_frame);
1047
			ast_queue_frame(p->chan, &ast_null_frame);
1138
			ast_mutex_unlock(&p->lock);	/* For other thread to read the condition. */
1048
			ast_mutex_unlock(&p->lock);	/* For other thread to read the condition. */
1139
			p->app_lock_flag = 1;
1049
			p->app_lock_flag = 1;
1140
			ast_mutex_lock(&p->lock);
1050
			ast_mutex_lock(&p->lock);
[+20] [20] 6 lines
[+20] static struct ast_channel *agent_new(struct agent_pvt *p, int state)
1147
			ast_mutex_unlock(&p->lock);	/* For other thread to read the condition. */
1057
			ast_mutex_unlock(&p->lock);	/* For other thread to read the condition. */
1148
			p->app_lock_flag = 0;
1058
			p->app_lock_flag = 0;
1149
			ast_cond_signal(&p->app_complete_cond);
1059
			ast_cond_signal(&p->app_complete_cond);
1150
			return NULL;
1060
			return NULL;
1151
		}
1061
		}
1152
	} else if (!ast_strlen_zero(p->loginchan)) {

   
1153
		if (p->chan)

   
1154
			ast_queue_frame(p->chan, &ast_null_frame);

   
1155
		if (!p->chan) {

   
1156
			ast_log(LOG_WARNING, "Agent disconnected while we were connecting the call\n");

   
1157
			p->owner = NULL;

   
1158
			tmp->tech_pvt = NULL;

   
1159
			p->app_sleep_cond = 1;

   
1160
			tmp = ast_channel_release(tmp);

   
1161
			ast_mutex_unlock(&p->lock);     /* For other thread to read the condition. */

   
1162
			return NULL;

   
1163
		}	

   
1164
	} 
1062
	} 
1165
	if (p->chan)
1063
	if (p->chan)
1166
		ast_indicate(p->chan, AST_CONTROL_UNHOLD);
1064
		ast_indicate(p->chan, AST_CONTROL_UNHOLD);
1167
	return tmp;
1065
	return tmp;
1168
}
1066
}
[+20] [20] 8 lines
[+20] static struct ast_channel *agent_new(struct agent_pvt *p, int state)
1177
{
1075
{
1178
	struct ast_config *cfg;
1076
	struct ast_config *cfg;
1179
	struct ast_config *ucfg;
1077
	struct ast_config *ucfg;
1180
	struct ast_variable *v;
1078
	struct ast_variable *v;
1181
	struct agent_pvt *p;
1079
	struct agent_pvt *p;
1182
	const char *general_val;

   
1183
	const char *catname;
1080
	const char *catname;
1184
	const char *hasagent;
1081
	const char *hasagent;
1185
	int genhasagent;
1082
	int genhasagent;
1186
	struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
1083
	struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
1187

    
   
1084

   
[+20] [20] 32 lines
[+20] static struct ast_channel *agent_new(struct agent_pvt *p, int state)
1220
	strcpy(recordformatext, "wav");
1117
	strcpy(recordformatext, "wav");
1221
	urlprefix[0] = '\0';
1118
	urlprefix[0] = '\0';
1222
	savecallsin[0] = '\0';
1119
	savecallsin[0] = '\0';
1223

    
   
1120

   
1224
	/* Read in [general] section for persistence */
1121
	/* Read in [general] section for persistence */
1225
	if ((general_val = ast_variable_retrieve(cfg, "general", "persistentagents")))

   
1226
		persistent_agents = ast_true(general_val);

   
1227
	multiplelogin = ast_true(ast_variable_retrieve(cfg, "general", "multiplelogin"));
1122
	multiplelogin = ast_true(ast_variable_retrieve(cfg, "general", "multiplelogin"));
1228

    
   
1123

   
1229
	/* Read in the [agents] section */
1124
	/* Read in the [agents] section */
1230
	v = ast_variable_browse(cfg, "agents");
1125
	v = ast_variable_browse(cfg, "agents");
1231
	while(v) {
1126
	while(v) {
[+20] [20] 5 lines
[+20] static struct ast_channel *agent_new(struct agent_pvt *p, int state)
1237
		} else if (!strcasecmp(v->name, "autologoff")) {
1132
		} else if (!strcasecmp(v->name, "autologoff")) {
1238
			autologoff = atoi(v->value);
1133
			autologoff = atoi(v->value);
1239
			if (autologoff < 0)
1134
			if (autologoff < 0)
1240
				autologoff = 0;
1135
				autologoff = 0;
1241
		} else if (!strcasecmp(v->name, "ackcall")) {
1136
		} else if (!strcasecmp(v->name, "ackcall")) {
1242
			if (!strcasecmp(v->value, "always"))
1137
			if (ast_true(v->value) || !strcasecmp(v->value, "always")) {
1243
				ackcall = 2;

   
1244
			else if (ast_true(v->value))

   
1245
				ackcall = 1;
1138
				ackcall = 1;
1246
			else
1139
			}
1247
				ackcall = 0;

   
1248
		} else if (!strcasecmp(v->name, "endcall")) {
1140
		} else if (!strcasecmp(v->name, "endcall")) {
1249
			endcall = ast_true(v->value);
1141
			endcall = ast_true(v->value);
1250
		} else if (!strcasecmp(v->name, "acceptdtmf")) {
1142
		} else if (!strcasecmp(v->name, "acceptdtmf")) {
1251
			acceptdtmf = *(v->value);
1143
			acceptdtmf = *(v->value);
1252
			ast_log(LOG_NOTICE, "Set acceptdtmf to %c\n", acceptdtmf);
1144
			ast_log(LOG_NOTICE, "Set acceptdtmf to %c\n", acceptdtmf);
[+20] [20] 116 lines
[+20] [+] static int check_availability(struct agent_pvt *newlyavailable, int needlock)
1369
		ast_mutex_unlock(&p->lock);
1261
		ast_mutex_unlock(&p->lock);
1370
	}
1262
	}
1371
	if (needlock)
1263
	if (needlock)
1372
		AST_LIST_UNLOCK(&agents);
1264
		AST_LIST_UNLOCK(&agents);
1373
	if (parent && chan)  {
1265
	if (parent && chan)  {
1374
		if (newlyavailable->ackcall > 1) {
1266
		if (newlyavailable->ackcall) {
1375
			/* Don't do beep here */
1267
			/* Don't do beep here */
1376
			res = 0;
1268
			res = 0;
1377
		} else {
1269
		} else {
1378
			ast_debug(3, "Playing beep, lang '%s'\n", newlyavailable->chan->language);
1270
			ast_debug(3, "Playing beep, lang '%s'\n", newlyavailable->chan->language);
1379
			res = ast_streamfile(newlyavailable->chan, beep, newlyavailable->chan->language);
1271
			res = ast_streamfile(newlyavailable->chan, beep, newlyavailable->chan->language);
[+20] [20] 87 lines
[+20] [+] static struct ast_channel *agent_request(const char *type, int format, void *data, int *cause)
1467

    
   
1359

   
1468
	/* Check actual logged in agents first */
1360
	/* Check actual logged in agents first */
1469
	AST_LIST_LOCK(&agents);
1361
	AST_LIST_LOCK(&agents);
1470
	AST_LIST_TRAVERSE(&agents, p, list) {
1362
	AST_LIST_TRAVERSE(&agents, p, list) {
1471
		ast_mutex_lock(&p->lock);
1363
		ast_mutex_lock(&p->lock);
1472
		if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent)) &&
1364
		if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) {
1473
		    ast_strlen_zero(p->loginchan)) {

   
1474
			if (p->chan)
1365
			if (p->chan)
1475
				hasagent++;
1366
				hasagent++;
1476
			now = ast_tvnow();
1367
			now = ast_tvnow();
1477
			if (!p->lastdisc.tv_sec || (now.tv_sec >= p->lastdisc.tv_sec)) {
1368
			if (!p->lastdisc.tv_sec || (now.tv_sec >= p->lastdisc.tv_sec)) {
1478
				p->lastdisc = ast_tv(0, 0);
1369
				p->lastdisc = ast_tv(0, 0);
[+20] [20] 12 lines
[+20] static struct ast_channel *agent_request(const char *type, int format, void *data, int *cause)
1491
	}
1382
	}
1492
	if (!p) {
1383
	if (!p) {
1493
		AST_LIST_TRAVERSE(&agents, p, list) {
1384
		AST_LIST_TRAVERSE(&agents, p, list) {
1494
			ast_mutex_lock(&p->lock);
1385
			ast_mutex_lock(&p->lock);
1495
			if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) {
1386
			if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) {
1496
				if (p->chan || !ast_strlen_zero(p->loginchan))
1387
				if (p->chan) {
1497
					hasagent++;
1388
					hasagent++;

    
   
1389
				}
1498
				now = ast_tvnow();
1390
				now = ast_tvnow();
1499
#if 0

   
1500
				ast_log(LOG_NOTICE, "Time now: %ld, Time of lastdisc: %ld\n", now.tv_sec, p->lastdisc.tv_sec);

   
1501
#endif

   
1502
				if (!p->lastdisc.tv_sec || (now.tv_sec >= p->lastdisc.tv_sec)) {
1391
				if (!p->lastdisc.tv_sec || (now.tv_sec >= p->lastdisc.tv_sec)) {
1503
					p->lastdisc = ast_tv(0, 0);
1392
					p->lastdisc = ast_tv(0, 0);
1504
					/* Agent must be registered, but not have any active call, and not be in a waiting state */
1393
					/* Agent must be registered, but not have any active call, and not be in a waiting state */
1505
					if (!p->owner && p->chan) {
1394
					if (!p->owner && p->chan) {
1506
						/* Could still get a fixed agent */
1395
						/* Could still get a fixed agent */
1507
						chan = agent_new(p, AST_STATE_DOWN);
1396
						chan = agent_new(p, AST_STATE_DOWN);
1508
					} else if (!p->owner && !ast_strlen_zero(p->loginchan)) {

   
1509
						/* Adjustable agent */

   
1510
						p->chan = ast_request("Local", format, p->loginchan, cause);

   
1511
						if (p->chan)

   
1512
							chan = agent_new(p, AST_STATE_DOWN);

   
1513
					}
1397
					}
1514
					if (chan) {
1398
					if (chan) {
1515
						ast_mutex_unlock(&p->lock);
1399
						ast_mutex_unlock(&p->lock);
1516
						break;
1400
						break;
1517
					}
1401
					}
[+20] [20] 42 lines
[+20] [+] static force_inline int powerof(unsigned int d)
1560
 */
1444
 */
1561
static int action_agents(struct mansession *s, const struct message *m)
1445
static int action_agents(struct mansession *s, const struct message *m)
1562
{
1446
{
1563
	const char *id = astman_get_header(m,"ActionID");
1447
	const char *id = astman_get_header(m,"ActionID");
1564
	char idText[256] = "";
1448
	char idText[256] = "";
1565
	char chanbuf[256];

   
1566
	struct agent_pvt *p;
1449
	struct agent_pvt *p;
1567
	char *username = NULL;
1450
	char *username = NULL;
1568
	char *loginChan = NULL;
1451
	char *loginChan = NULL;
1569
	char *talkingto = NULL;
1452
	char *talkingto = NULL;
1570
	char *talkingtoChan = NULL;
1453
	char *talkingtoChan = NULL;
[+20] [20] 15 lines
[+20] static int action_agents(struct mansession *s, const struct message *m)
1586
		username = S_OR(p->name, "None");
1469
		username = S_OR(p->name, "None");
1587

    
   
1470

   
1588
		/* Set a default status. It 'should' get changed. */
1471
		/* Set a default status. It 'should' get changed. */
1589
		status = "AGENT_UNKNOWN";
1472
		status = "AGENT_UNKNOWN";
1590

    
   
1473

   
1591
		if (!ast_strlen_zero(p->loginchan) && !p->chan) {
1474
		if (p->chan) {
1592
			loginChan = p->loginchan;

   
1593
			talkingto = "n/a";

   
1594
			talkingtoChan = "n/a";

   
1595
			status = "AGENT_IDLE";

   
1596
			if (p->acknowledged) {

   
1597
				snprintf(chanbuf, sizeof(chanbuf), " %s (Confirmed)", p->loginchan);

   
1598
				loginChan = chanbuf;

   
1599
			}

   
1600
		} else if (p->chan) {

   
1601
			loginChan = ast_strdupa(p->chan->name);
1475
			loginChan = ast_strdupa(p->chan->name);
1602
			if (p->owner && p->owner->_bridge) {
1476
			if (p->owner && p->owner->_bridge) {
1603
				talkingto = p->chan->cid.cid_num;
1477
				talkingto = p->chan->cid.cid_num;
1604
				if (ast_bridged_channel(p->owner))
1478
				if (ast_bridged_channel(p->owner))
1605
					talkingtoChan = ast_strdupa(ast_bridged_channel(p->owner)->name);
1479
					talkingtoChan = ast_strdupa(ast_bridged_channel(p->owner)->name);
[+20] [20] 30 lines
[+20] static int action_agents(struct mansession *s, const struct message *m)
1636
		"%s"
1510
		"%s"
1637
		"\r\n",idText);
1511
		"\r\n",idText);
1638
	return 0;
1512
	return 0;
1639
}
1513
}
1640

    
   
1514

   
1641
static void agent_logoff_maintenance(struct agent_pvt *p, char *loginchan, long logintime, const char *uniqueid, char *logcommand)

   
1642
{

   
1643
	char *tmp = NULL;

   
1644
	char agent[AST_MAX_AGENT];

   
1645

    
   

   
1646
	if (!ast_strlen_zero(logcommand))

   
1647
		tmp = logcommand;

   
1648
	else

   
1649
		tmp = ast_strdupa("");

   
1650

    
   

   
1651
	snprintf(agent, sizeof(agent), "Agent/%s", p->agent);

   
1652

    
   

   
1653
	if (!ast_strlen_zero(uniqueid)) {

   
1654
		manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogoff",

   
1655
				"Agent: %s\r\n"

   
1656
				"Reason: %s\r\n"

   
1657
				"Loginchan: %s\r\n"

   
1658
				"Logintime: %ld\r\n"

   
1659
				"Uniqueid: %s\r\n", 

   
1660
				p->agent, tmp, loginchan, logintime, uniqueid);

   
1661
	} else {

   
1662
		manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogoff",

   
1663
				"Agent: %s\r\n"

   
1664
				"Reason: %s\r\n"

   
1665
				"Loginchan: %s\r\n"

   
1666
				"Logintime: %ld\r\n",

   
1667
				p->agent, tmp, loginchan, logintime);

   
1668
	}

   
1669

    
   

   
1670
	ast_queue_log("NONE", ast_strlen_zero(uniqueid) ? "NONE" : uniqueid, agent, "AGENTCALLBACKLOGOFF", "%s|%ld|%s", loginchan, logintime, tmp);

   
1671
	set_agentbycallerid(p->logincallerid, NULL);

   
1672
	p->loginchan[0] ='\0';

   
1673
	p->logincallerid[0] = '\0';

   
1674
	ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "Agent/%s", p->agent);

   
1675
	if (persistent_agents)

   
1676
		dump_agents();

   
1677

    
   

   
1678
}

   
1679

    
   

   
1680
static int agent_logoff(const char *agent, int soft)
1515
static int agent_logoff(const char *agent, int soft)
1681
{
1516
{
1682
	struct agent_pvt *p;
1517
	struct agent_pvt *p;
1683
	long logintime;

   
1684
	int ret = -1; /* Return -1 if no agent if found */
1518
	int ret = -1; /* Return -1 if no agent if found */
1685

    
   
1519

   
1686
	AST_LIST_LOCK(&agents);
1520
	AST_LIST_LOCK(&agents);
1687
	AST_LIST_TRAVERSE(&agents, p, list) {
1521
	AST_LIST_TRAVERSE(&agents, p, list) {
1688
		if (!strcasecmp(p->agent, agent)) {
1522
		if (!strcasecmp(p->agent, agent)) {
[+20] [20] 19 lines
[+20] static int agent_logoff(const char *agent, int soft)
1708
					}
1542
					}
1709

    
   
1543

   
1710
					ast_mutex_unlock(&p->lock);
1544
					ast_mutex_unlock(&p->lock);
1711
				} else
1545
				} else
1712
					p->deferlogoff = 1;
1546
					p->deferlogoff = 1;
1713
			} else {

   
1714
				logintime = time(NULL) - p->loginstart;

   
1715
				p->loginstart = 0;

   
1716
				agent_logoff_maintenance(p, p->loginchan, logintime, NULL, "CommandLogoff");

   
1717
			}
1547
			}
1718
			break;
1548
			break;
1719
		}
1549
		}
1720
	}
1550
	}
1721
	AST_LIST_UNLOCK(&agents);
1551
	AST_LIST_UNLOCK(&agents);
[+20] [20] 131 lines
[+20] [+] static char *agents_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1853
				if (p->owner && ast_bridged_channel(p->owner))
1683
				if (p->owner && ast_bridged_channel(p->owner))
1854
					snprintf(talkingto, sizeof(talkingto), " talking to %s", ast_bridged_channel(p->owner)->name);
1684
					snprintf(talkingto, sizeof(talkingto), " talking to %s", ast_bridged_channel(p->owner)->name);
1855
				 else 
1685
				 else 
1856
					strcpy(talkingto, " is idle");
1686
					strcpy(talkingto, " is idle");
1857
				online_agents++;
1687
				online_agents++;
1858
			} else if (!ast_strlen_zero(p->loginchan)) {

   
1859
				if (ast_tvdiff_ms(ast_tvnow(), p->lastdisc) > 0 || !(p->lastdisc.tv_sec)) 

   
1860
					snprintf(location, sizeof(location) - 20, "available at '%s'", p->loginchan);

   
1861
				else 

   
1862
					snprintf(location, sizeof(location) - 20, "wrapping up at '%s'", p->loginchan);

   
1863
				talkingto[0] = '\0';

   
1864
				online_agents++;

   
1865
				if (p->acknowledged)

   
1866
					strncat(location, " (Confirmed)", sizeof(location) - strlen(location) - 1);

   
1867
			} else {
1688
			} else {
1868
				strcpy(location, "not logged in");
1689
				strcpy(location, "not logged in");
1869
				talkingto[0] = '\0';
1690
				talkingto[0] = '\0';
1870
				offline_agents++;
1691
				offline_agents++;
1871
			}
1692
			}
[+20] [20] 55 lines
[+20] [+] static char *agents_show_online(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1927
				snprintf(talkingto, sizeof(talkingto), " talking to %s", ast_bridged_channel(p->owner)->name);
1748
				snprintf(talkingto, sizeof(talkingto), " talking to %s", ast_bridged_channel(p->owner)->name);
1928
			else 
1749
			else 
1929
				strcpy(talkingto, " is idle");
1750
				strcpy(talkingto, " is idle");
1930
			agent_status = 1;
1751
			agent_status = 1;
1931
			online_agents++;
1752
			online_agents++;
1932
		} else if (!ast_strlen_zero(p->loginchan)) {

   
1933
			snprintf(location, sizeof(location) - 20, "available at '%s'", p->loginchan);

   
1934
			talkingto[0] = '\0';

   
1935
			agent_status = 1;

   
1936
			online_agents++;

   
1937
			if (p->acknowledged)

   
1938
				strncat(location, " (Confirmed)", sizeof(location) - strlen(location) - 1);

   
1939
		}
1753
		}
1940
		if (!ast_strlen_zero(p->moh))
1754
		if (!ast_strlen_zero(p->moh))
1941
			snprintf(music, sizeof(music), " (musiconhold is '%s')", p->moh);
1755
			snprintf(music, sizeof(music), " (musiconhold is '%s')", p->moh);
1942
		if (agent_status)
1756
		if (agent_status)
1943
			ast_cli(a->fd, "%-12.12s %s%s%s%s\n", p->agent, username, location, talkingto, music);
1757
			ast_cli(a->fd, "%-12.12s %s%s%s%s\n", p->agent, username, location, talkingto, music);
[+20] [20] 137 lines
[+20] [+] static int login_exec(struct ast_channel *chan, const char *data)
2081
				p->lastdisc = ast_tvnow();
1895
				p->lastdisc = ast_tvnow();
2082
				p->lastdisc.tv_sec++;
1896
				p->lastdisc.tv_sec++;
2083

    
   
1897

   
2084
				/* Set Channel Specific Agent Overrides */
1898
				/* Set Channel Specific Agent Overrides */
2085
				if (!ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"))) {
1899
				if (!ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"))) {
2086
					if (!strcasecmp(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"), "always"))
1900
					if (ast_true(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"))) {
2087
						p->ackcall = 2;

   
2088
					else if (ast_true(pbx_builtin_getvar_helper(chan, "AGENTACKCALL")))

   
2089
						p->ackcall = 1;
1901
						p->ackcall = 1;
2090
					else
1902
					} else {
2091
						p->ackcall = 0;
1903
						p->ackcall = 0;

    
   
1904
					}
2092
					tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTACKCALL");
1905
					tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTACKCALL");
2093
					ast_verb(3, "Saw variable AGENTACKCALL=%s, setting ackcall to: %d for Agent '%s'.\n", tmpoptions, p->ackcall, p->agent);
1906
					ast_verb(3, "Saw variable AGENTACKCALL=%s, setting ackcall to: %d for Agent '%s'.\n", tmpoptions, p->ackcall, p->agent);
2094
					ast_set_flag(p, AGENT_FLAG_ACKCALL);
1907
					ast_set_flag(p, AGENT_FLAG_ACKCALL);
2095
				} else {
1908
				} else {
2096
					p->ackcall = ackcall;
1909
					p->ackcall = ackcall;
[+20] [20] 35 lines
[+20] static int login_exec(struct ast_channel *chan, const char *data)
2132
				/* End Channel Specific Agent Overrides */
1945
				/* End Channel Specific Agent Overrides */
2133
				if (!p->chan) {
1946
				if (!p->chan) {
2134
					long logintime;
1947
					long logintime;
2135
					snprintf(agent, sizeof(agent), "Agent/%s", p->agent);
1948
					snprintf(agent, sizeof(agent), "Agent/%s", p->agent);
2136

    
   
1949

   
2137
					p->loginchan[0] = '\0';

   
2138
					p->logincallerid[0] = '\0';
1950
					p->logincallerid[0] = '\0';
2139
					p->acknowledged = 0;
1951
					p->acknowledged = 0;
2140
					
1952
					
2141
					ast_mutex_unlock(&p->lock);
1953
					ast_mutex_unlock(&p->lock);
2142
					AST_LIST_UNLOCK(&agents);
1954
					AST_LIST_UNLOCK(&agents);
[+20] [20] 32 lines
[+20] static int login_exec(struct ast_channel *chan, const char *data)
2175
						ast_queue_log("NONE", chan->uniqueid, agent, "AGENTLOGIN", "%s", chan->name);
1987
						ast_queue_log("NONE", chan->uniqueid, agent, "AGENTLOGIN", "%s", chan->name);
2176
						ast_verb(2, "Agent '%s' logged in (format %s/%s)\n", p->agent,
1988
						ast_verb(2, "Agent '%s' logged in (format %s/%s)\n", p->agent,
2177
								    ast_getformatname(chan->readformat), ast_getformatname(chan->writeformat));
1989
								    ast_getformatname(chan->readformat), ast_getformatname(chan->writeformat));
2178
						/* Login this channel and wait for it to go away */
1990
						/* Login this channel and wait for it to go away */
2179
						p->chan = chan;
1991
						p->chan = chan;
2180
						if (p->ackcall > 1)
1992
						if (p->ackcall) {
2181
							check_beep(p, 0);
1993
							check_beep(p, 0);
2182
						else
1994
						} else {
2183
							check_availability(p, 0);
1995
							check_availability(p, 0);

    
   
1996
						}
2184
						ast_mutex_unlock(&p->lock);
1997
						ast_mutex_unlock(&p->lock);
2185
						AST_LIST_UNLOCK(&agents);
1998
						AST_LIST_UNLOCK(&agents);
2186
						ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Agent/%s", p->agent);
1999
						ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Agent/%s", p->agent);
2187
						while (res >= 0) {
2000
						while (res >= 0) {
2188
							ast_mutex_lock(&p->lock);
2001
							ast_mutex_lock(&p->lock);
[+20] [20] 14 lines
[+20] static int login_exec(struct ast_channel *chan, const char *data)
2203
							if (p->lastdisc.tv_sec) {
2016
							if (p->lastdisc.tv_sec) {
2204
								if (ast_tvdiff_ms(ast_tvnow(), p->lastdisc) > 0) {
2017
								if (ast_tvdiff_ms(ast_tvnow(), p->lastdisc) > 0) {
2205
									ast_debug(1, "Wrapup time for %s expired!\n", p->agent);
2018
									ast_debug(1, "Wrapup time for %s expired!\n", p->agent);
2206
									p->lastdisc = ast_tv(0, 0);
2019
									p->lastdisc = ast_tv(0, 0);
2207
									ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Agent/%s", p->agent);
2020
									ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Agent/%s", p->agent);
2208
									if (p->ackcall > 1)
2021
									if (p->ackcall) {
2209
										check_beep(p, 0);
2022
										check_beep(p, 0);
2210
									else
2023
									} else {
2211
										check_availability(p, 0);
2024
										check_availability(p, 0);
2212
								}
2025
									}
2213
							}
2026
								}

    
   
2027
							}
2214
							ast_mutex_unlock(&p->lock);
2028
							ast_mutex_unlock(&p->lock);
2215
							AST_LIST_UNLOCK(&agents);
2029
							AST_LIST_UNLOCK(&agents);
2216
							/*	Synchronize channel ownership between call to agent and itself. */
2030
							/*	Synchronize channel ownership between call to agent and itself. */
2217
							ast_mutex_lock(&p->app_lock);
2031
							ast_mutex_lock(&p->app_lock);
2218
							if (p->app_lock_flag == 1) {
2032
							if (p->app_lock_flag == 1) {
2219
								ast_cond_wait(&p->app_complete_cond, &p->app_lock);
2033
								ast_cond_wait(&p->app_complete_cond, &p->app_lock);
2220
							}
2034
							}
2221
							ast_mutex_unlock(&p->app_lock);
2035
							ast_mutex_unlock(&p->app_lock);
2222
							ast_mutex_lock(&p->lock);
2036
							ast_mutex_lock(&p->lock);
2223
							ast_mutex_unlock(&p->lock);
2037
							ast_mutex_unlock(&p->lock);
2224
							if (p->ackcall > 1) 
2038
							if (p->ackcall) {
2225
								res = agent_ack_sleep(p);
2039
								res = agent_ack_sleep(p);
2226
							else
2040
							} else {
2227
								res = ast_safe_sleep_conditional( chan, 1000, agent_cont_sleep, p );
2041
								res = ast_safe_sleep_conditional( chan, 1000, agent_cont_sleep, p );
2228
							if ((p->ackcall > 1)  && (res == 1)) {
2042
							}

    
   
2043
							if (p->ackcall && (res == 1)) {
2229
								AST_LIST_LOCK(&agents);
2044
								AST_LIST_LOCK(&agents);
2230
								ast_mutex_lock(&p->lock);
2045
								ast_mutex_lock(&p->lock);
2231
								check_availability(p, 0);
2046
								check_availability(p, 0);
2232
								ast_mutex_unlock(&p->lock);
2047
								ast_mutex_unlock(&p->lock);
2233
								AST_LIST_UNLOCK(&agents);
2048
								AST_LIST_UNLOCK(&agents);
[+20] [20] 116 lines
[+20] [+] static int agentmonitoroutgoing_exec(struct ast_channel *chan, const char *data)
2350
			return res;
2165
			return res;
2351
	}
2166
	}
2352
	return 0;
2167
	return 0;
2353
}
2168
}
2354

    
   
2169

   
2355
/*!

   
2356
 * \brief Dump AgentCallbackLogin agents to the ASTdb database for persistence

   
2357
 */

   
2358
static void dump_agents(void)

   
2359
{

   
2360
	struct agent_pvt *cur_agent = NULL;

   
2361
	char buf[256];

   
2362

    
   

   
2363
	AST_LIST_TRAVERSE(&agents, cur_agent, list) {

   
2364
		if (cur_agent->chan)

   
2365
			continue;

   
2366

    
   

   
2367
		if (!ast_strlen_zero(cur_agent->loginchan)) {

   
2368
			snprintf(buf, sizeof(buf), "%s;%s", cur_agent->loginchan, cur_agent->logincallerid);

   
2369
			if (ast_db_put(pa_family, cur_agent->agent, buf))

   
2370
				ast_log(LOG_WARNING, "failed to create persistent entry in ASTdb for %s!\n", buf);

   
2371
			else

   
2372
				ast_debug(1, "Saved Agent: %s on %s\n", cur_agent->agent, cur_agent->loginchan);

   
2373
		} else {

   
2374
			/* Delete -  no agent or there is an error */

   
2375
			ast_db_del(pa_family, cur_agent->agent);

   
2376
		}

   
2377
	}

   
2378
}

   
2379

    
   

   
2380
/*!

   
2381
 * \brief Reload the persistent agents from astdb.

   
2382
 */

   
2383
static void reload_agents(void)

   
2384
{

   
2385
	char *agent_num;

   
2386
	struct ast_db_entry *db_tree;

   
2387
	struct ast_db_entry *entry;

   
2388
	struct agent_pvt *cur_agent;

   
2389
	char agent_data[256];

   
2390
	char *parse;

   
2391
	char *agent_chan;

   
2392
	char *agent_callerid;

   
2393

    
   

   
2394
	db_tree = ast_db_gettree(pa_family, NULL);

   
2395

    
   

   
2396
	AST_LIST_LOCK(&agents);

   
2397
	for (entry = db_tree; entry; entry = entry->next) {

   
2398
		agent_num = entry->key + strlen(pa_family) + 2;

   
2399
		AST_LIST_TRAVERSE(&agents, cur_agent, list) {

   
2400
			ast_mutex_lock(&cur_agent->lock);

   
2401
			if (strcmp(agent_num, cur_agent->agent) == 0)

   
2402
				break;

   
2403
			ast_mutex_unlock(&cur_agent->lock);

   
2404
		}

   
2405
		if (!cur_agent) {

   
2406
			ast_db_del(pa_family, agent_num);

   
2407
			continue;

   
2408
		} else

   
2409
			ast_mutex_unlock(&cur_agent->lock);

   
2410
		if (!ast_db_get(pa_family, agent_num, agent_data, sizeof(agent_data)-1)) {

   
2411
			ast_debug(1, "Reload Agent from AstDB: %s on %s\n", cur_agent->agent, agent_data);

   
2412
			parse = agent_data;

   
2413
			agent_chan = strsep(&parse, ";");

   
2414
			agent_callerid = strsep(&parse, ";");

   
2415
			ast_copy_string(cur_agent->loginchan, agent_chan, sizeof(cur_agent->loginchan));

   
2416
			if (agent_callerid) {

   
2417
				ast_copy_string(cur_agent->logincallerid, agent_callerid, sizeof(cur_agent->logincallerid));

   
2418
				set_agentbycallerid(cur_agent->logincallerid, cur_agent->agent);

   
2419
			} else

   
2420
				cur_agent->logincallerid[0] = '\0';

   
2421
			if (cur_agent->loginstart == 0)

   
2422
				time(&cur_agent->loginstart);

   
2423
			ast_devstate_changed(AST_DEVICE_UNKNOWN, "Agent/%s", cur_agent->agent);	

   
2424
		}

   
2425
	}

   
2426
	AST_LIST_UNLOCK(&agents);

   
2427
	if (db_tree) {

   
2428
		ast_log(LOG_NOTICE, "Agents successfully reloaded from database.\n");

   
2429
		ast_db_freetree(db_tree);

   
2430
	}

   
2431
}

   
2432

    
   

   
2433
/*! \brief Part of PBX channel interface */
2170
/*! \brief Part of PBX channel interface */
2434
static int agent_devicestate(void *data)
2171
static int agent_devicestate(void *data)
2435
{
2172
{
2436
	struct agent_pvt *p;
2173
	struct agent_pvt *p;
2437
	char *s;
2174
	char *s;
[+20] [20] 18 lines
[+20] static int agent_devicestate(void *data)
2456
				if (res != AST_DEVICE_INUSE)
2193
				if (res != AST_DEVICE_INUSE)
2457
					res = AST_DEVICE_BUSY;
2194
					res = AST_DEVICE_BUSY;
2458
			} else {
2195
			} else {
2459
				if (res == AST_DEVICE_BUSY)
2196
				if (res == AST_DEVICE_BUSY)
2460
					res = AST_DEVICE_INUSE;
2197
					res = AST_DEVICE_INUSE;
2461
				if (p->chan || !ast_strlen_zero(p->loginchan)) {
2198
				if (p->chan) {
2462
					if (res == AST_DEVICE_INVALID)
2199
					if (res == AST_DEVICE_INVALID)
2463
						res = AST_DEVICE_UNKNOWN;
2200
						res = AST_DEVICE_UNKNOWN;
2464
				} else if (res == AST_DEVICE_INVALID)	
2201
				} else if (res == AST_DEVICE_INVALID)	
2465
					res = AST_DEVICE_UNAVAILABLE;
2202
					res = AST_DEVICE_UNAVAILABLE;
2466
			}
2203
			}
[+20] [20] 54 lines
[+20] [+] static int function_agent(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
2521
		return -1;
2258
		return -1;
2522
	}
2259
	}
2523

    
   
2260

   
2524
	if (!strcasecmp(args.item, "status")) {
2261
	if (!strcasecmp(args.item, "status")) {
2525
		char *status = "LOGGEDOUT";
2262
		char *status = "LOGGEDOUT";
2526
		if (agent->chan || !ast_strlen_zero(agent->loginchan)) 
2263
		if (agent->chan) {
2527
			status = "LOGGEDIN";	
2264
			status = "LOGGEDIN";

    
   
2265
		}
2528
		ast_copy_string(buf, status, len);
2266
		ast_copy_string(buf, status, len);
2529
	} else if (!strcasecmp(args.item, "password")) 
2267
	} else if (!strcasecmp(args.item, "password")) 
2530
		ast_copy_string(buf, agent->password, len);
2268
		ast_copy_string(buf, agent->password, len);
2531
	else if (!strcasecmp(args.item, "name"))
2269
	else if (!strcasecmp(args.item, "name"))
2532
		ast_copy_string(buf, agent->name, len);
2270
		ast_copy_string(buf, agent->name, len);
[+20] [20] 4 lines
[+20] static int function_agent(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
2537
			ast_copy_string(buf, agent->chan->name, len);
2275
			ast_copy_string(buf, agent->chan->name, len);
2538
			tmp = strrchr(buf, '-');
2276
			tmp = strrchr(buf, '-');
2539
			if (tmp)
2277
			if (tmp)
2540
				*tmp = '\0';
2278
				*tmp = '\0';
2541
		} 
2279
		} 
2542
	} else if (!strcasecmp(args.item, "exten"))
2280
	} else if (!strcasecmp(args.item, "exten")) {
2543
		ast_copy_string(buf, agent->loginchan, len);	
2281
		buf[0] = '\0';

    
   
2282
	}
2544

    
   
2283

   
2545
	AST_LIST_UNLOCK(&agents);
2284
	AST_LIST_UNLOCK(&agents);
2546

    
   
2285

   
2547
	return 0;
2286
	return 0;
2548
}
2287
}
[+20] [20] 19 lines
[+20] [+] static int load_module(void)
2568
		return AST_MODULE_LOAD_FAILURE;
2307
		return AST_MODULE_LOAD_FAILURE;
2569
	}
2308
	}
2570
	/* Read in the config */
2309
	/* Read in the config */
2571
	if (!read_agent_config(0))
2310
	if (!read_agent_config(0))
2572
		return AST_MODULE_LOAD_DECLINE;
2311
		return AST_MODULE_LOAD_DECLINE;
2573
	if (persistent_agents)

   
2574
		reload_agents();

   
2575
	/* Dialplan applications */
2312
	/* Dialplan applications */
2576
	ast_register_application_xml(app, login_exec);
2313
	ast_register_application_xml(app, login_exec);
2577
	ast_register_application_xml(app3, agentmonitoroutgoing_exec);
2314
	ast_register_application_xml(app3, agentmonitoroutgoing_exec);
2578

    
   
2315

   
2579
	/* Manager commands */
2316
	/* Manager commands */
[+20] [20] 9 lines
[+20] static int load_module(void)
2589
	return AST_MODULE_LOAD_SUCCESS;
2326
	return AST_MODULE_LOAD_SUCCESS;
2590
}
2327
}
2591

    
   
2328

   
2592
static int reload(void)
2329
static int reload(void)
2593
{
2330
{
2594
	if (!read_agent_config(1)) {
2331
	return read_agent_config(1);
2595
		if (persistent_agents)

   
2596
			reload_agents();

   
2597
	}

   
2598
	return 0;

   
2599
}
2332
}
2600

    
   
2333

   
2601
static int unload_module(void)
2334
static int unload_module(void)
2602
{
2335
{
2603
	struct agent_pvt *p;
2336
	struct agent_pvt *p;
[+20] [20] 29 lines
/trunk/configs/agents.conf.sample
Revision 197925 New Change
 
  1. /trunk/channels/chan_agent.c: Loading...
  2. /trunk/configs/agents.conf.sample: Loading...

https://reviewboard.asterisk.org/ runs on a server provided by Digium, Inc. and uses bandwidth donated to the open source Asterisk community by API Digital Communications in Huntsville, AL USA.
Please report problems with this site to asteriskteam@digium.com.