Sun Dec 18 20:55:53 2011

Asterisk developer's documentation


res_esel.c File Reference

#include "asterisk.h"
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/say.h"
#include "asterisk/features.h"
#include "asterisk/musiconhold.h"
#include "asterisk/config.h"
#include "asterisk/cli.h"
#include "asterisk/manager.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/adsi.h"

Include dependency graph for res_esel.c:

Go to the source code of this file.

Data Structures

struct  esel_export
struct  esel_extension_state
struct  esel_pvt
struct  esel_queue

Functions

 AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS,"Extension State Export Logic (E.S.E.L.) Resource",.load=load_module,.unload=unload_module,)
 AST_MUTEX_DEFINE_STATIC (listlock)
static void * do_esel_thread (void *data)
static void esel_export_to_remote (struct esel_extension_state *exstate, struct esel_pvt *esel)
static int esel_is_exported (struct esel_export *extensions, struct esel_extension_state *exstate)
static int esel_queue_extension_state (struct esel_queue *queue, char *context, char *exten, int state, void *data, char *cid_num, char *cid_name)
static int esel_state2devstate (int state)
static int esel_state_cb (char *context, char *exten, int state, void *data, char *cid_num, char *cid_name)
static int load_module (void)
static int unload_module (void)

Variables

static struct esel_pvtdonkeys = NULL


Function Documentation

AST_MODULE_INFO ( ASTERISK_GPL_KEY  ,
AST_MODFLAG_GLOBAL_SYMBOLS  ,
"Extension State Export Logic (E.S.E.L.) Resource"  ,
load = load_module,
unload = unload_module 
)

AST_MUTEX_DEFINE_STATIC ( listlock   ) 

static void* do_esel_thread ( void *  data  )  [static]

Definition at line 176 of file res_esel.c.

References ast_cond_wait(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), esel_queue::cond, esel_pvt::connected, esel_queue::count, esel_export_to_remote(), esel_is_exported(), esel_pvt::extensions, free, esel_queue::head, esel_pvt::host, esel_queue::lock, LOG_ERROR, LOG_NOTICE, esel_pvt::name, esel_extension_state::next, esel_pvt::port, esel_pvt::queue, esel_pvt::raddr, esel_pvt::secret, esel_pvt::sockfd, esel_queue::tail, and esel_pvt::username.

Referenced by load_module().

00176                                         {
00177     struct esel_pvt *esel = (struct esel_pvt *)data;
00178     struct esel_queue *queue = &esel->queue;
00179     struct esel_extension_state *exstate = NULL;
00180     char msg[1024];
00181     char buf[1024];
00182     int numbytes = 0;
00183     int sent = 0;
00184     int res = 0;
00185     for (;;) {
00186    if (esel->connected) {
00187        ast_mutex_lock(&queue->lock);
00188        if (queue->count == 0) 
00189       ast_cond_wait(&queue->cond, &queue->lock);
00190        exstate = queue->head;
00191        if (exstate) {
00192       if (exstate->next) {
00193           queue->head = exstate->next;
00194       } else {
00195           queue->head = NULL;
00196           queue->tail = NULL;
00197       }
00198       queue->count--;
00199        } else {
00200       ast_log(LOG_ERROR, "I SHOULD NEVER HAPPEN! EXPECT SOME MAJOR KABOOM! DUCK AND COVER!\n");
00201        }
00202        ast_mutex_unlock(&queue->lock);
00203        
00204        if (exstate) {
00205            if (esel_is_exported(esel->extensions, exstate)) {
00206           esel_export_to_remote(exstate, esel);
00207       }
00208       free(exstate);
00209       exstate = NULL;
00210        }     
00211    } else {
00212        if (esel->sockfd > 0)
00213       close(esel->sockfd);
00214        if ((esel->sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
00215       ast_log(LOG_ERROR, "unable to request socket!\n");
00216       return NULL;
00217        }
00218        /* try to connect */
00219        res = connect(esel->sockfd, (struct sockaddr *)&esel->raddr, sizeof(struct sockaddr));
00220        if (res) {
00221       ast_log(LOG_NOTICE, "error connecting to %s:%d\n", esel->host, esel->port);
00222        } else {
00223       while (strncasecmp(buf, "Asterisk Call Manager:", 21)) {
00224           if ((numbytes=recv(esel->sockfd, buf, sizeof(buf), 0)) == -1) {
00225          esel->connected = 0;
00226          continue;
00227           }
00228           buf[numbytes] = '\0';
00229       //    ast_log(LOG_NOTICE, "read: %s", buf);
00230       }
00231       /* log into remote manager */
00232       memset(msg, 0x0, sizeof(msg));
00233       snprintf(msg, sizeof(msg) - 1, "Action: Login\r\nUsername: %s\r\nSecret: %s\r\n\r\n", esel->username, esel->secret);
00234       sent = send(esel->sockfd, msg, strlen(msg), 0);
00235    
00236       while (strncasecmp(buf, "Response:", 9)) {
00237           if ((numbytes=recv(esel->sockfd, buf, sizeof(buf), 0)) == -1) {
00238          continue;
00239           }
00240           buf[numbytes] = '\0';
00241       //    ast_log(LOG_NOTICE, "read: %s", buf);
00242       }
00243    
00244       if (!strncasecmp(buf, "Response: Success", 17)) {
00245           esel->connected = 1;
00246       } else {
00247           ast_log(LOG_ERROR, "error login into remote asterisk %s\n", esel->name);
00248       }
00249        }
00250        /* time heals everything... */
00251        sleep(10);
00252    }
00253     }
00254     return NULL;
00255 }

static void esel_export_to_remote ( struct esel_extension_state exstate,
struct esel_pvt esel 
) [static]

Definition at line 164 of file res_esel.c.

References esel_extension_state::cid_name, esel_extension_state::cid_num, esel_pvt::connected, esel_extension_state::devstate, esel_state2devstate(), esel_pvt::sockfd, and esel_extension_state::state.

Referenced by do_esel_thread().

00164                                                                                                {
00165     char msg[1024];
00166     int sent = 0;
00167     memset(msg, 0x0, sizeof(msg));
00168     snprintf(msg, sizeof(msg) - 1, "Action: Devstate\r\nDevstate: %s\r\nValue: %d\r\nCallerID: %s\r\nCallerIDName: %s\r\n\r\n", exstate->devstate, esel_state2devstate(exstate->state), exstate->cid_num, exstate->cid_name);
00169     sent = send(esel->sockfd, msg, strlen(msg), 0);
00170     if (sent == -1) {
00171    esel->connected = 0;
00172     }
00173 //    ast_log(LOG_NOTICE, "%s", msg);
00174 }

static int esel_is_exported ( struct esel_export extensions,
struct esel_extension_state exstate 
) [static]

Definition at line 139 of file res_esel.c.

References esel_extension_state::context, esel_export::context, esel_export::devstate, esel_extension_state::devstate, esel_extension_state::exten, esel_export::exten, and esel_export::next.

Referenced by do_esel_thread().

00139                                                                                                   {
00140     struct esel_export *export = NULL;
00141     export = extensions;
00142     while (export) {
00143    if ((!strcasecmp(export->exten, exstate->exten)) && (!strcasecmp(export->context, exstate->context))) {
00144        /* copy mapping */
00145        ast_copy_string(exstate->devstate, export->devstate, sizeof(exstate->devstate));
00146        return 1;
00147    }
00148    export = export->next;
00149     }
00150     return 0;
00151 }

static int esel_queue_extension_state ( struct esel_queue queue,
char *  context,
char *  exten,
int  state,
void *  data,
char *  cid_num,
char *  cid_name 
) [static]

Definition at line 98 of file res_esel.c.

References ast_cond_signal(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), esel_extension_state::cid_name, esel_extension_state::cid_num, esel_queue::cond, esel_extension_state::context, esel_queue::count, esel_extension_state::exten, free, esel_queue::head, esel_queue::lock, LOG_ERROR, LOG_WARNING, malloc, esel_extension_state::next, option_verbose, esel_extension_state::prev, esel_extension_state::state, and esel_queue::tail.

Referenced by esel_state_cb().

00098                                                                                                                                                   {
00099    struct esel_extension_state *exstate = NULL;
00100 
00101    exstate = malloc(sizeof(struct esel_extension_state));
00102    if (!exstate) {
00103        ast_log(LOG_ERROR, "Unable to malloc!\n");
00104        return 1;
00105    }
00106    memset(exstate,0,sizeof(struct esel_extension_state));
00107    exstate->next = NULL;
00108    exstate->prev = NULL;
00109 
00110    ast_mutex_lock(&queue->lock);
00111    if (queue->count > 100) {
00112        ast_mutex_unlock(&queue->lock);
00113        free(exstate);
00114        if (option_verbose > 5)
00115       ast_log(LOG_WARNING, "E.S.E.L Queue too long.\n");
00116        return -1;
00117    }
00118    ast_copy_string(exstate->exten, exten, sizeof(exstate->exten));
00119    ast_copy_string(exstate->context, context, sizeof(exstate->context));
00120    ast_copy_string(exstate->cid_num, cid_num, sizeof(exstate->cid_num));
00121    ast_copy_string(exstate->cid_name, cid_name, sizeof(exstate->cid_name));
00122    exstate->state = state;
00123    if (!queue->head) {
00124       /* Empty queue */
00125       queue->head = exstate;
00126       queue->tail = exstate;
00127    } else {
00128       /* Double link */
00129       queue->tail->next = exstate;
00130       exstate->prev = queue->tail;
00131       queue->tail = exstate;
00132    }
00133    queue->count++;
00134    ast_cond_signal(&queue->cond);
00135    ast_mutex_unlock(&queue->lock);
00136    return 0;
00137 }

static int esel_state2devstate ( int  state  )  [static]

Definition at line 153 of file res_esel.c.

Referenced by esel_export_to_remote().

00153                                           {
00154     switch(state) {
00155    case 1:
00156        return 2;
00157    case 8:
00158        return 6;
00159    default:
00160        return state;
00161     }
00162 }

static int esel_state_cb ( char *  context,
char *  exten,
int  state,
void *  data,
char *  cid_num,
char *  cid_name 
) [static]

Definition at line 257 of file res_esel.c.

References ast_mutex_lock(), ast_mutex_unlock(), esel_queue_extension_state(), esel_pvt::next, and esel_pvt::queue.

Referenced by load_module().

00257                                                                                                            {
00258    struct esel_pvt *esel;
00259 
00260    esel = donkeys;
00261         ast_mutex_lock(&listlock);
00262    while (esel) {
00263        esel_queue_extension_state(&esel->queue, context, exten, state, data, cid_num, cid_name);
00264        esel = esel->next;
00265    }
00266         ast_mutex_unlock(&listlock);
00267    return 0;
00268 }

static int load_module ( void   )  [static]

Definition at line 271 of file res_esel.c.

References ast_category_browse(), ast_cond_init(), ast_config_destroy(), ast_config_load(), ast_extension_state_add(), ast_gethostbyname(), ast_log(), ast_mutex_init(), ast_pthread_create, ast_variable_browse(), ast_variable_retrieve(), ast_verbose(), esel_queue::cond, esel_pvt::connected, esel_export::context, esel_export::devstate, do_esel_thread(), esel_state_cb(), esel_pvt::esel_thread, esel_export::exten, esel_pvt::extensions, esel_pvt::host, esel_queue::lock, LOG_ERROR, malloc, ast_variable::name, esel_pvt::name, name, esel_pvt::next, ast_variable::next, esel_export::next, option_verbose, esel_pvt::port, esel_pvt::queue, esel_pvt::raddr, esel_pvt::secret, secret, esel_pvt::username, username, ast_variable::value, var, and VERBOSE_PREFIX_3.

00272 {
00273    int res = 0;
00274    const char *cat, *host, *port, *username, *secret, *name;
00275    struct ast_config *cfg;
00276    struct ast_variable *var;
00277    struct esel_pvt *esel = NULL;
00278    struct esel_export *export = NULL;
00279    struct hostent *he;
00280    struct ast_hostent h;
00281 
00282    cfg = ast_config_load("esel.conf");
00283    if (cfg) {
00284        cat = ast_category_browse(cfg, NULL);
00285        while(cat) {
00286       name = cat;
00287       host = ast_variable_retrieve(cfg, cat, "host");
00288       username = ast_variable_retrieve(cfg, cat, "username");
00289       secret = ast_variable_retrieve(cfg, cat, "secret");
00290       port = ast_variable_retrieve(cfg, cat, "port");
00291 
00292       if (name && host && username && secret && port) {
00293           esel = malloc(sizeof(struct esel_pvt));
00294           if (!esel) {
00295          ast_log(LOG_ERROR, "unable to malloc!\n");
00296          return -1;
00297           }
00298           memset(esel, 0x0, sizeof(struct esel_pvt));
00299           ast_copy_string(esel->name, name, sizeof(esel->name));
00300           ast_copy_string(esel->host, host, sizeof(esel->host));
00301           ast_copy_string(esel->username, username, sizeof(esel->username));
00302           ast_copy_string(esel->secret, secret, sizeof(esel->secret));
00303           
00304           esel->port = atoi(port);
00305           if ((he=ast_gethostbyname(host, &h)) == NULL) {
00306          ast_log(LOG_ERROR, "unknown host!\n");
00307          return -1;
00308           }
00309 
00310           esel->raddr.sin_family = AF_INET;
00311           esel->raddr.sin_port = htons(esel->port);
00312           esel->raddr.sin_addr = *((struct in_addr *)he->h_addr);
00313           bzero(&(esel->raddr.sin_zero), 8);  
00314           
00315           esel->connected = 0;
00316 
00317           ast_mutex_init(&esel->queue.lock);
00318           ast_cond_init(&esel->queue.cond, NULL);
00319 
00320 
00321           /* read exports */
00322           var = ast_variable_browse(cfg, cat);
00323           while (var) {
00324          if (!strcasecmp(var->name, "export")) {
00325              char *extenp = NULL, *contextp = NULL, *devstatep = NULL;
00326              extenp = var->value;
00327              devstatep = strchr(var->value, ',') + 1;
00328              contextp = strchr(var->value, '@') + 1;
00329              if (devstatep && contextp) {
00330             export = malloc(sizeof(struct esel_export));
00331             if (!export) {
00332                 ast_log(LOG_ERROR, "unable to malloc!\n");
00333                 return -1;
00334             }
00335             memset(export, 0x0, sizeof(struct esel_export));
00336                ast_copy_string(export->exten, extenp, contextp - extenp);
00337                ast_copy_string(export->context, contextp, devstatep - contextp);
00338                ast_copy_string(export->devstate, devstatep, sizeof(export->devstate));
00339             if (option_verbose > 2)
00340                 ast_verbose(VERBOSE_PREFIX_3 "exporting %s @ %s as %s to %s\n", export->exten, export->context , export->devstate , esel->name);          
00341             export->next = esel->extensions;
00342             esel->extensions = export;
00343             export = NULL;
00344              }
00345          }
00346          var = var->next;
00347           }
00348 
00349 
00350 
00351           esel->next = donkeys;
00352           donkeys = esel;
00353 
00354           ast_pthread_create(&esel->esel_thread, NULL, do_esel_thread, esel);
00355 
00356       }
00357       cat = ast_category_browse(cfg, cat);
00358        }
00359           ast_config_destroy(cfg);
00360    }
00361    ast_extension_state_add(NULL, NULL, esel_state_cb, NULL);
00362    return res;
00363 }

static int unload_module ( void   )  [static]

Definition at line 366 of file res_esel.c.

References ast_module_user_hangup_all, ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), esel_pvt::esel_thread, free, esel_queue::lock, esel_pvt::next, esel_pvt::queue, and esel_pvt::sockfd.

00367 {
00368    struct esel_pvt *esel, *eseln;
00369    ast_module_user_hangup_all();
00370    esel = donkeys;
00371         ast_mutex_lock(&listlock);
00372    while (esel) {
00373        pthread_cancel(esel->esel_thread);
00374        pthread_join(esel->esel_thread, NULL);
00375        ast_mutex_destroy(&esel->queue.lock);
00376        close(esel->sockfd);
00377        eseln = esel->next;
00378        free(esel);
00379        esel = eseln;
00380    }
00381         ast_mutex_unlock(&listlock);
00382    return 0;
00383 }


Variable Documentation

struct esel_pvt* donkeys = NULL [static]

Definition at line 96 of file res_esel.c.


Generated on Sun Dec 18 20:55:53 2011 for Asterisk - the Open Source PBX by  doxygen 1.5.6