· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
Asterisk Ver0-1-0/App Dial

AsteriskVer0-1-0/AppDial


Attempts to "dial out" on all the specified channels (each specified by a type and identifier) simultaneously. The first channel that answers "wins", and all the other outgoing channels are hung up.

* int load_module(void)
  • return ast_register_application(app, dial_exec);

struct localuser {
        struct ast_channel *chan;
        int stillgoing;
        int allowredirect;
        struct localuser *next;
};

\ digit digit digit
    An octal character code. The numeric code is 3 octal digits. For compatibility with other Unix systems, 8 and 9 are accepted as digits: for example, \008 has the value 010, and \009 the value 011. 

* static int dial_exec(struct ast_channel *chan, void *data)
  • struct localuser *outgoing=NULL, *tmp;
  • peers = strtok(info, "|");
  • timeout = strtok(NULL, "|");
  • rest = peers;
    • technology1/number1&technology2/number2...
  • do {
    • cur = strtok(rest, "&");
    • rest = strtok(NULL, "\128");
      • 앞부분의 technology 와 number 을 cur 에 넣고, 나머지 부분을 rest 에 보관하고자 하는 프로그램이나 문제 있음.
    • tech 와 number 에 technology 와 number 을 assign
    • tmp = malloc(sizeof(struct localuser));
    • tmp->allowredirect = 1;
    • number 이 BYEXTENSION 이면 number = chan->exten; tmp->allowredirect = 0;
      • 없어진 option 인듯함.
    • tmp->chan = ast_request(tech, chan->format, number);
      • channel 을 생성하지 못하면, free(tmp); continue;
    • res = ast_call(tmp->chan, number, 0);
      • call 이 안되면, ast_hangup(tmp->chan); free(tmp); continue;
    • tmp->stillgoing = -1;
    • tmp->next = outgoing;
    • outgoing = tmp; request 와 call 이 성공한 localuser list 를 만듬.
  • } while(rest);
  • if (timeout) to = atoi(timeout) * 1000;
  • else to = -1;
  • peer = wait_for_answer(chan, outgoing, &to, &allowredir);
    • outgoing 이 null 인 경우 이전에 조치를 취하는 것이 좋을 듯함.
  • if (peer) {
    • hanguptree(outgoing, peer); peer 을 재외한 나머지 channel 을 hangup 시킴.
    • outgoing = NULL;
    • res = bridge_call(chan, peer, allowredir);
    • ast_hangup(peer);
  • }
  • out:
  • hanguptree(outgoing, NULL);
  • return res;

struct chanlist {
        char type[80];
        char description[80];
        int capabilities;
        struct ast_channel * (*requester)(char *type, int format, void *data);
        struct chanlist *next;
} *backends = NULL;
* struct ast_channel *ast_request(char *type, int format, void *data)
  • chan = backends;
  • type 의 channel 을 찾아, chan->requester 가 있으면 이를 수행시킨다.
    • c = chan->requester(type, format, data);
  • return c;

* int ast_call(struct ast_channel *chan, char *addr, int timeout)
  • chan->pvt_call 이 있으면 이를 수행시킨다.
    • res = chan->pvt->call(chan, addr, timeout);
  • return res;

* int ast_hangup(struct ast_channel *chan)
  • if (chan->stream) ast_stopstream(chan);
  • if (chan->sched) sched_context_destroy(chan->sched);
  • if (chan->blocking) Hard hangup called, while fd is blocking
  • if (chan->pvt->hangup)
    • res = chan->pvt->hangup(chan);
  • if (chan->pvt->pvt) Channel '%s' may not have been hung up properly
  • if (chan->trans) Hard hangup called on '%s' while a translator is in place!
  • if (chan->pbx) PBX may not have been terminated properly
  • if (chan->dnid) free(chan->dnid);
  • if (chan->callerid) free(chan->callerid);
  • free(chan->pvt);
  • free(chan);
  • return res;

* static struct ast_channel *ixj_request(char *type, int format, void *data)

* static int ixj_call(struct ast_channel *ast, char *dest, int timeout)
  • p = ast->pvt->pvt;
  • channel state 가 AST_STATE_DOWN 도 아니고 AST_STATE_RESERVED 도 아니면
    • return -1;
  • ioctl(p->fd, IXJCTL_RING_START);
  • ast->state = AST_STATE_RINGING;
  • return 0;

* static int ixj_hangup(struct ast_channel *ast)
  • p = ast->pvt->pvt;
  • ast->state = AST_STATE_DOWN;
  • ioctl(p->fd, IXJCTL_REC_STOP) stop recording
  • ioctl(p->fd, IXJCTL_PLAY_STOP) stop playing
  • ioctl(p->fd, IXJCTL_RING_STOP) stop ringing
  • ioctl(p->fd, IXJCTL_CPT_STOP) stop sounds
  • if (ioctl(p->fd, IXJCTL_HOOKSTATE))
    • ioctl(p->fd, IXJCTL_BUSY);
  • p->lastformat = -1; p->lastinput = -1; p->ministate = 0; p->obuflen = 0; p->dialtone = 0;
  • ast->pvt->pvt = NULL;
  • ast->state = AST_STATE_DOWN;
  • restart_monitor();
  • return 0;

* static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir)
  • to 가 -1 인 경우 매끄럽지 못함.
  • tv.tv_sec = *to / 1000; tv.tv_usec = (*to % 1000) * 1000;
  • while((tv.tv_sec || tv.tv_usec) && !peer) {
    • FD_SET(in->fd, &rfds); FD_SET(in->fd, &efds);
    • o = outgoing;
    • found = -1; numlines = 0;
    • while(o) {
      • if (o->stillgoing) {
        • CHECK_BLOCKING(o->chan);
        • FD_SET(o->chan->fd, &rfds); FD_SET(o->chan->fd, &efds);
        • if (o->chan->fd > found) found = o->chan->fd;
      • }
      • numlines++;
      • o = o->next;
    • }
      • input channel 과 request, call 이 성공적인 channel 들을 FD_SET 함.
    • if (found<0) {
    • }
    • if (in->fd > found) found = in->fd;
    • if (*to > -1)
      • found = select(found + 1, &rfds, NULL, &efds, &tv);
    • else
      • found = select(found + 1, &rfds, NULL, &efds, NULL);
    • if (found < 0) {
    • }
    • o = outgoing;
    • while(o) {
      • if (o->stillgoing) {
        • o->chan->blocking = 0;
        • if (FD_ISSET(o->chan->fd, &rfds) || FD_ISSET(o->chan->fd, &efds)) {
        • 입력된 데이타가 있으면
          • f = ast_read(o->chan); ixj_read
          • if (f) {
            • AST_CONTROL_ANSWER: ringing 인 상태에서 offhook 이면
              • peer = o->chan;
            • AST_CONTROL_BUSY
              • o->stillgoing = 0;
              • numbusies++;
            • AST_CONTROL_RINGING
            • AST_CONTROL_OFFHOOK
            • ast_frfree(f);
          • } else {
            • o->stillgoing = 0;
          • }
        • }
      • }
      • o = o->next;
    • }
    • if (FD_ISSET(in->fd, &rfds) || FD_ISSET(in->fd, &efds)) {
      • f = ast_read(in);
      • 입력된 데이타가 없거나, hangup 이면
        • *to=-1; return NULL;
    • }
  • }
  • if (!(tv.tv_sec || tv.tv_usec) && (option_verbose > 2))
    • Nobody picked up in %d ms\n
  • *to = 0;
  • return peer;

FD_ZERO(fd_set *fdset) : *fdset의 모든 비트를 지운다.
FD_SET(int fd, fd_set *fdset) : *fdset 중 소켓 fd에 해당하는 비트를 1로 한다.
FD_CLR(int fd, fd_set *fdset) : *fdset 중 소켓 fd에 해당하는 비트를 0으로 한다.
FD_ISSET(int fd, fd_set *fdset) : *fdset 중 소켓 fd에 해당하는 비트가 세트되어 있으면 양수값인 fd를 리턴한다.

select() 는 FD_SET으로 설정된 fd만을 확인합니다. 그리고 확인 결과 read또는 write 준비가 된 fd를 fdset 내에서 '세트'시킵니다. 따라서 select() 함수 직후에 FD_ISSET으로 특정 fd가 'SET'되었는지 확인할 수 있습니다. 

* static int bridge_call(struct ast_channel *chan, struct ast_channel *peer, int allowredirect)
  • struct ast_channel *cs3;
  • if (chan->state != AST_STATE_UP)
    • if (ast_answer(chan))
      • return -1;
  • cs0 = chan;
  • cs1 = peer;
  • for (/* ever */;;) {
    • who = ast_waitfor_n(cs, 2, &to);
    • f = ast_read(who);
    • if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)))
      • return -1;
    • if ((f->frametype == AST_FRAME_VOICE) ||
      (f->frametype == AST_FRAME_DTMF)) {
      • if ((f->frametype == AST_FRAME_DTMF) && (who == peer) && allowredirect) {
      • } else {
        • if (who == chan)
          • ast_write(peer, f);
        • else
          • ast_write(chan, f);
      • }
      • ast_frfree(f);
    • } else
      • ast_frfree(f);
    • cs2 = cs0; cs0 = cs1; cs1 = cs2;
  • }
  • return res;

* static int ixj_answer(struct ast_channel *ast)
  • ixj_setup(ast);
  • ast->rings = 0;
  • ast->state = AST_STATE_UP;
  • return 0;

* static int ixj_setup(struct ast_channel *ast)
  • p = ast->pvt->pvt;
  • ioctl(p->fd, IXJCTL_CPT_STOP);
  • if (ast->format & AST_FORMAT_G723_1) {
    • ioctl(p->fd, IXJCTL_REC_STOP);
    • if (p->lastinput != AST_FORMAT_G723_1) {
      • p->lastinput = AST_FORMAT_G723_1;
      • if (ioctl(p->fd, IXJCTL_REC_CODEC, G723_63)) {
        • Failed to set codec to g723.1
        • return -1;
      • }
    • }
  • } else if (ast->format & AST_FORMAT_SLINEAR) {
    • ioctl(p->fd, IXJCTL_REC_STOP);
    • if (p->lastinput != AST_FORMAT_SLINEAR) {
      • p->lastinput = AST_FORMAT_SLINEAR;
      • if (ioctl(p->fd, IXJCTL_REC_CODEC, LINEAR16)) {
        • Failed to set codec to signed linear 16
        • return -1;
      • }
    • }
  • } else {
    • Can't do format
    • return -1;
  • }
  • if (ioctl(p->fd, IXJCTL_REC_START)) {
    • Failed to start recording
    • return -1;
  • }
  • return 0;



sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2009-07-14 08:59:36
Processing time 0.0208 sec