[Asterisk-Dev] Looking for some comments on a patch/new features for chan_agent.c

Jonathan Feally vulture at netvulture.com
Tue May 18 03:47:59 MST 2004


Hello All,
I'm looking for a little feedback on my patch included here for 
chan_agent.c. I'm not an expert in c, but have tried my best. I've found 
that there were a few things I wanted to accomplish with 
AgentCallbackLogin() and also that part of the code was there to hangup 
after 3 login attempts but was never completed. I will use this patch to 
allow my agents to modify their queue memberships via menus after they 
have logged in. Not all of my agents will be in the same queues everyday 
and I don't want to setup different agent numbers for each possible 
combination of queue membership.

I welcome any suggestions on how to improve this patch's code, 
operation, option letters or fix any bugs found in my code 
changes/additions.
P.S. Documentation is not my way of life, so if you have any suggestions 
on saying how things work - those are welcome also!

I will submit this to cvs after some testers and comments and maybe some 
adjustments.
Patch changes are listed below - Thanks Ahead of Time! -Jon


Patches most useful modes of operation:
AgentCallbackLogin(|2ghv) - 2 tries - goodbye on fail + hangup on fail + 
local variables
AgentCallbackLogin(|2GHv) - 2 tries - no goodbye + no hangup + local 
variables

Goals:
Fix Max Login Attempts and allow user to set max attempts via options of 
function in extensions.conf
Change behavior of function after login success of failure in these 
respects:
1.    Hangup/Don't Hangup in Callback mode
2.    Play Goodbye/Don't Play Goodbye in Callback mode
3.    Set Variables for use in extensions.conf either globally or local 
to the exten

Results:
Completes the logic to check if maxtries has been exceeded
Adds New Options: (defaults are 3 login attempts, play announcement, 
hangup, and return -1)
    a-f - Set Max Login Attempts to (1-6)
    g - play goodbye only on login failure
    G - never play goodbye
    h - hangup only on login failure (returns -1 or 0)
    H - never hangup (returns 0)
    v - Set Local Variables AGENTNUMBER, AGENTPASS, AGENTEXTEN on 
successful login
    V - Same as v - but set the variable globally
Existing Options - No change to their behavior
    s - do not play the announcement

New variables in __login_exec () after patch
    int maxtries = 3;  //value range of 1-6
    int login_state = 0;  //value range of 1-6
    char option;  //used for temporary storage in determining AgentLogin 
and AgentCallbackLogin() options
    int play_goodbye = 1;  //value range of 0-2
    int hangup_call = 1;  //value range of 0-2
    int set_vars = 0;  //value range of 0-2

Changed variable:
old:    int play_announcement;  //value range of 0-1
new:    int play_announcement = 1;  //Was set to 1 further down in the 
function - moved to the beginning of the function



Patch Below or use attachment:

Index: asterisk/channels/chan_agent.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_agent.c,v
retrieving revision 1.72
diff -c -r1.72 chan_agent.c
*** asterisk/channels/chan_agent.c    9 May 2004 07:51:44 -0000    1.72
--- asterisk/channels/chan_agent.c    18 May 2004 09:59:33 -0000
***************
*** 68,76 ****
 
  static char *descrip2 =
  "  AgentCallbackLogin([AgentNo][|[options][exten]@context]):\n"
! "Asks the agent to login to the system with callback.  Always returns 
-1.\n"
  "The agent's callback extension is called (optionally with the 
specified\n"
! "context. \n";
 
  static char *descrip3 =
  "  AgentMonitorOutgoing([options]):\n"
--- 68,85 ----
 
  static char *descrip2 =
  "  AgentCallbackLogin([AgentNo][|[options][exten]@context]):\n"
! "Asks the agent to login to the system with callback.\n"
  "The agent's callback extension is called (optionally with the 
specified\n"
! "context. \n"
! "Options: (defaults are 3 login attempts, play announcement, hangup, 
and return -1)\n"
! "a-f - Max Login Attempts (1-6)\n"
! "g - play goodbye only on login failure\n"
! "G - never play goodbye\n"
! "h - hangup only on login failure (returns -1 or 0)\n"
! "H - never hangup (returns 0)\n"
! "s - do not play the announcement\n"
! "v - Set Local Variables AGENTNUMBER, AGENTPASS, AGENTEXTEN on 
successful login\n"
! "V - Same as v - but set the variables globally";
 
  static char *descrip3 =
  "  AgentMonitorOutgoing([options]):\n"
***************
*** 1117,1126 ****
--- 1126,1137 ----
  {
      int res=0;
      int tries = 0;
+     int maxtries = 3;
      struct agent_pvt *p;
      struct localuser *u;
      struct timeval tv;
      time_t start;
+     int login_state = 0;
      char user[AST_MAX_AGENT];
      char pass[AST_MAX_AGENT];
      char agent[AST_MAX_AGENT] = "";
***************
*** 1129,1137 ****
      char info[512];
      char *opt_user = NULL;
      char *options = NULL;
      char *context = NULL;
      char *exten = NULL;
!     int play_announcement;
      char *filename = "agent-loginok";
     
      LOCAL_USER_ADD(u);
--- 1140,1152 ----
      char info[512];
      char *opt_user = NULL;
      char *options = NULL;
+     char option;
      char *context = NULL;
      char *exten = NULL;
!     int play_announcement = 1;
!     int play_goodbye = 1;
!     int hangup_call = 1;
!     int set_vars = 0;
      char *filename = "agent-loginok";
     
      LOCAL_USER_ADD(u);
***************
*** 1156,1161 ****
--- 1171,1208 ----
                      exten = NULL;
              }
          }
+         if( options ) {
+             while(*options) {
+                 option = (char)options[0];
+                 if (option=='a')
+                     maxtries = 1;
+                 if (option=='b')
+                     maxtries = 2;
+                 if (option=='c')
+                     maxtries = 3;
+                 if (option=='d')
+                     maxtries = 4;
+                 if (option=='e')
+                     maxtries = 5;
+                 if (option=='f')
+                     maxtries = 6;
+                 if (option=='g')
+                     play_goodbye = 1;
+                 if (option=='G')
+                     play_goodbye = 0;
+                 if (option=='h')
+                     hangup_call = 1;
+                 if (option=='H')
+                     hangup_call = 0;
+                 if (option=='s')
+                     play_announcement = 0;
+                 if (option=='v')
+                     set_vars = 1;
+                 if (option=='V')
+                     set_vars = 2;
+                 options++;
+             }
+         }
      }
 
      if (chan->_state != AST_STATE_UP)
***************
*** 1166,1172 ****
          else
              res = ast_app_getdata(chan, "agent-user", user, 
sizeof(user) - 1, 0);
      }
!     while (!res && (tries < 3)) {
          /* Check for password */
          ast_mutex_lock(&agentlock);
          p = agents;
--- 1213,1220 ----
          else
              res = ast_app_getdata(chan, "agent-user", user, 
sizeof(user) - 1, 0);
      }
!     while (!res && tries < maxtries) {
!         tries++;
          /* Check for password */
          ast_mutex_lock(&agentlock);
          p = agents;
***************
*** 1195,1200 ****
--- 1243,1249 ----
              ast_mutex_lock(&p->lock);
              if (!strcmp(p->agent, user) &&
                  !strcmp(p->password, pass) && !p->pending) {
+                     login_state = 1; /* Successful Login */
                      if (!p->chan) {
                          if (callbackmode) {
                              char tmpchan[AST_MAX_BUF] = "";
***************
*** 1227,1232 ****
--- 1276,1282 ----
                                      }
                                  }
                              }
+                             exten = tmpchan;
                              if (!res) {
                                  if (context && 
!ast_strlen_zero(context) && !ast_strlen_zero(tmpchan))
                                      snprintf(p->loginchan, 
sizeof(p->loginchan), "%s@%s", tmpchan, context);
***************
*** 1252,1261 ****
                              strcpy(p->loginchan, "");
                              p->acknowledged = 0;
                          }
!                         play_announcement = 1;
!                         if( options )
!                             if( strchr( options, 's' ) )
!                                 play_announcement = 0;
                          ast_mutex_unlock(&p->lock);
                          ast_mutex_unlock(&agentlock);
                          if( !res && play_announcement )
--- 1302,1308 ----
                              strcpy(p->loginchan, "");
                              p->acknowledged = 0;
                          }
!
                          ast_mutex_unlock(&p->lock);
                          ast_mutex_unlock(&agentlock);
                          if( !res && play_announcement )
***************
*** 1278,1292 ****
                          if (p->chan)
                              res = -1;
                          if (callbackmode && !res) {
-                             /* Just say goodbye and be done with it */
                              ast_mutex_unlock(&agentlock);
                              if (!res)
                                  res = ast_safe_sleep(chan, 500);
-                             res = ast_streamfile(chan, "vm-goodbye", 
chan->language);
-                             if (!res)
-                                 res = ast_waitstream(chan, "");
-                             if (!res)
-                                 res = ast_safe_sleep(chan, 1000);
                              ast_mutex_unlock(&p->lock);
                          } else if (!res) {
  #ifdef HONOR_MUSIC_CLASS
--- 1325,1333 ----
***************
*** 1399,1411 ****
          if (!p)
              ast_mutex_unlock(&agentlock);
 
!         if (!res)
              res = ast_app_getdata(chan, errmsg, user, sizeof(user) - 
1, 0);
      }
         
      LOCAL_USER_REMOVE(u);
!     /* Always hangup */
!     return -1;
  }
 
  static int login_exec(struct ast_channel *chan, void *data)
--- 1440,1482 ----
          if (!p)
              ast_mutex_unlock(&agentlock);
 
!         if (!res && tries < maxtries) {
              res = ast_app_getdata(chan, errmsg, user, sizeof(user) - 
1, 0);
+         }
      }
         
      LOCAL_USER_REMOVE(u);
!     if (!res)
!         res = ast_safe_sleep(chan, 500);
!
!     /* Play vm-goodbye and return based upon callbackmode and 
login_state */
!     if (set_vars && login_state) {
!         if (set_vars==1) {
!             pbx_builtin_setvar_helper(chan, "AGENTNUMBER", user);
!             pbx_builtin_setvar_helper(chan, "AGENTPASS", pass);
!             pbx_builtin_setvar_helper(chan, "AGENTEXTEN", exten);
!         }
!         if (set_vars==2) {
!             pbx_builtin_setvar_helper(NULL, "AGENTNUMBER", user);
!             pbx_builtin_setvar_helper(NULL, "AGENTPASS", pass);
!             pbx_builtin_setvar_helper(NULL, "AGENTEXTEN", exten);
!         }
!     }
!     if (!callbackmode)
!         return -1;
!     if (play_goodbye==2 || (play_goodbye==1 && !login_state)) {
!         if (!res)
!             res = ast_safe_sleep(chan, 1000);
!         res = ast_streamfile(chan, "vm-goodbye", chan->language);
!         if (!res)
!             res = ast_waitstream(chan, "");
!         if (!res)
!             res = ast_safe_sleep(chan, 1000);
!     }
!     if (hangup_call==2 || (hangup_call==1 && !login_state)) {
!         return -1;
!     }
!     return 0;
  }
 
  static int login_exec(struct ast_channel *chan, void *data)

-------------- next part --------------
Index: asterisk/channels/chan_agent.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_agent.c,v
retrieving revision 1.72
diff -c -r1.72 chan_agent.c
*** asterisk/channels/chan_agent.c	9 May 2004 07:51:44 -0000	1.72
--- asterisk/channels/chan_agent.c	18 May 2004 09:59:33 -0000
***************
*** 68,76 ****
  
  static char *descrip2 =
  "  AgentCallbackLogin([AgentNo][|[options][exten]@context]):\n"
! "Asks the agent to login to the system with callback.  Always returns -1.\n"
  "The agent's callback extension is called (optionally with the specified\n"
! "context. \n";
  
  static char *descrip3 =
  "  AgentMonitorOutgoing([options]):\n"
--- 68,85 ----
  
  static char *descrip2 =
  "  AgentCallbackLogin([AgentNo][|[options][exten]@context]):\n"
! "Asks the agent to login to the system with callback.\n"
  "The agent's callback extension is called (optionally with the specified\n"
! "context. \n"
! "Options: (defaults are 3 login attempts, play announcement, hangup, and return -1)\n"
! "a-f - Max Login Attempts (1-6)\n"
! "g - play goodbye only on login failure\n"
! "G - never play goodbye\n"
! "h - hangup only on login failure (returns -1 or 0)\n"
! "H - never hangup (returns 0)\n"
! "s - do not play the announcement\n"
! "v - Set Local Variables AGENTNUMBER, AGENTPASS, AGENTEXTEN on successful login\n"
! "V - Same as v - but set the variables globally";
  
  static char *descrip3 =
  "  AgentMonitorOutgoing([options]):\n"
***************
*** 1117,1126 ****
--- 1126,1137 ----
  {
  	int res=0;
  	int tries = 0;
+ 	int maxtries = 3;
  	struct agent_pvt *p;
  	struct localuser *u;
  	struct timeval tv;
  	time_t start;
+ 	int login_state = 0;
  	char user[AST_MAX_AGENT];
  	char pass[AST_MAX_AGENT];
  	char agent[AST_MAX_AGENT] = "";
***************
*** 1129,1137 ****
  	char info[512];
  	char *opt_user = NULL;
  	char *options = NULL;
  	char *context = NULL;
  	char *exten = NULL;
! 	int play_announcement;
  	char *filename = "agent-loginok";
  	
  	LOCAL_USER_ADD(u);
--- 1140,1152 ----
  	char info[512];
  	char *opt_user = NULL;
  	char *options = NULL;
+ 	char option;
  	char *context = NULL;
  	char *exten = NULL;
! 	int play_announcement = 1;
! 	int play_goodbye = 1;
! 	int hangup_call = 1;
! 	int set_vars = 0;
  	char *filename = "agent-loginok";
  	
  	LOCAL_USER_ADD(u);
***************
*** 1156,1161 ****
--- 1171,1208 ----
  					exten = NULL;
  			}
  		}
+ 		if( options ) {
+ 			while(*options) {
+ 				option = (char)options[0];
+ 				if (option=='a')
+ 					maxtries = 1;
+ 				if (option=='b')
+ 					maxtries = 2;
+ 				if (option=='c')
+ 					maxtries = 3;
+ 				if (option=='d')
+ 					maxtries = 4;
+ 				if (option=='e')
+ 					maxtries = 5;
+ 				if (option=='f')
+ 					maxtries = 6;
+ 				if (option=='g')
+ 					play_goodbye = 1;
+ 				if (option=='G')
+ 					play_goodbye = 0;
+ 				if (option=='h')
+ 					hangup_call = 1;
+ 				if (option=='H')
+ 					hangup_call = 0;
+ 				if (option=='s')
+ 					play_announcement = 0;
+ 				if (option=='v')
+ 					set_vars = 1;
+ 				if (option=='V')
+ 					set_vars = 2;
+ 				options++;
+ 			}
+ 		}
  	}
  
  	if (chan->_state != AST_STATE_UP)
***************
*** 1166,1172 ****
  		else
  			res = ast_app_getdata(chan, "agent-user", user, sizeof(user) - 1, 0);
  	}
! 	while (!res && (tries < 3)) {
  		/* Check for password */
  		ast_mutex_lock(&agentlock);
  		p = agents;
--- 1213,1220 ----
  		else
  			res = ast_app_getdata(chan, "agent-user", user, sizeof(user) - 1, 0);
  	}
! 	while (!res && tries < maxtries) {
! 		tries++;
  		/* Check for password */
  		ast_mutex_lock(&agentlock);
  		p = agents;
***************
*** 1195,1200 ****
--- 1243,1249 ----
  			ast_mutex_lock(&p->lock);
  			if (!strcmp(p->agent, user) &&
  				!strcmp(p->password, pass) && !p->pending) {
+ 					login_state = 1; /* Successful Login */
  					if (!p->chan) {
  						if (callbackmode) {
  							char tmpchan[AST_MAX_BUF] = "";
***************
*** 1227,1232 ****
--- 1276,1282 ----
  									}
  								}
  							}
+ 							exten = tmpchan;
  							if (!res) {
  								if (context && !ast_strlen_zero(context) && !ast_strlen_zero(tmpchan))
  									snprintf(p->loginchan, sizeof(p->loginchan), "%s@%s", tmpchan, context);
***************
*** 1252,1261 ****
  							strcpy(p->loginchan, "");
  							p->acknowledged = 0;
  						}
! 						play_announcement = 1;
! 						if( options )
! 							if( strchr( options, 's' ) )
! 								play_announcement = 0;
  						ast_mutex_unlock(&p->lock);
  						ast_mutex_unlock(&agentlock);
  						if( !res && play_announcement )
--- 1302,1308 ----
  							strcpy(p->loginchan, "");
  							p->acknowledged = 0;
  						}
! 
  						ast_mutex_unlock(&p->lock);
  						ast_mutex_unlock(&agentlock);
  						if( !res && play_announcement )
***************
*** 1278,1292 ****
  						if (p->chan)
  							res = -1;
  						if (callbackmode && !res) {
- 							/* Just say goodbye and be done with it */
  							ast_mutex_unlock(&agentlock);
  							if (!res)
  								res = ast_safe_sleep(chan, 500);
- 							res = ast_streamfile(chan, "vm-goodbye", chan->language);
- 							if (!res)
- 								res = ast_waitstream(chan, "");
- 							if (!res)
- 								res = ast_safe_sleep(chan, 1000);
  							ast_mutex_unlock(&p->lock);
  						} else if (!res) {
  #ifdef HONOR_MUSIC_CLASS
--- 1325,1333 ----
***************
*** 1399,1411 ****
  		if (!p)
  			ast_mutex_unlock(&agentlock);
  
! 		if (!res)
  			res = ast_app_getdata(chan, errmsg, user, sizeof(user) - 1, 0);
  	}
  		
  	LOCAL_USER_REMOVE(u);
! 	/* Always hangup */
! 	return -1;
  }
  
  static int login_exec(struct ast_channel *chan, void *data)
--- 1440,1482 ----
  		if (!p)
  			ast_mutex_unlock(&agentlock);
  
! 		if (!res && tries < maxtries) {
  			res = ast_app_getdata(chan, errmsg, user, sizeof(user) - 1, 0);
+ 		}
  	}
  		
  	LOCAL_USER_REMOVE(u);
! 	if (!res)
! 		res = ast_safe_sleep(chan, 500);
! 
! 	/* Play vm-goodbye and return based upon callbackmode and login_state */
! 	if (set_vars && login_state) {
! 		if (set_vars==1) {
! 			pbx_builtin_setvar_helper(chan, "AGENTNUMBER", user);
! 			pbx_builtin_setvar_helper(chan, "AGENTPASS", pass);
! 			pbx_builtin_setvar_helper(chan, "AGENTEXTEN", exten);
! 		}
! 		if (set_vars==2) {
! 			pbx_builtin_setvar_helper(NULL, "AGENTNUMBER", user);
! 			pbx_builtin_setvar_helper(NULL, "AGENTPASS", pass);
! 			pbx_builtin_setvar_helper(NULL, "AGENTEXTEN", exten);
! 		}
! 	}
! 	if (!callbackmode)
! 		return -1;
! 	if (play_goodbye==2 || (play_goodbye==1 && !login_state)) {
! 		if (!res)
! 			res = ast_safe_sleep(chan, 1000);
! 		res = ast_streamfile(chan, "vm-goodbye", chan->language);
! 		if (!res)
! 			res = ast_waitstream(chan, "");
! 		if (!res)
! 			res = ast_safe_sleep(chan, 1000);
! 	}
! 	if (hangup_call==2 || (hangup_call==1 && !login_state)) {
! 		return -1;
! 	}
! 	return 0;
  }
  
  static int login_exec(struct ast_channel *chan, void *data)


More information about the asterisk-dev mailing list