Index: manager.c =================================================================== RCS file: /usr/cvsroot/asterisk/manager.c,v retrieving revision 1.41 diff -u -r1.41 manager.c --- manager.c 9 Mar 2004 20:01:46 -0000 1.41 +++ manager.c 9 Apr 2004 16:25:49 -0000 @@ -59,9 +59,11 @@ { -1, "all" }, }; +static struct intl_man_listener *ilstn = NULL; static struct mansession *sessions = NULL; static struct manager_action *first_action = NULL; static ast_mutex_t actionlock = AST_MUTEX_INITIALIZER; +static ast_mutex_t islock = AST_MUTEX_INITIALIZER; int ast_carefulwrite(int fd, char *s, int len, int timeoutms) { @@ -175,6 +177,16 @@ return ""; } +void astman_dump(struct message *m,char *buf,size_t size) +{ + int x; + for (x=0;xhdrcount;x++) { + strncat(buf,m->headers[x],size); + strncat(buf,"\n",size); + } + +} + void astman_send_error(struct mansession *s, struct message *m, char *error) { char *id = astman_get_header(m,"ActionID"); @@ -847,6 +859,10 @@ struct mansession *s; char tmp[4096]; va_list ap; + struct intl_man_listener *ptr; + struct message m; + char *stack,*val; + memset(&m, 0, sizeof(&m)); ast_mutex_lock(&sessionlock); s = sessions; @@ -865,6 +881,48 @@ } s = s->next; } + + /* + Build a struct message so we can deliver it to internal registrants + providing there is a need. + anthm 4/2004 + */ + if(ilstn) { + va_start(ap, fmt); + vsnprintf(tmp, sizeof(tmp), fmt, ap); + va_end(ap); + snprintf(m.headers[0],sizeof(m.headers[0]),"Event: %s",event); + m.hdrcount = 1; + val=stack=tmp; + + while(val) { + val = strsep(&stack, "\r\n"); + if(!val) + break; + if (strchr(val,':')) { + strncpy(m.headers[m.hdrcount],val,sizeof(m.headers[m.hdrcount])); + m.hdrcount++; + } + } + /* + walk the list of internal registrants and call thier + custom callback func with our struct message obj + + NULL indicates match everything otherwise the specific + event name you want to bind to or '|' seperated list of Events + ptr->func is your custom callback 'int mycall(struct message *m)' */ + + + for(ptr=ilstn;ptr;ptr=ptr->next) + if(ptr->event == NULL || + ((val = strstr(ptr->event,event)) && + (val == ptr->event || (val-1)[0] == '|') && + ((val[strlen(event)] == '|') || + (val[strlen(event)] == '\0')))) + ptr->func(&m); + + } + ast_mutex_unlock(&sessionlock); return 0; } @@ -896,6 +954,122 @@ return 0; } + +/******************************************************************************* + Register a pointer to a callback function to be called when + a specific or all events happen. + + This is an internal version of a mansession + + +FYI: +struct intl_man_listener { + char *event; + int (*func)(struct message *); + struct intl_man_listener *next; +}; + +USAGE: + +Top Level of a mod: + +static int myhandler1(struct message *m) { + char *event = astman_get_header(m,"Event"); + ast_log(LOG_WARNING,"Caught Event: %s\n",event); + return 0; +} +static struct intl_man_listener lstn1; + +In load_module(): + +lstn1.event = (char *) "all"; +lstn1.func = myhandler1; +ast_internal_manager_register(&lstn1); + + +in unload_module() +ast_internal_manager_deregister(&lstn1); + + + anthm 4/2004 +*/ + + +/* adds an internal registration */ +struct intl_man_listener *ast_internal_manager_register(struct intl_man_listener *new) { + struct intl_man_listener *ptr; + int doit=1; + + if(! new || ! new->func) { + ast_log(LOG_WARNING,"Cannot register without a valid object and func pointer.\n"); + return NULL; + } + + ast_mutex_lock(&islock); + if(!ilstn) + ilstn = new; + else { + for(ptr=ilstn;ptr->next;ptr=ptr->next) { + if(ptr == new || ptr->next == new) { + doit=0; + break; + } + } + if(doit) { + new->next = NULL; + ptr->next = new; + } + else + ast_log(LOG_WARNING,"This registration is already present."); + } + ast_mutex_unlock(&islock); + + if(doit) + ast_verbose(VERBOSE_PREFIX_2"Adding Internal Listener For Event: [%s]\n",new->event ? new->event : "all"); + + return new; +} + +/* removes an internal registration */ +int ast_internal_manager_deregister(struct intl_man_listener *me) { + struct intl_man_listener *ptr=NULL,*last=NULL; + int found=0; + + ast_mutex_lock(&islock); + if(ilstn == me) { + ilstn = NULL; + found++; + } + else { + for(ptr=ilstn;ptr;ptr=ptr->next) { + if(ptr == me) { + found++; + if(last && ptr->next) { + last->next = ptr->next; + } + else if(last && ! ptr->next) { + last->next = NULL; + } + else if(! last && ptr->next) { + ilstn = ptr->next; + } + else if(! last && ! ptr->next) { + ilstn = NULL; + } + } + last = ptr; + } + } + + if(found) + ast_verbose(VERBOSE_PREFIX_2"Removing Internal Listener For Event: [%s]\n",me->event ? me->event : "all"); + else + ast_log(LOG_WARNING,"Unable to locate Internal Listener\n"); + + ast_mutex_unlock(&islock); + return 1; +} + int ast_manager_register( char *action, int auth, int (*func)(struct mansession *s, struct message *m), char *synopsis) { Index: include/asterisk/manager.h =================================================================== RCS file: /usr/cvsroot/asterisk/include/asterisk/manager.h,v retrieving revision 1.8 diff -u -r1.8 manager.h --- include/asterisk/manager.h 1 Mar 2004 21:12:32 -0000 1.8 +++ include/asterisk/manager.h 9 Apr 2004 16:25:49 -0000 @@ -53,6 +53,8 @@ #define MAX_HEADERS 80 #define MAX_LEN 256 + + struct mansession { pthread_t t; ast_mutex_t lock; @@ -76,6 +78,12 @@ char headers[MAX_HEADERS][MAX_LEN]; }; +struct intl_man_listener { + char *event; + int (*func)(struct message *); + struct intl_man_listener *next; +}; + struct manager_action { char action[256]; char *synopsis; @@ -84,6 +92,10 @@ struct manager_action *next; }; +struct intl_man_listener *ast_internal_manager_register(struct intl_man_listener *new); +int ast_internal_manager_deregister(struct intl_man_listener *me); +void astman_dump(struct message *m,char *buf,size_t size); + int ast_carefulwrite(int fd, char *s, int len, int timeoutms); /* External routines may register/unregister manager callbacks this way */