static struct ast_channel *app_dial(const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name) { int state = 0; int cause = 0; int to; struct ast_channel *chan; struct ast_frame *f = NULL; int res = 0, ready = 0; chan = ast_request(type, format, data, &cause); if (!chan) { switch (cause) { case AST_CAUSE_BUSY: state = AST_CONTROL_BUSY; break; case AST_CAUSE_CONGESTION: state = AST_CONTROL_CONGESTION; break; } if (outstate) *outstate = state; ast_verbose("Unable to call channel %s/%s reason: %s\n", (char *) type, (char *) data, ast_cause2str(cause)); return NULL; } if (ast_call(chan, data, timeout)) { ast_verbose("Unable to request channel %s/%s\n", type, (char *) data); switch (cause) { case AST_CAUSE_BUSY: state = AST_CONTROL_BUSY; break; case AST_CAUSE_CONGESTION: state = AST_CONTROL_CONGESTION; break; } if (outstate) *outstate = state; return NULL; } struct timeval started; started = ast_tvnow(); to = timeout; ast_set_callerid(chan, cid_num, cid_name, cid_num); while (timeout && (chan->_state != AST_STATE_UP)) { #if 1 /* see if the timeout has been violated */ int timeout_violation = ast_tvdiff_ms(ast_tvnow(), started); if ( timeout_violation > ( timeout * 1000 )) { state = AST_CONTROL_UNHOLD; ast_log(LOG_NOTICE, "We exceeded our AT-timeout\n"); break; /*doh! timeout */ } #endif if (chan) { f = ast_read(chan); if (f == NULL) { state = AST_CONTROL_HANGUP; res = 0; break; } if (f->frametype == AST_FRAME_CONTROL || f->frametype == AST_FRAME_DTMF || f->frametype == AST_FRAME_TEXT) { if (f->subclass == AST_CONTROL_RINGING) { state = f->subclass; ast_verbose("%s is ringing\n", chan->name); } if (((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION))) { state = f->subclass; ast_frfree(f); f = NULL; break; } else if (f->subclass == AST_CONTROL_ANSWER) { /* This is what we are hoping for */ state = f->subclass; ast_frfree(f); f = NULL; ready = 1; break; } else { ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass); } /* else who cares */ } if (f) { ast_frfree(f); } } } if (chan && ready) { if (chan->_state == AST_STATE_UP) state = AST_CONTROL_ANSWER; res = 0; } else if (chan) { res = -1; ast_hangup(chan); chan = NULL; } else { res = -1; } *outstate = state; return chan; }