· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
Asterisk Source/App Dial

AsteriskSource/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;

ID
Password
Join
Deprive a mirror of its silver and even the Czar won't see his face.


sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2009-08-09 14:52:34
Processing time 0.0017 sec