== 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 *cs[3]; * if (chan->state != AST_STATE_UP) * if (ast_answer(chan)) * return -1; * cs[0] = chan; * cs[1] = 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); * cs[2] = cs[0]; cs[0] = cs[1]; cs[1] = cs[2]; * } * 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;