static void *attempt_thread(void *data) { struct outgoing *o = (struct outgoing *) data; int res, reason; if (!cw_strlen_zero(o->app)) { if (option_verbose > 2) cw_verbose(VERBOSE_PREFIX_3 "Attempting call on %s/%s for application %s(%s) (Retry %d)\n", o->tech, o->dest, o->app, o->data, o->retries); res = cw_pbx_outgoing_app(o->tech, CW_FORMAT_SLINEAR, o->dest, o->waittime * 1000, o->app, o->data, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, NULL); } else { if (option_verbose > 2) cw_verbose(VERBOSE_PREFIX_3 "Attempting call on %s/%s for %s@%s:%d (Retry %d)\n", o->tech, o->dest, o->exten, o->context,o->priority, o->retries); res = cw_pbx_outgoing_exten(o->tech, CW_FORMAT_SLINEAR, o->dest, o->waittime * 1000, o->context, o->exten, o->priority, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, NULL); } if (res) { cw_log(LOG_NOTICE, "Call failed to go through, reason %d\n", reason); if (o->retries >= o->maxretries + 1) { /* Max retries exceeded */ cw_log(LOG_EVENT, "Queued call to %s/%s expired without completion after %d attempt%s\n", o->tech, o->dest, o->retries - 1, ((o->retries - 1) != 1) ? "s" : ""); unlink(o->fn); } else { /* Notate that the call is still active */ safe_append(o, time(NULL), "EndRetry"); } } else { cw_log(LOG_NOTICE, "Call completed to %s/%s\n", o->tech, o->dest); cw_log(LOG_EVENT, "Queued call to %s/%s completed\n", o->tech, o->dest); unlink(o->fn); } free_outgoing(o); return NULL; }
int unload_module(void) { cw_verbose(VERBOSE_PREFIX_1 "Unloading [Sub]Agent Module\n"); res_snmp_dont_stop = 0; return ((thread != CW_PTHREADT_NULL) ? pthread_join(thread, NULL) : 0); }
static int settransfercapability_exec(struct cw_channel *chan, int argc, char **argv) { struct localuser *u; int x; int transfercapability = -1; LOCAL_USER_ADD(u); for (x = 0; x < (sizeof(transcaps) / sizeof(transcaps[0])); x++) { if (!strcasecmp(transcaps[x].name, argv[0])) { transfercapability = transcaps[x].val; break; } } if (transfercapability < 0) { cw_log(LOG_WARNING, "'%s' is not a valid transfer capability (see 'show application SetTransferCapability')\n", argv[0]); LOCAL_USER_REMOVE(u); return 0; } chan->transfercapability = (unsigned short)transfercapability; if (option_verbose > 2) cw_verbose(VERBOSE_PREFIX_3 "Setting transfer capability to: 0x%.2x - %s.\n", transfercapability, argv[0]); LOCAL_USER_REMOVE(u); return 0; }
int icd_module_unload(void) { /*TODO didnt get this far */ cw_verbose(VERBOSE_PREFIX_3 "Unloaded ICD Module[MatchAgent]!\n"); return 0; }
/* Configure an customer. data is a config obj. */ icd_status init_icd_customer(icd_customer * that, icd_config * data) { icd_status(*init) (icd_customer * that, icd_config * data); char *moh; icd_caller *caller = (icd_caller *) that; icd_status result; assert(that != NULL); if (that->allocated != 1) ICD_MEMSET_ZERO(that, sizeof(icd_caller)); /* Initialize base class */ result = init_icd_caller((icd_caller *) that, data); if (result != ICD_SUCCESS) { return result; } icd_caller__add_role((icd_caller *) that, ICD_CUSTOMER_ROLE); moh = icd_caller__get_moh((icd_caller *) that); if (moh == NULL) { icd_caller__set_moh((icd_caller *) that, "default"); } /* Set plugable function pointer for Agent Caller plugable functions */ icd_caller__set_plugable_fn_ptr(caller, icd_customer_get_plugable_fns); /* * if we wanted to customized for a specific instance of a agent caller we can add * a pointer in the caller->plugable_fns_list for a speific dist use the family * of helpers in the plugable_fns_list.c otherwise we set the function ptrs to * the staic struc declared locally here in icd_agent_plugable_fns plugable_fns = (icd_plugable_fn *)icd_list__peek((icd_list *)caller->plugable_fns_list); icd_list_iterator *iter; iter = icd_list__get_iterator((icd_list *)(caller->plugable_fns_list)); while (icd_list_iterator__has_more(iter)) { plugable_fns = (icd_plugable_fn *)icd_list_iterator__next(iter); result = icd_plugable__set_state_call_end_fn(plugable_fns, icd_customer__standard_state_call_end, NULL); result = icd_plugable__set_cleanup_caller_fn(plugable_fns, icd_customer__standard_cleanup_caller); } destroy_icd_list_iterator(&iter); */ /* fix me This is supposed to be the agent_init in a loadable module * icd_config_registry__register_ptr(registry, "customer.init", "myModule", * icd_module__init_agent); * then we run * icd_config__get_any_value(data, "customer.init.", myModule_init_agent_) */ init = (icd_status(*)(icd_customer * that, icd_config * data)) icd_config__get_value(data, "customers.init"); if (init != NULL) { cw_verbose(VERBOSE_PREFIX_1 "Customer plugable init for [%s] \n", icd_caller__get_name(caller)); return init(that, data); } return ICD_SUCCESS; }
static void *icd_distributor__match_agent_run(void *that) { icd_distributor *dist; icd_status result; assert(that != NULL); assert(((icd_distributor *)that)->customers != NULL); assert(((icd_distributor *)that)->agents != NULL); dist = (icd_distributor *)that; while (dist->thread_state != ICD_THREAD_STATE_FINISHED) { if (dist->thread_state == ICD_THREAD_STATE_RUNNING) { result = icd_distributor__lock(dist); /* Distribute callers if we can, or pause until some are added */ while(icd_distributor__get_added_callers_number(dist) > 0){ icd_distributor__reset_added_callers_number(dist); if (icd_distributor__customers_pending(dist) && icd_distributor__agents_pending(dist)) { result = icd_distributor__unlock(dist); /* func ptr to the icd_distributor__link_callers_via_?? note may also come from custom * function eg from icd_mod_?? installed using icd_distributor__set_link_callers_fn */ if (icd_verbose > 4) cw_verbose(VERBOSE_PREFIX_3 "Distributor__run [%s] link_fn[%p] \n", icd_distributor__get_name(dist), dist->link_fn); result = dist->link_fn(dist, dist->link_fn_extra); result = icd_distributor__lock(dist); } } /* All distributor links are now created wait for changes of customer or agent list */ cw_cond_wait(&(dist->wakeup), &(dist->lock)); /* wait until signal received */ result = icd_distributor__unlock(dist); if (icd_verbose > 4) cw_verbose(VERBOSE_PREFIX_3 "Distributor__run [%s] wait \n", icd_distributor__get_name(dist)); } else { /* TBD - Make paused thread work better. * - Use pthread_cond_wait() * - Use same or different condition variable? */ } /* Play nice */ sched_yield(); } /* Do any cleanup here */ return NULL; }
int load_module(void) { if (!load_config()) return -1; cw_verbose(VERBOSE_PREFIX_1 "Loading [Sub]Agent Module\n"); res_snmp_dont_stop = 1; if (res_snmp_enabled) return cw_pthread_create(&thread, NULL, agent_thread, NULL); return 0; }
int cw_app_has_voicemail(const char *mailbox, const char *folder) { static int warned = 0; if (cw_has_voicemail_func) return cw_has_voicemail_func(mailbox, folder); if ((option_verbose > 2) && !warned) { cw_verbose(VERBOSE_PREFIX_3 "Message check requested for mailbox %s/folder %s but voicemail not loaded.\n", mailbox, folder ? folder : "INBOX"); warned++; } return 0; }
int icd_module_load(icd_config_registry * registry) { assert(registry != NULL); icd_config_registry__register_ptr(registry, "dist", "matchagent", init_icd_distributor_match_agent); icd_config_registry__register_ptr(registry, "dist.link", "popcustmatchagent", link_callers_via_pop_customer_match_agent ); cw_verbose(VERBOSE_PREFIX_3 "Registered ICD Module[MatchAgent]!\n"); return 0; }
int icd_module_load(icd_config_registry * registry) { assert(registry != NULL); module_id = icd_event_factory__add_module(module_name); if (module_id == 0) cw_log(LOG_WARNING, "Unable to register Module Name[%s]", module_name); else { icd_event_factory__add_listener(event_factory, queues, icd_module__event_cwmgr, NULL); cw_verbose(VERBOSE_PREFIX_3 "Registered ICD Module[%s]!\n",module_name); } return 0; }
int reload(void) { cw_verbose(VERBOSE_PREFIX_1 "Reloading [Sub]Agent Module\n"); res_snmp_dont_stop = 0; if (thread != CW_PTHREADT_NULL) pthread_join(thread, NULL); thread = CW_PTHREADT_NULL; load_config(); res_snmp_dont_stop = 1; if (res_snmp_enabled) return cw_pthread_create(&thread, NULL, agent_thread, NULL); return 0; }
/* Set global indication country */ int cw_set_indication_country(const char *country) { if (country) { struct tone_zone *z = cw_get_indication_zone(country); if (z) { if (option_verbose > 2) cw_verbose(VERBOSE_PREFIX_3 "Setting default indication country to '%s'\n",country); current_tonezone = z; return 0; } } return 1; /* not found */ }
static icd_status init_icd_distributor_match_agent(icd_distributor * that, char *name, icd_config * data) { assert(that != NULL); assert(data != NULL); strncpy(that->name, name, sizeof(that->name)); icd_distributor__set_config_params(that, data); icd_distributor__create_lists(that, data); icd_list__set_node_insert_func((icd_list *) that->agents, icd_list__insert_fifo, NULL); icd_distributor__set_link_callers_fn(that, link_callers_via_pop_customer_match_agent, NULL); icd_distributor__set_run_fn(that, icd_distributor__match_agent_run); icd_distributor__create_thread(that); cw_verbose(VERBOSE_PREFIX_3 "Registered ICD Distributor[%s] Initialized !\n", name); return ICD_SUCCESS; }
/* remove an existing country and all its indications, country must exist. * Also, all countries which are an alias for the specified country are removed. */ int cw_unregister_indication_country(const char *country) { struct tone_zone *tz, *pz = NULL, *tmp; int res = -1; if (cw_mutex_lock(&tzlock)) { cw_log(LOG_WARNING, "Unable to lock tone_zones list\n"); return -1; } tz = tone_zones; while (tz) { if (country == NULL || (strcasecmp(country, tz->country) == 0 || strcasecmp(country, tz->alias) == 0)) { /* tone_zone found, remove */ tmp = tz->next; if (pz) pz->next = tmp; else tone_zones = tmp; /* if we are unregistering the default country, w'll notice */ if (tz == current_tonezone) { cw_log(LOG_NOTICE,"Removed default indication country '%s'\n",tz->country); current_tonezone = NULL; } if (option_verbose > 2) cw_verbose(VERBOSE_PREFIX_3 "Unregistered indication country '%s'\n",tz->country); free_zone(tz); if (tone_zones == tz) tone_zones = tmp; tz = tmp; res = 0; } else { /* next zone please */ pz = tz; tz = tz->next; } } cw_mutex_unlock(&tzlock); return res; }
int cw_app_messagecount(const char *mailbox, int *newmsgs, int *oldmsgs) { static int warned = 0; if (newmsgs) *newmsgs = 0; if (oldmsgs) *oldmsgs = 0; if (cw_messagecount_func) return cw_messagecount_func(mailbox, newmsgs, oldmsgs); if (!warned && (option_verbose > 2)) { warned++; cw_verbose(VERBOSE_PREFIX_3 "Message count requested for mailbox %s but voicemail not loaded.\n", mailbox); } return 0; }
static int dumpchan_exec(struct cw_channel *chan, int argc, char **argv) { static char *line = "================================================================================"; char vars[1024]; char info[1024]; struct localuser *u; int level; LOCAL_USER_ADD(u); level = (argc > 0 ? atoi(argv[0]) : 0); if (option_verbose >= level) { cw_serialize_showchan(chan, info, sizeof(info)); pbx_builtin_serialize_variables(chan, vars, sizeof(vars)); cw_verbose("\nDumping Info For Channel: %s:\n%s\nInfo:\n%s\nVariables:\n%s%s\n", chan->name, line, info, vars, line); } LOCAL_USER_REMOVE(u); return 0; }
/* add a new country, if country exists, it will be replaced. */ int cw_register_indication_country(struct tone_zone *zone) { struct tone_zone *tz,*pz; if (cw_mutex_lock(&tzlock)) { cw_log(LOG_WARNING, "Unable to lock tone_zones list\n"); return -1; } for (pz = NULL, tz = tone_zones; tz; pz = tz, tz = tz->next) { if (strcasecmp(zone->country,tz->country) == 0) { /* tone_zone already there, replace */ zone->next = tz->next; if (pz) pz->next = zone; else tone_zones = zone; /* if we are replacing the default zone, re-point it */ if (tz == current_tonezone) current_tonezone = zone; /* now free the previous zone */ free_zone(tz); cw_mutex_unlock(&tzlock); return 0; } } /* country not there, add */ zone->next = NULL; if (pz) pz->next = zone; else tone_zones = zone; cw_mutex_unlock(&tzlock); if (option_verbose > 2) cw_verbose(VERBOSE_PREFIX_3 "Registered indication country '%s'\n",zone->country); return 0; }
static void parse_config(void) { struct cw_config *cfg; struct cw_variable *var; if ((cfg = cw_config_load("codecs.conf"))) { if ((var = cw_variable_browse(cfg, "plc"))) { while (var) { if (!strcasecmp(var->name, "genericplc")) { useplc = cw_true(var->value) ? 1 : 0; if (option_verbose > 2) cw_verbose(VERBOSE_PREFIX_3 "codec_g722: %susing generic PLC\n", useplc ? "" : "not "); } var = var->next; } } cw_config_destroy(cfg); } }
/* Match the customers "identifier" to the agents "identifier". * the "identifier" is set to what ever value is required typical use case * agent identifier=agent_id and the customer identifier = agent_id * exten => 9001,1,icd_customer(identifier=123|name=roundrobin-customer|queue=roundrobin_q|moh=ringing) * exten => 8001,1,icd_agent(identifier=123|agent=101|noauth=1|queue=test_q * */ icd_status link_callers_via_pop_customer_match_agent(icd_distributor * dist, void *extra) { icd_member *customer = NULL; icd_member *agent = NULL; icd_caller *customer_caller = NULL; icd_caller *agent_caller = NULL; char *tmp_str; icd_list_iterator *iter; icd_status result; int LinkFound; assert(dist != NULL); assert(dist->customers != NULL); assert(dist->agents != NULL); if (!icd_member_list__has_members(dist->customers)) { return ICD_ENOTFOUND; } if (!icd_member_list__has_members(dist->agents)) { return ICD_ENOTFOUND; } /* Go through all the customers looking for a match */ /* For each customer on the list, try to find the match agent. * Return after all customer has been pass looked over once */ while(1){ LinkFound = 0; result = icd_member_list__lock(dist->customers); iter = icd_distributor__get_customer_iterator(dist); while (icd_list_iterator__has_more_nolock(iter)) { customer = (icd_member *) icd_list_iterator__next(iter); if (customer != NULL) { customer_caller = icd_member__get_caller(customer); } if (customer == NULL || customer_caller == NULL) { cw_log(LOG_ERROR, "MatchAgent Distributor %s could not retrieve customer from list\n", icd_distributor__get_name(dist)); continue; } tmp_str = icd_caller__get_param(customer_caller, "identifier"); if (tmp_str == NULL) { cw_log(LOG_WARNING, "MatchAgent Distributor [%s] reports that customer [%s] has no identifier\n", icd_distributor__get_name(dist), icd_caller__get_name(customer_caller)); continue; } agent_caller = (icd_caller *) icd_fieldset__get_value(agents, tmp_str); if (agent_caller == NULL) { cw_log(LOG_WARNING, "MatchAgent Distributor [%s] reports that agent [%s] is not in ICD\n", icd_distributor__get_name(dist), tmp_str); continue; } if(icd_caller__get_state(agent_caller) != ICD_CALLER_STATE_READY){ continue; } icd_member_list__lock(dist->agents); agent = icd_member_list__get_for_caller(dist->agents, agent_caller); if (agent == NULL ) { /* cw_log(LOG_WARNING, "MatchAgent Distributor [%s] reports that agent [%s] is not in distributor\n", icd_distributor__get_name(dist), tmp_str); */ icd_member_list__unlock(dist->agents); continue; } if (icd_member__lock(agent) != ICD_SUCCESS){ icd_member_list__unlock(dist->agents); continue; } icd_member_list__unlock(dist->agents); result = icd_member__distribute(agent); if (result != ICD_SUCCESS) { cw_log(LOG_WARNING, "MatchAgent Distributor [%s] reports that cannot distribute agent [%s]\n", icd_distributor__get_name(dist), tmp_str); icd_member__unlock(agent); continue; } if(icd_caller__get_state(customer_caller) == ICD_CALLER_STATE_READY){ icd_caller__lock(customer_caller); if(icd_caller__get_state(customer_caller) == ICD_CALLER_STATE_READY){ /* Still in READY state - OK */ result = ICD_SUCCESS; } else { result = ICD_ERESOURCE; icd_caller__unlock(customer_caller); } } else { result = ICD_ERESOURCE; } if (result != ICD_SUCCESS) { icd_caller__set_state(agent_caller, ICD_CALLER_STATE_READY); icd_member__unlock(agent); continue; } result = icd_member__distribute(customer); if (result != ICD_SUCCESS) { icd_caller__unlock(customer_caller); icd_caller__set_state(agent_caller, ICD_CALLER_STATE_READY); icd_member__unlock(agent); continue; } LinkFound = 1; icd_member_list__unlock(dist->customers); result = icd_caller__join_callers(customer_caller, agent_caller); if (result != ICD_SUCCESS) { icd_caller__set_state(customer_caller, ICD_CALLER_STATE_READY); icd_caller__set_state(agent_caller, ICD_CALLER_STATE_READY); icd_caller__unlock(customer_caller); icd_member__unlock(agent); } else { /* Figure out who the bridger is, and who the bridgee is */ result = icd_distributor__select_bridger(agent_caller, customer_caller); cw_verbose(VERBOSE_PREFIX_3 "MatchAgent Distributor [%s] Link CustomerID[%d] to AgentID[%d]\n", icd_distributor__get_name(dist), icd_caller__get_id(customer_caller), icd_caller__get_id(agent_caller)); if (icd_caller__has_role(customer_caller, ICD_BRIDGER_ROLE)) { result = icd_caller__bridge(customer_caller); } else if (icd_caller__has_role(agent_caller, ICD_BRIDGER_ROLE)) { result = icd_caller__bridge(agent_caller); } else { cw_log(LOG_ERROR, "MatchAgent Distributor %s found no bridger responsible to bridge call\n", icd_distributor__get_name(dist)); icd_caller__set_state(agent_caller, ICD_CALLER_STATE_READY); icd_caller__set_state(customer_caller, ICD_CALLER_STATE_READY); icd_caller__unlock(customer_caller); icd_member__unlock(agent); continue; } } if( LinkFound) { icd_caller__unlock(customer_caller); icd_member__unlock(agent); break; } } /* while (icd_list_iterator__has_more(iter)) */ if(! LinkFound) { result = icd_member_list__unlock(dist->customers); } destroy_icd_list_iterator(&iter); if(! LinkFound) { break; } } return ICD_SUCCESS; }
int icd_module_unload(void) { cw_verbose(VERBOSE_PREFIX_3 "Unloaded ICD Module[%s]!\n", module_name); return 0; }
static int changrab_cli(int fd, int argc, char *argv[]) { char *chan_name_1, *chan_name_2 = NULL, *context,*exten,*flags=NULL; char *pria = NULL; struct cw_channel *xferchan_1, *xferchan_2; int pri=0,x=1; if(argc < 3) { cw_cli(fd,CGUSAGE); return -1; } chan_name_1 = argv[x++]; if(chan_name_1[0] == '-') { flags = cw_strdupa(chan_name_1); if (strchr(flags,'h')) { chan_name_1 = argv[x++]; if((xferchan_1 = my_cw_get_channel_by_name_locked(chan_name_1))) { cw_mutex_unlock(&xferchan_1->lock); cw_hangup(xferchan_1); cw_verbose("OK, good luck!\n"); return 0; } else return -1; } else if (strchr(flags,'m') || strchr(flags,'M')) { chan_name_1 = argv[x++]; if((xferchan_1 = my_cw_get_channel_by_name_locked(chan_name_1))) { cw_mutex_unlock(&xferchan_1->lock); strchr(flags,'m') ? cw_moh_start(xferchan_1,NULL) : cw_moh_stop(xferchan_1); } else return 1; return 0; } if(argc < 4) { cw_cli(fd,CGUSAGE); return -1; } chan_name_1 = argv[x++]; } exten = cw_strdupa(argv[x++]); if((context = strchr(exten,'@'))) { *context = 0; context++; if(!(context && exten)) { cw_cli(fd,CGUSAGE); return -1; } if((pria = strchr(context,':'))) { *pria = '\0'; pria++; pri = atoi(pria); } else { pri = argv[x] ? atoi(argv[x++]) : 1; } if(!pri) pri = 1; } else if (strchr(exten,'/')) { chan_name_2 = exten; } xferchan_1 = my_cw_get_channel_by_name_locked(chan_name_1); if(!xferchan_1) { cw_log(LOG_WARNING, "No Such Channel: %s\n",chan_name_1); return -1; } cw_mutex_unlock(&xferchan_1->lock); if(flags && strchr(flags,'b')) { if(cw_bridged_channel(xferchan_1)) { xferchan_1 = cw_bridged_channel(xferchan_1); } } if(chan_name_2) { struct cw_frame *f; struct cw_channel *newchan_1, *newchan_2; if (!(newchan_1 = cw_channel_alloc(0))) { cw_log(LOG_WARNING, "Memory Error!\n"); cw_hangup(newchan_1); return -1; } else { snprintf(newchan_1->name, sizeof (newchan_1->name), "ChanGrab/%s", xferchan_1->name); newchan_1->readformat = xferchan_1->readformat; newchan_1->writeformat = xferchan_1->writeformat; cw_channel_masquerade(newchan_1, xferchan_1); if ((f = cw_read(newchan_1))) { cw_fr_free(f); } else { cw_hangup(newchan_1); return -1; } } if(!(xferchan_2 = my_cw_get_channel_by_name_locked(chan_name_2))) { cw_log(LOG_WARNING, "No Such Channel: %s\n",chan_name_2); cw_hangup(newchan_1); return -1; } cw_mutex_unlock(&xferchan_2->lock); if(flags && strchr(flags, 'B')) { if(cw_bridged_channel(xferchan_2)) { xferchan_2 = cw_bridged_channel(xferchan_2); } } if(!(newchan_2 = cw_channel_alloc(0))) { cw_log(LOG_WARNING, "Memory Error!\n"); cw_hangup(newchan_1); return -1; } else { snprintf(newchan_2->name, sizeof (newchan_2->name), "ChanGrab/%s", xferchan_2->name); newchan_2->readformat = xferchan_2->readformat; newchan_2->writeformat = xferchan_2->writeformat; cw_channel_masquerade(newchan_2, xferchan_2); if ((f = cw_read(newchan_2))) { cw_fr_free(f); } else { cw_hangup(newchan_1); cw_hangup(newchan_2); return -1; } } cw_bridge_call_thread_launch(newchan_1, newchan_2); } else { cw_verbose("Transferring_to context %s, extension %s, priority %d\n", context, exten, pri); cw_async_goto(xferchan_1, context, exten, pri); if(xferchan_1) cw_mutex_unlock(&xferchan_1->lock); } return 0; }
static int _while_exec(struct cw_channel *chan, int argc, char **argv, int end) { int res=0; struct localuser *u; char *while_pri = NULL; char *goto_str = NULL, *my_name = NULL; char *label = NULL; char varname[VAR_SIZE], end_varname[VAR_SIZE]; const char *prefix = "WHILE"; size_t size=0; int used_index_i = -1, x=0; char used_index[VAR_SIZE] = "0", new_index[VAR_SIZE] = "0"; if (!end && argc != 1) { cw_log(LOG_ERROR, "Syntax: %s\n", while_syntax); return -1; } if (!chan) { /* huh ? */ return -1; } LOCAL_USER_ADD(u); /* dont want run away loops if the chan isn't even up this is up for debate since it slows things down a tad ...... */ if (cw_waitfordigit(chan,1) < 0) ALL_DONE(u,-1); for (x=0;;x++) { if (get_index(chan, prefix, x)) { used_index_i = x; } else break; } snprintf(used_index, VAR_SIZE, "%d", used_index_i); snprintf(new_index, VAR_SIZE, "%d", used_index_i + 1); size = strlen(chan->context) + strlen(chan->exten) + 32; my_name = alloca(size); snprintf(my_name, size, "%s_%s_%d", chan->context, chan->exten, chan->priority); if (cw_strlen_zero(label)) { if (end) label = used_index; else if (!(label = pbx_builtin_getvar_helper(chan, my_name))) { label = new_index; pbx_builtin_setvar_helper(chan, my_name, label); } } snprintf(varname, VAR_SIZE, "%s_%s", prefix, label); while_pri = pbx_builtin_getvar_helper(chan, varname); if ((while_pri = pbx_builtin_getvar_helper(chan, varname)) && !end) { snprintf(end_varname, VAR_SIZE, "END_%s", varname); } if (!end && !cw_true(argv[0])) { /* Condition Met (clean up helper vars) */ pbx_builtin_setvar_helper(chan, varname, NULL); pbx_builtin_setvar_helper(chan, my_name, NULL); snprintf(end_varname, VAR_SIZE, "END_%s", varname); if ((goto_str=pbx_builtin_getvar_helper(chan, end_varname))) { pbx_builtin_setvar_helper(chan, end_varname, NULL); cw_parseable_goto(chan, goto_str); } else { int pri = find_matching_endwhile(chan); if (pri > 0) { if (option_verbose > 2) cw_verbose(VERBOSE_PREFIX_3 "Jumping to priority %d\n", pri); chan->priority = pri; } else { cw_log(LOG_WARNING, "Couldn't find matching EndWhile? (While at %s@%s priority %d)\n", chan->context, chan->exten, chan->priority); } } ALL_DONE(u,res); } if (!end && !while_pri) { size = strlen(chan->context) + strlen(chan->exten) + 32; goto_str = alloca(size); snprintf(goto_str, size, "%s,%s,%d", chan->context, chan->exten, chan->priority); pbx_builtin_setvar_helper(chan, varname, goto_str); } else if (end && while_pri) { /* END of loop */ snprintf(end_varname, VAR_SIZE, "END_%s", varname); if (! pbx_builtin_getvar_helper(chan, end_varname)) { size = strlen(chan->context) + strlen(chan->exten) + 32; goto_str = alloca(size); snprintf(goto_str, size, "%s,%s,%d", chan->context, chan->exten, chan->priority+1); pbx_builtin_setvar_helper(chan, end_varname, goto_str); } cw_parseable_goto(chan, while_pri); } ALL_DONE(u, res); }
int cw_record_review(struct cw_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, const char *path) { int silencethreshold = 128; int maxsilence=0; int res = 0; int cmd = 0; int max_attempts = 3; int attempts = 0; int recorded = 0; int message_exists = 0; /* Note that urgent and private are for flagging messages as such in the future */ /* barf if no pointer passed to store duration in */ if (duration == NULL) { cw_log(LOG_WARNING, "Error cw_record_review called without duration pointer\n"); return -1; } cmd = '3'; /* Want to start by recording */ while ((cmd >= 0) && (cmd != 't')) { switch (cmd) { case '1': if (!message_exists) { /* In this case, 1 is to record a message */ cmd = '3'; break; } else { cw_streamfile(chan, "vm-msgsaved", chan->language); cw_waitstream(chan, ""); cmd = 't'; return res; } case '2': /* Review */ cw_verbose(VERBOSE_PREFIX_3 "Reviewing the recording\n"); cw_streamfile(chan, recordfile, chan->language); cmd = cw_waitstream(chan, CW_DIGIT_ANY); break; case '3': message_exists = 0; /* Record */ if (recorded == 1) cw_verbose(VERBOSE_PREFIX_3 "Re-recording\n"); else cw_verbose(VERBOSE_PREFIX_3 "Recording\n"); recorded = 1; cmd = cw_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, silencethreshold, maxsilence, path); if (cmd == -1) { /* User has hung up, no options to give */ return cmd; } if (cmd == '0') { break; } else if (cmd == '*') { break; } else { /* If all is well, a message exists */ message_exists = 1; cmd = 0; } break; case '4': case '5': case '6': case '7': case '8': case '9': case '*': case '#': cmd = cw_play_and_wait(chan, "vm-sorry"); break; default: if (message_exists) { cmd = cw_play_and_wait(chan, "vm-review"); } else { cmd = cw_play_and_wait(chan, "vm-torerecord"); if (!cmd) cmd = cw_waitfordigit(chan, 600); } if (!cmd) cmd = cw_waitfordigit(chan, 6000); if (!cmd) { attempts++; } if (attempts > max_attempts) { cmd = 't'; } } } if (cmd == 't') cmd = 0; return cmd; }
static int visdn_ppp_exec(struct cw_channel *chan, int argc, char **argv) { struct visdn_chan *visdn_chan; const char **nargv; struct localuser *u; struct cw_frame *f; int res=-1; LOCAL_USER_ADD(u); if (chan->_state != CW_STATE_UP) cw_answer(chan); cw_mutex_lock(&chan->lock); if (strcmp(chan->type, "VISDN")) { cw_log(LOG_WARNING, "Only VISDN channels may be connected to" " this application\n"); cw_mutex_unlock(&chan->lock); return -1; } visdn_chan = chan->tech_pvt; if (!strlen(visdn_chan->visdn_chanid)) { cw_log(LOG_WARNING, "vISDN crossconnector channel ID not present\n"); cw_mutex_unlock(&chan->lock); return -1; } nargv = alloca((2 + argc + 3 + 1) * sizeof(nargv[0])); nargv[0] = PPP_EXEC; nargv[1] = "nodetach"; memcpy(nargv + 2, argc, argv * sizeof(argv[0])); nargv[2 + argc + 0] = "plugin"; nargv[2 + argc + 1] = "visdn.so"; nargv[2 + argc + 2] = visdn_chan->visdn_chanid; nargv[2 + argc + 3] = NULL; cw_mutex_unlock(&chan->lock); #if 0 int i; for (i=0;i<argc;i++) { cw_log(LOG_NOTICE, "Arg %d: %s\n", i, argv[i]); } #endif signal(SIGCHLD, SIG_DFL); pid_t pid = spawn_ppp(chan, nargv); if (pid < 0) { cw_log(LOG_WARNING, "Failed to spawn pppd\n"); return -1; } while(cw_waitfor(chan, -1) > -1) { f = cw_read(chan); if (!f) { cw_log(LOG_NOTICE, "Channel '%s' hungup." " Signalling PPP at %d to die...\n", chan->name, pid); kill(pid, SIGTERM); break; } cw_fr_free(f); int status; res = wait4(pid, &status, WNOHANG, NULL); if (res < 0) { cw_log(LOG_WARNING, "wait4 returned %d: %s\n", res, strerror(errno)); break; } else if (res > 0) { if (option_verbose > 2) { if (WIFEXITED(status)) { cw_verbose(VERBOSE_PREFIX_3 "PPP on %s terminated with status %d\n", chan->name, WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { cw_verbose(VERBOSE_PREFIX_3 "PPP on %s terminated with signal %d\n", chan->name, WTERMSIG(status)); } else { cw_verbose(VERBOSE_PREFIX_3 "PPP on %s terminated weirdly.\n", chan->name); } } break; } } LOCAL_USER_REMOVE(u); return res; }
int cw_play_and_record(struct cw_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int silencethreshold, int maxsilence, const char *path) { int d; char *fmts; char comment[256]; int x, fmtcnt=1, res=-1,outmsg=0; struct cw_frame *f; struct cw_filestream *others[MAX_OTHER_FORMATS]; char *sfmt[MAX_OTHER_FORMATS]; char *stringp=NULL; time_t start, end; struct cw_dsp *sildet=NULL; /* silence detector dsp */ int totalsilence = 0; int dspsilence = 0; int gotsilence = 0; /* did we timeout for silence? */ int rfmt=0; if (silencethreshold < 0) silencethreshold = global_silence_threshold; if (maxsilence < 0) maxsilence = global_maxsilence; /* barf if no pointer passed to store duration in */ if (duration == NULL) { cw_log(LOG_WARNING, "Error play_and_record called without duration pointer\n"); return -1; } cw_log(LOG_DEBUG,"play_and_record: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt); snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name); if (playfile) { d = cw_play_and_wait(chan, playfile); if (d > -1) d = cw_streamfile(chan, "beep",chan->language); if (!d) d = cw_waitstream(chan,""); if (d < 0) return -1; } fmts = cw_strdupa(fmt); stringp=fmts; strsep(&stringp, "|,"); cw_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts); sfmt[0] = cw_strdupa(fmts); while((fmt = strsep(&stringp, "|,"))) { if (fmtcnt > MAX_OTHER_FORMATS - 1) { cw_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app_voicemail.c\n"); break; } sfmt[fmtcnt++] = cw_strdupa(fmt); } time(&start); end=start; /* pre-initialize end to be same as start in case we never get into loop */ for (x=0;x<fmtcnt;x++) { others[x] = cw_writefile(recordfile, sfmt[x], comment, O_TRUNC, 0, 0700); cw_verbose( VERBOSE_PREFIX_3 "x=%d, open writing: %s format: %s, %p\n", x, recordfile, sfmt[x], others[x]); if (!others[x]) { break; } } if (path) cw_unlock_path(path); if (maxsilence > 0) { sildet = cw_dsp_new(); /* Create the silence detector */ if (!sildet) { cw_log(LOG_WARNING, "Unable to create silence detector :(\n"); return -1; } cw_dsp_set_threshold(sildet, silencethreshold); rfmt = chan->readformat; res = cw_set_read_format(chan, CW_FORMAT_SLINEAR); if (res < 0) { cw_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); cw_dsp_free(sildet); return -1; } } /* Request a video update */ cw_indicate(chan, CW_CONTROL_VIDUPDATE); if (x == fmtcnt) { /* Loop forever, writing the packets we read to the writer(s), until we read a # or get a hangup */ f = NULL; for(;;) { res = cw_waitfor(chan, 2000); if (!res) { cw_log(LOG_DEBUG, "One waitfor failed, trying another\n"); /* Try one more time in case of masq */ res = cw_waitfor(chan, 2000); if (!res) { cw_log(LOG_WARNING, "No audio available on %s??\n", chan->name); res = -1; } } if (res < 0) { f = NULL; break; } f = cw_read(chan); if (!f) break; if (f->frametype == CW_FRAME_VOICE) { /* write each format */ for (x=0;x<fmtcnt;x++) { res = cw_writestream(others[x], f); } /* Silence Detection */ if (maxsilence > 0) { dspsilence = 0; cw_dsp_silence(sildet, f, &dspsilence); if (dspsilence) totalsilence = dspsilence; else totalsilence = 0; if (totalsilence > maxsilence) { /* Ended happily with silence */ if (option_verbose > 2) cw_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000); cw_fr_free(f); gotsilence = 1; outmsg=2; break; } } /* Exit on any error */ if (res) { cw_log(LOG_WARNING, "Error writing frame\n"); cw_fr_free(f); break; } } else if (f->frametype == CW_FRAME_VIDEO) { /* Write only once */ cw_writestream(others[0], f); } else if (f->frametype == CW_FRAME_DTMF) { if (f->subclass == '#') { if (option_verbose > 2) cw_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass); res = '#'; outmsg = 2; cw_fr_free(f); break; } if (f->subclass == '0') { /* Check for a '0' during message recording also, in case caller wants operator */ if (option_verbose > 2) cw_verbose(VERBOSE_PREFIX_3 "User cancelled by pressing %c\n", f->subclass); res = '0'; outmsg = 0; cw_fr_free(f); break; } } if (maxtime) { time(&end); if (maxtime < (end - start)) { if (option_verbose > 2) cw_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n"); outmsg = 2; res = 't'; cw_fr_free(f); break; } } cw_fr_free(f); } if (end == start) time(&end); if (!f) { if (option_verbose > 2) cw_verbose( VERBOSE_PREFIX_3 "User hung up\n"); res = -1; outmsg=1; } } else { cw_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", recordfile, sfmt[x]); } *duration = end - start; for (x=0;x<fmtcnt;x++) { if (!others[x]) break; if (res > 0) { if (totalsilence) cw_stream_rewind(others[x], totalsilence-200); else cw_stream_rewind(others[x], 200); } cw_truncstream(others[x]); cw_closestream(others[x]); } if (rfmt) { if (cw_set_read_format(chan, rfmt)) { cw_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", cw_getformatname(rfmt), chan->name); } } if (outmsg > 1) { /* Let them know recording is stopped */ if(!cw_streamfile(chan, "auth-thankyou", chan->language)) cw_waitstream(chan, ""); } if (sildet) cw_dsp_free(sildet); return res; }
int cw_play_and_prepend(struct cw_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int *duration, int beep, int silencethreshold, int maxsilence) { int d = 0; char *fmts; char comment[256]; int x, fmtcnt=1, res=-1,outmsg=0; struct cw_frame *f; struct cw_filestream *others[MAX_OTHER_FORMATS]; struct cw_filestream *realfiles[MAX_OTHER_FORMATS]; char *sfmt[MAX_OTHER_FORMATS]; char *stringp=NULL; time_t start, end; struct cw_dsp *sildet; /* silence detector dsp */ int totalsilence = 0; int dspsilence = 0; int gotsilence = 0; /* did we timeout for silence? */ int rfmt=0; char prependfile[80]; if (silencethreshold < 0) silencethreshold = global_silence_threshold; if (maxsilence < 0) maxsilence = global_maxsilence; /* barf if no pointer passed to store duration in */ if (duration == NULL) { cw_log(LOG_WARNING, "Error play_and_prepend called without duration pointer\n"); return -1; } cw_log(LOG_DEBUG,"play_and_prepend: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt); snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name); if (playfile || beep) { if (!beep) d = cw_play_and_wait(chan, playfile); if (d > -1) d = cw_streamfile(chan, "beep",chan->language); if (!d) d = cw_waitstream(chan,""); if (d < 0) return -1; } cw_copy_string(prependfile, recordfile, sizeof(prependfile)); strncat(prependfile, "-prepend", sizeof(prependfile) - strlen(prependfile) - 1); fmts = cw_strdupa(fmt); stringp=fmts; strsep(&stringp, "|,"); cw_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts); sfmt[0] = cw_strdupa(fmts); while((fmt = strsep(&stringp, "|,"))) { if (fmtcnt > MAX_OTHER_FORMATS - 1) { cw_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app_voicemail.c\n"); break; } sfmt[fmtcnt++] = cw_strdupa(fmt); } time(&start); end=start; /* pre-initialize end to be same as start in case we never get into loop */ for (x=0;x<fmtcnt;x++) { others[x] = cw_writefile(prependfile, sfmt[x], comment, O_TRUNC, 0, 0700); cw_verbose( VERBOSE_PREFIX_3 "x=%d, open writing: %s format: %s, %p\n", x, prependfile, sfmt[x], others[x]); if (!others[x]) { break; } } sildet = cw_dsp_new(); /* Create the silence detector */ if (!sildet) { cw_log(LOG_WARNING, "Unable to create silence detector :(\n"); return -1; } cw_dsp_set_threshold(sildet, silencethreshold); if (maxsilence > 0) { rfmt = chan->readformat; res = cw_set_read_format(chan, CW_FORMAT_SLINEAR); if (res < 0) { cw_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); return -1; } } if (x == fmtcnt) { /* Loop forever, writing the packets we read to the writer(s), until we read a # or get a hangup */ f = NULL; for(;;) { res = cw_waitfor(chan, 2000); if (!res) { cw_log(LOG_DEBUG, "One waitfor failed, trying another\n"); /* Try one more time in case of masq */ res = cw_waitfor(chan, 2000); if (!res) { cw_log(LOG_WARNING, "No audio available on %s??\n", chan->name); res = -1; } } if (res < 0) { f = NULL; break; } f = cw_read(chan); if (!f) break; if (f->frametype == CW_FRAME_VOICE) { /* write each format */ for (x=0;x<fmtcnt;x++) { if (!others[x]) break; res = cw_writestream(others[x], f); } /* Silence Detection */ if (maxsilence > 0) { dspsilence = 0; cw_dsp_silence(sildet, f, &dspsilence); if (dspsilence) totalsilence = dspsilence; else totalsilence = 0; if (totalsilence > maxsilence) { /* Ended happily with silence */ if (option_verbose > 2) cw_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000); cw_fr_free(f); gotsilence = 1; outmsg=2; break; } } /* Exit on any error */ if (res) { cw_log(LOG_WARNING, "Error writing frame\n"); cw_fr_free(f); break; } } else if (f->frametype == CW_FRAME_VIDEO) { /* Write only once */ cw_writestream(others[0], f); } else if (f->frametype == CW_FRAME_DTMF) { /* stop recording with any digit */ if (option_verbose > 2) cw_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass); res = 't'; outmsg = 2; cw_fr_free(f); break; } if (maxtime) { time(&end); if (maxtime < (end - start)) { if (option_verbose > 2) cw_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n"); res = 't'; outmsg=2; cw_fr_free(f); break; } } cw_fr_free(f); } if (end == start) time(&end); if (!f) { if (option_verbose > 2) cw_verbose( VERBOSE_PREFIX_3 "User hung up\n"); res = -1; outmsg=1; #if 0 /* delete all the prepend files */ for (x=0;x<fmtcnt;x++) { if (!others[x]) break; cw_closestream(others[x]); cw_filedelete(prependfile, sfmt[x]); } #endif } } else { cw_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", prependfile, sfmt[x]); } *duration = end - start; #if 0 if (outmsg > 1) { #else if (outmsg) { #endif struct cw_frame *fr; for (x=0;x<fmtcnt;x++) { snprintf(comment, sizeof(comment), "Opening the real file %s.%s\n", recordfile, sfmt[x]); realfiles[x] = cw_readfile(recordfile, sfmt[x], comment, O_RDONLY, 0, 0); if (!others[x] || !realfiles[x]) break; if (totalsilence) cw_stream_rewind(others[x], totalsilence-200); else cw_stream_rewind(others[x], 200); cw_truncstream(others[x]); /* add the original file too */ while ((fr = cw_readframe(realfiles[x]))) { cw_writestream(others[x],fr); } cw_closestream(others[x]); cw_closestream(realfiles[x]); cw_filerename(prependfile, recordfile, sfmt[x]); #if 0 cw_verbose("Recording Format: sfmts=%s, prependfile %s, recordfile %s\n", sfmt[x],prependfile,recordfile); #endif cw_filedelete(prependfile, sfmt[x]); } } if (rfmt) { if (cw_set_read_format(chan, rfmt)) { cw_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", cw_getformatname(rfmt), chan->name); } } if (outmsg) { if (outmsg > 1) { /* Let them know it worked */ cw_streamfile(chan, "auth-thankyou", chan->language); cw_waitstream(chan, ""); } } return res; } /* Channel group core functions */ int cw_app_group_split_group(char *data, char *group, int group_max, char *category, int category_max) { int res=0; char tmp[256]; char *grp=NULL, *cat=NULL; if (!cw_strlen_zero(data)) { cw_copy_string(tmp, data, sizeof(tmp)); grp = tmp; cat = strchr(tmp, '@'); if (cat) { *cat = '\0'; cat++; } } if (!cw_strlen_zero(grp)) cw_copy_string(group, grp, group_max); else res = -1; if (cat) snprintf(category, category_max, "%s_%s", GROUP_CATEGORY_PREFIX, cat); else cw_copy_string(category, GROUP_CATEGORY_PREFIX, category_max); return res; }
int ldap_lookup(char *host, int port, int version, int timeout, char *user, char *pass, char *base, char *scope, char *filter, char *attribute, char *result) { char *attrs[] = { NULL }; char **values; LDAP *ld; LDAPMessage *res, *entry; int ret, ldap_scope = LDAP_SCOPE_SUBTREE; ld = ldap_init(host, port); if (!ld) { cw_log(LOG_WARNING, "LDAPget: unable to initialize ldap connection to %s:%d\n", host, port); return 0; } ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &timeout); ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version); if (user) { if (option_verbose > 2) cw_verbose(VERBOSE_PREFIX_3 "LDAPget: bind to %s as %s\n", host, user); ret = ldap_simple_bind_s(ld, user, pass); } else { if (option_verbose > 2) cw_verbose(VERBOSE_PREFIX_3 "LDAPget: bind to %s anonymously\n", host); ret = ldap_simple_bind_s(ld, NULL, NULL); } if (ret) { cw_log(LOG_WARNING, "LDAPget: bind failed: %s\n", ldap_err2string(ret)); ldap_unbind(ld); return 0; } if (strncmp(scope,"sub",3)==0) { ldap_scope = LDAP_SCOPE_SUBTREE; } else if (strncmp(scope,"base",4)==0) { ldap_scope = LDAP_SCOPE_BASE; } else if (strncmp(scope,"one",3)==0) { ldap_scope = LDAP_SCOPE_ONELEVEL; } ret = ldap_search_s(ld, base, ldap_scope, filter, attrs, 0, &res); if (ret) { cw_log(LOG_DEBUG, "LDAPget: search failed: %s\n", ldap_err2string(ret)); ldap_msgfree(res); ldap_unbind(ld); return 0; } entry = ldap_first_entry(ld, res); if (!entry) { if (option_verbose > 2) cw_verbose (VERBOSE_PREFIX_3 "LDAPget: Value not found in directory.\n"); ldap_msgfree(res); ldap_unbind(ld); return 0; } values = ldap_get_values(ld, entry, attribute); if (values && values[0]) { memset(result, 0, strlen(values[0])); strncpy(result, values[0], strlen(values[0])); result[strlen(values[0])] = '\0'; if (option_verbose > 2) cw_verbose(VERBOSE_PREFIX_3 "LDAPget: %s=%s\n", attribute, result); } else { if (option_verbose > 2) cw_verbose (VERBOSE_PREFIX_3 "LDAPget: %s not found.\n", attribute); ldap_msgfree(res); ldap_unbind(ld); return 0; } ldap_value_free(values); ldap_msgfree(res); ldap_unbind_s(ld); return 1; }
static int ldap_exec(struct cw_channel *chan, int argc, char **argv) { char result[2048]; struct localuser *u; char *varname, *config, *keys = NULL, *key = NULL, *tail = NULL; char *result_conv; struct cw_config *cfg; int port = LDAP_PORT, version = LDAP_VERSION2, timeout = 10; char *temp, *host, *user, *pass, *base, *scope, *filter, *_filter, *attribute, *convert_from = NULL, *convert_to = NULL; if (argc != 1) { cw_log(LOG_ERROR, "Syntax: %s\n", g_syntax); pbx_builtin_setvar_helper(chan, "LDAPSTATUS", "FAILURE"); return 0; } LOCAL_USER_ADD(u); if (strchr(argv[0], '=')) { varname = strsep (&argv[0], "="); if (strchr(argv[0], '/')) { config = strsep(&argv[0], "/"); keys = strsep(&argv[0], "\0"); if (option_verbose > 2) cw_verbose(VERBOSE_PREFIX_3 "LDAPget: varname=%s, config-section=%s, keys=%s\n", varname, config, keys); } else { config = strsep(&argv[0], "\0"); if (option_verbose > 2) cw_verbose(VERBOSE_PREFIX_3 "LDAPget: varname=%s, config-section=%s\n", varname, config); } if (!varname || !config) { cw_log(LOG_WARNING, "Ignoring; Syntax error in argument\n"); pbx_builtin_setvar_helper(chan, "LDAPSTATUS", "FAILURE"); return 0; } } else { cw_log(LOG_WARNING, "Ignoring, no parameters\n"); pbx_builtin_setvar_helper(chan, "LDAPSTATUS", "FAILURE"); return 0; } cfg = cw_config_load(LDAP_CONFIG); if (!cfg) { cw_log(LOG_WARNING, "No such configuration file %s\n", LDAP_CONFIG); return -1; } if (!(host = cw_variable_retrieve(cfg, config, "host"))) { host = "localhost"; } if ((temp = cw_variable_retrieve(cfg, config, "port"))) { port = atoi(temp); } if ((temp = cw_variable_retrieve(cfg, config, "timeout"))) { timeout = atoi(temp); } if ((temp = cw_variable_retrieve(cfg, config, "version"))) { version = atoi(temp); } user = cw_variable_retrieve(cfg, config, "user"); pass = cw_variable_retrieve(cfg, config, "pass"); base = cw_variable_retrieve(cfg, config, "base"); if (!base) base = ""; base = replace_cw_vars(chan, base); if (!(scope = cw_variable_retrieve(cfg, config, "scope"))) { scope = "sub"; } if (!(_filter = cw_variable_retrieve(cfg, config, "filter"))) { _filter = "(&(objectClass=person)(telephoneNumber=${CALLERIDNUM}))"; } if (!(attribute = cw_variable_retrieve(cfg, config, "attribute"))) { attribute = "cn"; } if ((temp = cw_variable_retrieve(cfg, config, "convert"))) { if (strchr(temp, ',')) { convert_from = strtrim(strsep(&temp, ",")); convert_to = strtrim(strsep(&temp, "\0")); } else { cw_log(LOG_WARNING, "syntax error: convert = <source-charset>,<destination charset>\n"); } } if (option_verbose > 3) cw_verbose (VERBOSE_PREFIX_4 "LDAPget: ldap://%s/%s?%s?%s?%s\n", host, base, attribute, scope, _filter); filter = replace_cw_vars(chan, _filter); if (option_verbose > 3) cw_verbose (VERBOSE_PREFIX_4 "LDAPget: %s\n", filter); if (keys && strstr(filter, "%s") != NULL) { filter = (char *)realloc(filter, (strlen(filter)+strlen(keys)+1)*sizeof(char)); while((key = strsep(&keys, "|")) != NULL) { if ((tail = strstr(filter, "%s")) != NULL) { memmove(tail+strlen(key), tail+2, strlen(tail+2)+1); memcpy(tail, key, strlen(key)); } } } if (option_verbose > 2) cw_verbose (VERBOSE_PREFIX_3 "LDAPget: ldap://%s/%s?%s?%s?%s\n", host, base, attribute, scope, filter); if (ldap_lookup(host, port, version, timeout, user, pass, base, scope, filter, attribute, result)) { if (convert_from) { if (option_verbose > 2) cw_verbose(VERBOSE_PREFIX_3 "LDAPget: convert: %s -> %s\n", convert_from, convert_to); result_conv = malloc(strlen(result) * 2); strconvert(convert_from, convert_to, result, result_conv); strcpy(result, result_conv); free(result_conv); } if (strcmp("CALLERIDNAME", varname)==0) { cw_set_callerid(chan, NULL, result, NULL); if (option_verbose > 2) cw_verbose (VERBOSE_PREFIX_3 "LDAPget: set CIDNAME to \"%s\"\n", result); } else { if (option_verbose > 2) cw_verbose (VERBOSE_PREFIX_3 "LDAPget: set %s='%s'\n", varname, result); pbx_builtin_setvar_helper(chan, varname, result); } } else { pbx_builtin_setvar_helper(chan, "LDAPSTATUS", "FAILURE"); return 0; } cw_config_destroy(cfg); free(filter); free(base); pbx_builtin_setvar_helper(chan, "LDAPSTATUS", "SUCCESS"); LOCAL_USER_REMOVE(u); return 0; }
static int privacy_exec (struct cw_channel *chan, int argc, char **argv) { char phone[30]; struct localuser *u; struct cw_config *cfg; char *s; int res=0; int retries; int maxretries = 3; int minlength = 10; int x; LOCAL_USER_ADD (u); if (!cw_strlen_zero(chan->cid.cid_num)) { if (option_verbose > 2) cw_verbose (VERBOSE_PREFIX_3 "CallerID Present: Skipping\n"); pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "SUCCESS"); } else { /*Answer the channel if it is not already*/ if (chan->_state != CW_STATE_UP) { res = cw_answer(chan); if (res) { pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "FAIL"); LOCAL_USER_REMOVE(u); return 0; } } /*Read in the config file*/ cfg = cw_config_load(PRIV_CONFIG); /*Play unidentified call*/ res = cw_safe_sleep(chan, 1000); if (!res) res = cw_streamfile(chan, "privacy-unident", chan->language); if (!res) res = cw_waitstream(chan, ""); if (cfg && (s = cw_variable_retrieve(cfg, "general", "maxretries"))) { if (sscanf(s, "%d", &x) == 1) { maxretries = x; } else { cw_log(LOG_WARNING, "Invalid max retries argument\n"); } } if (cfg && (s = cw_variable_retrieve(cfg, "general", "minlength"))) { if (sscanf(s, "%d", &x) == 1) { minlength = x; } else { cw_log(LOG_WARNING, "Invalid min length argument\n"); } } /*Ask for 10 digit number, give 3 attempts*/ for (retries = 0; retries < maxretries; retries++) { if (!res ) res = cw_app_getdata(chan, "privacy-prompt", phone, sizeof(phone), 0); if (res < 0) break; /*Make sure we get at least our minimum of digits*/ if (strlen(phone) >= minlength ) break; else { res = cw_streamfile(chan, "privacy-incorrect", chan->language); if (!res) res = cw_waitstream(chan, ""); } } /*Got a number, play sounds and send them on their way*/ if ((retries < maxretries) && res == 1 ) { res = cw_streamfile(chan, "privacy-thankyou", chan->language); if (!res) res = cw_waitstream(chan, ""); cw_set_callerid (chan, phone, "Privacy Manager", NULL); if (option_verbose > 2) cw_verbose (VERBOSE_PREFIX_3 "Changed Caller*ID to %s\n",phone); pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "SUCCESS"); } else { /* Flag Failure */ pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "FAIL"); } if (cfg) cw_config_destroy(cfg); } LOCAL_USER_REMOVE (u); return 0; }
static struct cw_key *try_load_key (char *dir, char *fname, int ifd, int ofd, int *not2) { int ktype = 0; char *c = NULL; char ffname[256]; FILE *f; EVP_MD_CTX mdctx; unsigned char md_value[CW_MAX_BINARY_MD_SIZE]; unsigned int md_len; struct cw_key *key; static int notice = 0; int found = 0; /* Make sure its name is a public or private key */ if ((c = strstr(fname, ".pub")) && !strcmp(c, ".pub")) { ktype = CW_KEY_PUBLIC; } else if ((c = strstr(fname, ".key")) && !strcmp(c, ".key")) { ktype = CW_KEY_PRIVATE; } else return NULL; /* Get actual filename */ snprintf(ffname, sizeof(ffname), "%s/%s", dir, fname); cw_mutex_lock(&keylock); key = keys; while(key) { /* Look for an existing version already */ if (!strcasecmp(key->fn, ffname)) break; key = key->next; } cw_mutex_unlock(&keylock); /* Open file */ f = fopen(ffname, "r"); if (!f) { cw_log(LOG_WARNING, "Unable to open key file %s: %s\n", ffname, strerror(errno)); return NULL; } EVP_DigestInit(&mdctx, EVP_md5()); while(!feof(f)) { /* Calculate a "whatever" quality md5sum of the key */ char buf[256]; memset(buf, 0, 256); fgets(buf, sizeof(buf), f); if (!feof(f)) { EVP_DigestUpdate(&mdctx, (unsigned char *) buf, strlen(buf)); } } EVP_DigestFinal(&mdctx, md_value, &md_len); if (key) { /* If the MD5 sum is the same, and it isn't awaiting a passcode then this is far enough */ if (!memcmp(md_value, key->md_value, md_len) && !(key->ktype & KEY_NEEDS_PASSCODE)) { fclose(f); key->delme = 0; return NULL; } else { /* Preserve keytype */ ktype = key->ktype; /* Recycle the same structure */ found++; } } /* Make fname just be the normal name now */ *c = '\0'; if (!key) { key = (struct cw_key *)malloc(sizeof(struct cw_key)); if (!key) { cw_log(LOG_WARNING, "Out of memory\n"); fclose(f); return NULL; } memset(key, 0, sizeof(struct cw_key)); } /* At this point we have a key structure (old or new). Time to fill it with what we know */ /* Gotta lock if this one already exists */ if (found) cw_mutex_lock(&keylock); /* First the filename */ cw_copy_string(key->fn, ffname, sizeof(key->fn)); /* Then the name */ cw_copy_string(key->name, fname, sizeof(key->name)); key->ktype = ktype; /* Yes, assume we're going to be deleted */ key->delme = 1; /* Keep the key type */ memcpy(key->md_value, md_value, md_len); key->md_len = md_len; /* Can I/O takes the FD we're given */ key->infd = ifd; key->outfd = ofd; /* Reset the file back to the beginning */ rewind(f); /* Now load the key with the right method */ if (ktype == CW_KEY_PUBLIC) key->rsa = PEM_read_RSA_PUBKEY(f, NULL, pw_cb, key); else key->rsa = PEM_read_RSAPrivateKey(f, NULL, pw_cb, key); fclose(f); if (key->rsa) { if (RSA_size(key->rsa) == 128) { /* Key loaded okay */ key->ktype &= ~KEY_NEEDS_PASSCODE; if (option_verbose > 2) cw_verbose(VERBOSE_PREFIX_3 "Loaded %s key '%s'\n", key->ktype == CW_KEY_PUBLIC ? "PUBLIC" : "PRIVATE", key->name); if (option_debug) cw_log(LOG_DEBUG, "Key '%s' loaded OK\n", key->name); key->delme = 0; } else cw_log(LOG_NOTICE, "Key '%s' is not expected size.\n", key->name); } else if (key->infd != -2) { cw_log(LOG_WARNING, "Key load %s '%s' failed\n",key->ktype == CW_KEY_PUBLIC ? "PUBLIC" : "PRIVATE", key->name); if (ofd > -1) { ERR_print_errors_fp(stderr); } else ERR_print_errors_fp(stderr); } else { cw_log(LOG_NOTICE, "Key '%s' needs passcode.\n", key->name); key->ktype |= KEY_NEEDS_PASSCODE; if (!notice) { if (!option_initcrypto) cw_log(LOG_NOTICE, "Add the '-i' flag to the callweaver command line if you want to automatically initialize passcodes at launch.\n"); notice++; } /* Keep it anyway */ key->delme = 0; /* Print final notice about "init keys" when done */ *not2 = 1; } if (found) cw_mutex_unlock(&keylock); if (!found) { cw_mutex_lock(&keylock); key->next = keys; keys = key; cw_mutex_unlock(&keylock); } return key; }