#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"
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_pvt * | donkeys = NULL |
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 }
Definition at line 96 of file res_esel.c.