/*! \brief Helper function that creates an outgoing channel and returns it immediately */ static struct ast_channel *dial_transfer(const struct ast_channel *caller, const char *exten, const char *context) { char destination[AST_MAX_EXTENSION+AST_MAX_CONTEXT+1] = ""; struct ast_channel *chan = NULL; int cause; /* Fill the variable with the extension and context we want to call */ snprintf(destination, sizeof(destination), "%s@%s", exten, context); /* Now we request that chan_local prepare to call the destination */ if (!(chan = ast_request("Local", caller->nativeformats, caller, destination, &cause))) { return NULL; } /* Before we actually dial out let's inherit the appropriate dialplan variables */ ast_channel_inherit_variables(caller, chan); /* Since the above worked fine now we actually call it and return the channel */ if (ast_call(chan, destination, 0)) { ast_hangup(chan); return NULL; } return chan; }
/*! * \internal * \brief Helper function that creates an outgoing channel and returns it immediately. This function is nearly * identical to the dial_transfer function in bridge_basic.c, however it doesn't swap the * local channel and the channel that instigated the park. */ static struct ast_channel *park_local_transfer(struct ast_channel *parker, const char *context, const char *exten, struct transfer_channel_data *parked_channel_data) { char destination[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 1]; struct ast_channel *parkee; struct ast_channel *parkee_side_2; int cause; /* Fill the variable with the extension and context we want to call */ snprintf(destination, sizeof(destination), "%s@%s", exten, context); /* Now we request that chan_local prepare to call the destination */ parkee = ast_request("Local", ast_channel_nativeformats(parker), NULL, parker, destination, &cause); if (!parkee) { return NULL; } /* Before we actually dial out let's inherit appropriate information. */ ast_channel_lock_both(parker, parkee); ast_channel_req_accountcodes(parkee, parker, AST_CHANNEL_REQUESTOR_REPLACEMENT); ast_connected_line_copy_from_caller(ast_channel_connected(parkee), ast_channel_caller(parker)); ast_channel_inherit_variables(parker, parkee); ast_channel_datastore_inherit(parker, parkee); ast_channel_unlock(parker); parkee_side_2 = ast_local_get_peer(parkee); ast_assert(parkee_side_2 != NULL); ast_channel_unlock(parkee); /* We need to have the parker subscribe to the new local channel before hand. */ if (create_parked_subscription_full(parker, ast_channel_uniqueid(parkee_side_2), 1, parked_channel_data)) { ast_channel_unref(parkee_side_2); ast_hangup(parkee); return NULL; } ast_bridge_set_transfer_variables(parkee_side_2, ast_channel_name(parker), 0); ast_channel_unref(parkee_side_2); /* Since the above worked fine now we actually call it and return the channel */ if (ast_call(parkee, destination, 0)) { ast_hangup(parkee); return NULL; } return parkee; }
static struct ast_channel *prepare_bridge_media_channel(const char *type) { RAII_VAR(struct ast_format_cap *, cap, NULL, ao2_cleanup); struct ast_channel *chan; cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); if (!cap) { return NULL; } ast_format_cap_append(cap, ast_format_slin, 0); chan = ast_request(type, cap, NULL, NULL, "ARI", NULL); if (!chan) { return NULL; } if (stasis_app_channel_unreal_set_internal(chan)) { ast_channel_cleanup(chan); return NULL; } return chan; }
static int chanavail_exec(struct ast_channel *chan, void *data) { int res=-1, inuse=-1, option_state=0, priority_jump=0; int status; struct localuser *u; char *info, tmp[512], trychan[512], *peers, *tech, *number, *rest, *cur, *options, *stringp; struct ast_channel *tempchan; if (ast_strlen_zero(data)) { ast_log(LOG_WARNING, "ChanIsAvail requires an argument (Zap/1&Zap/2)\n"); return -1; } LOCAL_USER_ADD(u); info = ast_strdupa(data); stringp = info; strsep(&stringp, "|"); options = strsep(&stringp, "|"); if (options) { if (strchr(options, 's')) option_state = 1; if (strchr(options, 'j')) priority_jump = 1; } peers = info; if (peers) { cur = peers; do { /* remember where to start next time */ rest = strchr(cur, '&'); if (rest) { *rest = 0; rest++; } tech = cur; number = strchr(tech, '/'); if (!number) { ast_log(LOG_WARNING, "ChanIsAvail argument takes format ([technology]/[device])\n"); LOCAL_USER_REMOVE(u); return -1; } *number = '\0'; number++; if (option_state) { /* If the pbx says in use then don't bother trying further. This is to permit testing if someone's on a call, even if the channel can permit more calls (ie callwaiting, sip calls, etc). */ snprintf(trychan, sizeof(trychan), "%s/%s",cur,number); status = inuse = ast_device_state(trychan); } if ((inuse <= 1) && (tempchan = ast_request(tech, chan->nativeformats, number, &status))) { pbx_builtin_setvar_helper(chan, "AVAILCHAN", tempchan->name); /* Store the originally used channel too */ snprintf(tmp, sizeof(tmp), "%s/%s", tech, number); pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", tmp); snprintf(tmp, sizeof(tmp), "%d", status); pbx_builtin_setvar_helper(chan, "AVAILSTATUS", tmp); ast_hangup(tempchan); tempchan = NULL; res = 1; break; } else { snprintf(tmp, sizeof(tmp), "%d", status); pbx_builtin_setvar_helper(chan, "AVAILSTATUS", tmp); } cur = rest; } while (cur); } if (res < 1) { pbx_builtin_setvar_helper(chan, "AVAILCHAN", ""); pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", ""); if (priority_jump || option_priority_jumping) { if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101)) { LOCAL_USER_REMOVE(u); return -1; } } } LOCAL_USER_REMOVE(u); return 0; }
static struct ast_conference *build_conf(char *confno, char *pin, int make, int dynamic) { struct ast_conference *cnf; struct zt_confinfo ztc; ast_mutex_lock(&conflock); cnf = confs; while(cnf) { if (!strcmp(confno, cnf->confno)) break; cnf = cnf->next; } if (!cnf && (make || dynamic)) { cnf = malloc(sizeof(struct ast_conference)); if (cnf) { /* Make a new one */ memset(cnf, 0, sizeof(struct ast_conference)); strncpy(cnf->confno, confno, sizeof(cnf->confno) - 1); strncpy(cnf->pin, pin, sizeof(cnf->pin) - 1); cnf->markedusers = 0; cnf->chan = ast_request("zap", AST_FORMAT_ULAW, "pseudo"); if (cnf->chan) { cnf->fd = cnf->chan->fds[0]; /* for use by conf_play() */ } else { ast_log(LOG_WARNING, "Unable to open pseudo channel - trying device\n"); cnf->fd = open("/dev/zap/pseudo", O_RDWR); if (cnf->fd < 0) { ast_log(LOG_WARNING, "Unable to open pseudo device\n"); free(cnf); cnf = NULL; goto cnfout; } } memset(&ztc, 0, sizeof(ztc)); /* Setup a new zap conference */ ztc.chan = 0; ztc.confno = -1; ztc.confmode = ZT_CONF_CONFANN; if (ioctl(cnf->fd, ZT_SETCONF, &ztc)) { ast_log(LOG_WARNING, "Error setting conference\n"); if (cnf->chan) ast_hangup(cnf->chan); else close(cnf->fd); free(cnf); cnf = NULL; goto cnfout; } /* Fill the conference struct */ cnf->start = time(NULL); cnf->zapconf = ztc.confno; cnf->isdynamic = dynamic; cnf->firstuser = NULL; cnf->lastuser = NULL; cnf->locked = 0; if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "Created MeetMe conference %d for conference '%s'\n", cnf->zapconf, cnf->confno); cnf->next = confs; confs = cnf; } else ast_log(LOG_WARNING, "Out of memory\n"); } cnfout: ast_mutex_unlock(&conflock); return cnf; }
static void *dialstring(void *string) { struct ast_channel *channel; char *bufptr,*destptr; int ms=10000; /* ms affects number of rings */ int cnt=0,first; char tech[256]; char tele[256]; char filename[256]; int answered=0; for(first=0, bufptr=(char *)string, destptr=tech; *bufptr&&cnt<256; cnt++){ if(*bufptr=='/' && !first) { *destptr=0; destptr=tele; first=1; } else if(*bufptr==',') { *destptr=0; destptr=filename; } else { *destptr=*bufptr; destptr++; } bufptr++; } *destptr=0; ast_log(LOG_DEBUG, "Printing string arg: %s Eos\n", (char *)string); if(strlen(tech)+strlen(tele)+strlen(filename) > 256) { ast_log(LOG_ERROR, "Autodial:Error string too long\n"); free(string); pthread_exit(NULL); } ast_log(LOG_DEBUG, "Autodial Tech %s(%d) Tele %s(%d) Filename %s(%d)\n",tech, (int)strlen(tech), tele, (int)strlen(tele), filename, (int)strlen(filename)); channel=ast_request(tech,AST_FORMAT_SLINEAR,tele); if(channel!=NULL){ ast_call(channel,tele,10000); } else { ast_log(LOG_ERROR, "Autodial:Sorry unable to obtain channel\n"); free(string); pthread_exit(NULL); } if(channel->_state==AST_STATE_UP) ast_log(LOG_DEBUG, "Autodial:Line is Up\n"); while(ms>0){ struct ast_frame *f; ms=ast_waitfor(channel,ms); f=ast_read(channel); if(!f){ ast_log(LOG_DEBUG, "Autodial:Hung Up\n"); break; } if (f->frametype==AST_FRAME_CONTROL) { if (f->subclass==AST_CONTROL_ANSWER) { ast_log(LOG_DEBUG, "Autodial:Phone Answered\n"); if (channel->_state==AST_STATE_UP) { char res; ast_streamfile(channel,filename,0); /* Press Five for snooze */ res=ast_waitstream(channel, "37"); if(res=='3'){ answered=1; set_snooze_alarm((char *)string,60); ast_streamfile(channel,"demo-thanks",0); ast_waitstream(channel, ""); } else if(res=='7'){ answered=1; ast_streamfile(channel,"demo-thanks",0); ast_waitstream(channel, ""); } ast_stopstream(channel); ms=0; } } else if (f->subclass==AST_CONTROL_RINGING) ast_log(LOG_DEBUG, "Autodial:Phone Ringing end\n"); } ast_frfree(f); } if(!answered) set_snooze_alarm((char *) string, 5); free(string); ast_hangup(channel); ast_log(LOG_DEBUG, "Autodial:Hung up channel\n"); pthread_exit(NULL); return NULL; }