Issue #3930 - Add manager command for listing dialplan (coded april 2005, in bugtrack...
authorOlle Johansson <oej@edvina.net>
Mon, 30 Oct 2006 21:18:39 +0000 (21:18 +0000)
committerOlle Johansson <oej@edvina.net>
Mon, 30 Oct 2006 21:18:39 +0000 (21:18 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@46508 65c4cc65-6c06-0410-ace0-fbb531ad65f3

include/asterisk/manager.h
main/manager.c
main/pbx.c

index 96326f0..68c2fed 100644 (file)
@@ -124,6 +124,7 @@ struct ast_variable *astman_get_variables(struct message *m);
 void astman_send_error(struct mansession *s, struct message *m, char *error);
 void astman_send_response(struct mansession *s, struct message *m, char *resp, char *msg);
 void astman_send_ack(struct mansession *s, struct message *m, char *msg);
+void astman_send_listack(struct mansession *s, struct message *m, char *msg, char *listflag);
 
 void astman_append(struct mansession *s, const char *fmt, ...)
         __attribute__ ((format (printf, 2, 3)));
index 465e2a8..a2d146c 100644 (file)
@@ -736,13 +736,15 @@ void astman_append(struct mansession *s, const char *fmt, ...)
  * XXX MSG_MOREDATA should go to a header file.
  */
 #define MSG_MOREDATA   ((char *)astman_send_response)
-void astman_send_response(struct mansession *s, struct message *m, char *resp, char *msg)
+static void astman_send_response_full(struct mansession *s, struct message *m, char *resp, char *msg, char *listflag)
 {
        char *id = astman_get_header(m,"ActionID");
 
        astman_append(s, "Response: %s\r\n", resp);
        if (!ast_strlen_zero(id))
                astman_append(s, "ActionID: %s\r\n", id);
+       if (listflag)
+               astman_append(s, "Eventlist: %s\r\n", listflag);        /* Start, complete, cancelled */
        if (msg == MSG_MOREDATA)
                return;
        else if (msg)
@@ -751,19 +753,29 @@ void astman_send_response(struct mansession *s, struct message *m, char *resp, c
                astman_append(s, "\r\n");
 }
 
+void astman_send_response(struct mansession *s, struct message *m, char *resp, char *msg)
+{
+       astman_send_response_full(s, m, resp, msg, NULL);
+}
+
 void astman_send_error(struct mansession *s, struct message *m, char *error)
 {
-       astman_send_response(s, m, "Error", error);
+       astman_send_response_full(s, m, "Error", error, NULL);
 }
 
 void astman_send_ack(struct mansession *s, struct message *m, char *msg)
 {
-       astman_send_response(s, m, "Success", msg);
+       astman_send_response_full(s, m, "Success", msg, NULL);
 }
 
 static void astman_start_ack(struct mansession *s, struct message *m)
 {
-       astman_send_response(s, m, "Success", MSG_MOREDATA);
+       astman_send_response_full(s, m, "Success", MSG_MOREDATA, NULL);
+}
+
+void astman_send_listack(struct mansession *s, struct message *m, char *msg, char *listflag)
+{
+       astman_send_response_full(s, m, "Success", msg, listflag);
 }
 
 
index bc91bd2..7ea9596 100644 (file)
@@ -3184,7 +3184,9 @@ static char *complete_show_dialplan_context(const char *line, const char *word,
        return ret;
 }
 
+/*! \brief Counters for the show dialplan manager command */
 struct dialplan_counters {
+       int total_items;
        int total_context;
        int total_exten;
        int total_prio;
@@ -3410,6 +3412,244 @@ static int handle_show_dialplan(int fd, int argc, char *argv[])
        return RESULT_SUCCESS;
 }
 
+/*! \brief Send ack once */
+static void manager_dpsendack(struct mansession *s, struct message *m, int *sentack)
+{
+       if (*sentack)
+               return;
+       astman_send_listack(s, m, "DialPlan list will follow", "start");
+       *sentack = 1;
+       return;
+}
+
+/*! \brief Show dialplan extensions */
+static int manager_show_dialplan_helper(struct mansession *s, struct message *m, char *actionidtext, char *context, char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude)
+{
+       struct ast_context *c;
+       int res=0, old_total_exten = dpc->total_exten;
+       int sentpositivemanagerack = 0;
+
+       if (ast_strlen_zero(exten))
+               exten = NULL;
+       if (ast_strlen_zero(context))
+               context = NULL;
+
+       if (option_debug > 2)
+               ast_log(LOG_DEBUG, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten);
+
+       /* try to lock contexts */
+       if (ast_lock_contexts()) {
+               astman_send_error(s, m, "Failed to lock contexts\r\n");
+               ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n");
+               return -1;
+       }
+
+       /* walk all contexts ... */
+       for (c = ast_walk_contexts(NULL); c ; c = ast_walk_contexts(c)) {
+               /* show this context? */
+               if (!context ||
+                       !strcmp(ast_get_context_name(c), context)) {
+                       dpc->context_existence = 1;
+
+                       if (option_debug > 2)
+                               ast_log(LOG_DEBUG, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c));
+
+                       /* try to lock context before walking in ... */
+                       if (!ast_lock_context(c)) {
+                               struct ast_exten *e;
+                               struct ast_include *i;
+                               struct ast_ignorepat *ip;
+                               struct ast_sw *sw;
+                               char buf[256], buf2[256];
+
+                               /* walk extensions in context  */
+                               for (e = ast_walk_context_extensions(c, NULL); e; e = ast_walk_context_extensions(c, e)) {
+                                       struct ast_exten *p;
+                                       int prio;
+
+                                       /* looking for extension? is this our extension? */
+                                       if (exten &&
+                                               !ast_extension_match(ast_get_extension_name(e), exten))
+                                       {
+                                               if (option_debug > 2)
+                                                       ast_log(LOG_DEBUG, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e));
+                                               /* we are looking for extension and it's not our
+                                                * extension, so skip to next extension */
+                                               continue;
+                                       }
+                                       if (option_debug > 2)
+                                               ast_log(LOG_DEBUG, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e));
+
+                                       dpc->extension_existence = 1;
+
+                                       /* may we print context info? */        
+                                       dpc->total_context++;
+                                       dpc->total_prio++;
+
+                                       /* write extension name and first peer */       
+                                       bzero(buf, sizeof(buf));                
+                               
+                                       dpc->total_items++;
+                                       manager_dpsendack(s, m, &sentpositivemanagerack);
+                                       astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
+                                       astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) );
+
+                                       prio = ast_get_extension_priority(e);
+                                       if (prio == PRIORITY_HINT) {
+                                               astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(e));
+                                       } else {
+                                               astman_append(s, "Priority: %d\r\nApplication: %s\r\nAppData: %s\r\n", prio, ast_get_extension_app(e), (char *) ast_get_extension_app_data(e));
+                                       }
+                                       astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e));
+
+                                       dpc->total_exten++;
+
+                                       /* walk next extension peers */
+                                       for (p=ast_walk_extension_priorities(e, e); p; p=ast_walk_extension_priorities(e, p)) {
+                                               dpc->total_prio++;
+                                               bzero((void *)buf2, sizeof(buf2));
+                                               bzero((void *)buf, sizeof(buf));
+                                               dpc->total_items++;
+                                               manager_dpsendack(s, m, &sentpositivemanagerack);
+                                               astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
+                                               astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) );
+
+                                               if (ast_get_extension_label(p))
+                                                       astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p));
+                                               prio = ast_get_extension_priority(p);
+                                               if (prio == PRIORITY_HINT) {
+                                                       astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p));
+                                               } else {
+                                                       astman_append(s, "Priority: %d\r\nApplication: %s\r\nAppData: %s\r\n", prio, ast_get_extension_app(p), (char *) ast_get_extension_app_data(p));
+                                               }
+                                               astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e));
+                                       }
+                               }
+
+                               /* walk included and write info ... */
+                               for (i = ast_walk_context_includes(c, NULL); i; i = ast_walk_context_includes(c, i)) {
+                                       if (exten) {
+                                               /* Check all includes for the requested extension */
+                                               manager_show_dialplan_helper(s, m, actionidtext, (char *)ast_get_include_name(i), exten, dpc, i);
+                                       } else {
+                                               dpc->total_items++;
+                                               manager_dpsendack(s, m, &sentpositivemanagerack);
+                                               astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
+                                               astman_append(s, "Context: %s\r\nIncludeContext: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ast_get_include_name(i), ast_get_include_registrar(i));
+                                               astman_append(s, "\r\n");
+                                               if (option_debug > 2)
+                                                       ast_log(LOG_DEBUG, "manager_show_dialplan: Found Included context: %s \n", buf);
+                                       }
+                               }
+
+                               /* walk ignore patterns and write info ... */
+                               for (ip=ast_walk_context_ignorepats(c, NULL); ip; ip=ast_walk_context_ignorepats(c, ip)) {
+                                       const char *ipname = ast_get_ignorepat_name(ip);
+                                       char ignorepat[AST_MAX_EXTENSION];
+
+                                       snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
+                                       if ((!exten) || ast_extension_match(ignorepat, exten)) {
+                                               dpc->total_items++;
+                                               manager_dpsendack(s, m, &sentpositivemanagerack);
+                                               astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
+                                               astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip));
+                                               astman_append(s, "\r\n");
+                                       }
+                               }
+                               if (!rinclude) {
+                                       for (sw = ast_walk_context_switches(c, NULL); sw; sw = ast_walk_context_switches(c, sw)) {
+                                               dpc->total_items++;
+                                               manager_dpsendack(s, m, &sentpositivemanagerack);
+                                               astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
+                                               astman_append(s, "Context: %s\r\nSwitch: %s/%s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ast_get_switch_name(sw), ast_get_switch_data(sw), ast_get_switch_registrar(sw)); 
+                                               astman_append(s, "\r\n");
+                                               if (option_debug > 2)
+                                                       ast_log(LOG_DEBUG, "manager_show_dialplan: Found Switch : %s \n", buf);
+                                       }
+                               }
+       
+                               ast_unlock_context(c);
+
+                       } else if (option_debug > 2) {
+                               ast_log(LOG_DEBUG, "manager_show_dialplan: Failed to lock context\n");
+                       }
+               }
+       } 
+       ast_unlock_contexts();
+
+       if (dpc->total_exten == old_total_exten) {
+               if (option_debug > 2)
+                       ast_log(LOG_DEBUG, "manager_show_dialplan: Found nothing new\n");
+               /* Nothing new under the sun */
+               return -1;
+       } else {
+               return res;
+       }
+}
+
+/*! \brief  Manager listing of dial plan */
+static int manager_show_dialplan(struct mansession *s, struct message *m)
+{
+       char *exten = NULL, *context = NULL;
+       char *id = astman_get_header(m, "ActionID");
+       char idtext[256];
+       int res;
+
+       /* Variables used for different counters */
+       struct dialplan_counters counters;
+
+       if (id && !ast_strlen_zero(id))
+               snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
+
+
+       memset(&counters, 0, sizeof(counters));
+
+       exten = astman_get_header(m, "Extension");
+       context = astman_get_header(m, "Context");
+       
+       res = manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL);
+
+       if (context && !counters.context_existence) {
+               char errorbuf[BUFSIZ];
+       
+               snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s\r\n", context);
+               astman_send_error(s, m, errorbuf);
+               return 0;
+       }
+       if (exten && !counters.extension_existence) {
+               char errorbuf[BUFSIZ];
+
+               if (context)
+                       snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s\r\n", exten, context);
+               else
+                       snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context\r\n", exten);
+               astman_send_error(s, m, errorbuf);
+               return 0;
+       }
+
+       manager_event(EVENT_FLAG_CONFIG, "ShowDialPlanComplete",
+               "EventList: Complete\r\n"
+               "ListItems: %d\r\n"
+               "ListExtensions: %d\r\n"
+               "ListPriorities: %d\r\n"        
+               "ListContexts: %d\r\n"  
+               "%s"
+               "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext);
+
+       /* everything ok */
+       return 0;
+}
+
+static char mandescr_show_dialplan[] =
+"Description: Show dialplan contexts and extensions.\n"
+"Be aware that showing the full dialplan may take a lot of capacity\n"
+"Variables: \n"
+" ActionID: <id>               Action ID for this AMI transaction (optional)\n"
+" Extension: <extension>       Extension (Optional)\n"
+" Context: <context>           Context (Optional)\n"
+"\n";
+
+
 /*! \brief CLI support for listing global variables in a parseable way */
 static int handle_show_globals(int fd, int argc, char *argv[])
 {
@@ -5732,6 +5972,9 @@ int load_pbx(void)
                        return -1;
                }
        }
+       
+       /* Register manager application */
+       ast_manager_register2("ShowDialPlan", EVENT_FLAG_CONFIG, manager_show_dialplan, "List dialplan", mandescr_show_dialplan);
        return 0;
 }