Index: res/res_agi.c =================================================================== --- res/res_agi.c (revision 247785) +++ res/res_agi.c (working copy) @@ -2629,6 +2629,90 @@ return RESULT_SUCCESS; } +static int handle_openaudio(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[]) +{ + struct hostent *hp; + struct ast_hostent ahp; + unsigned short portno; + int socktype; + + if (argc != 5) { + return RESULT_SHOWUSAGE; + } + + if (!strcasecmp(argv[2], "tcp")) { + socktype = SOCK_STREAM; + } else if (!strcasecmp(argv[2], "udp")) { + socktype = SOCK_DGRAM; + } else { + ast_agi_send(agi->fd, chan, "200 result=0 Unknown protocol '%s'\n", argv[2]); + return RESULT_SUCCESS; + } + + if (!(hp = ast_gethostbyname(argv[3], &ahp))) { + ast_agi_send(agi->fd, chan, "200 result=0 Host not found\n"); + return RESULT_SUCCESS; + } + + if (sscanf(argv[4], "%hd", &portno) != 1 || portno == 0) { + ast_agi_send(agi->fd, chan, "200 result=0 Invalid port number\n"); + return RESULT_SUCCESS; + } + + if ((agi->audio = socket(hp->h_addrtype, socktype, 0)) < 0) { + ast_agi_send(agi->fd, chan, "200 result=0 socket(%d) %s\n", errno, strerror(errno)); + return RESULT_SUCCESS; + } + + if (hp->h_addrtype == AF_INET) { + struct sockaddr_in sin; + memcpy(&sin.sin_addr.s_addr, hp->h_addr_list[0], sizeof(sin.sin_addr.s_addr)); + sin.sin_port = htons(portno); + if (connect(agi->audio, &sin, sizeof(sin))) { + close(agi->audio); + agi->audio = -1; + ast_agi_send(agi->fd, chan, "200 result=0 connect(%d) %s\n", errno, strerror(errno)); + return RESULT_SUCCESS; + } + /* Fall through to success */ + } else if (hp->h_addrtype == AF_INET6) { + struct sockaddr_in6 sin6; + memcpy(&sin6.sin6_addr.s6_addr, hp->h_addr_list[0], sizeof(sin6.sin6_addr.s6_addr)); + sin6.sin6_port = htons(portno); + if (connect(agi->audio, &sin6, sizeof(sin6))) { + close(agi->audio); + agi->audio = -1; + ast_agi_send(agi->fd, chan, "200 result=0 connect(%d) %s\n", errno, strerror(errno)); + return RESULT_SUCCESS; + } + /* Fall through to success */ + } else { + /* ast_gethostbyname returned a record that wasn't either IPv4 or IPv6?!! */ + ast_agi_send(agi->fd, chan, "200 result=0 This should never happen.\n"); + close(agi->audio); + agi->audio = -1; + return RESULT_SUCCESS; + } + + ast_agi_send(agi->fd, chan, "200 result=1 Audio pipe opened.\n"); + return RESULT_SUCCESS; +} + +static int handle_closeaudio(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[]) +{ + if (agi->audio > -1) { + if (close(agi->audio) < 0) { + ast_agi_send(agi->fd, chan, "200 result=0 %s\n", strerror(errno)); + } else { + ast_agi_send(agi->fd, chan, "200 result=1\n"); + agi->audio = -1; + } + } else { + ast_agi_send(agi->fd, chan, "200 result=1 Audio stream not open\n"); + } + return RESULT_SUCCESS; +} + static int handle_setmusic(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[]) { if (argc < 3) { @@ -2935,6 +3019,7 @@ { { "answer", NULL }, handle_answer, NULL, NULL, 0 }, { { "asyncagi", "break", NULL }, handle_asyncagi_break, NULL, NULL, 1 }, { { "channel", "status", NULL }, handle_channelstatus, NULL, NULL, 0 }, + { { "close", "audio", NULL }, handle_closeaudio, NULL, NULL, 0 }, { { "database", "del", NULL }, handle_dbdel, NULL, NULL, 1 }, { { "database", "deltree", NULL }, handle_dbdeltree, NULL, NULL, 1 }, { { "database", "get", NULL }, handle_dbget, NULL, NULL, 1 }, @@ -2946,6 +3031,7 @@ { { "get", "variable", NULL }, handle_getvariable, NULL, NULL, 1 }, { { "hangup", NULL }, handle_hangup, NULL, NULL, 0 }, { { "noop", NULL }, handle_noop, NULL, NULL, 1 }, + { { "open", "audio", NULL }, handle_openaudio, NULL, NULL, 0 }, { { "receive", "char", NULL }, handle_recvchar, NULL, NULL, 0 }, { { "receive", "text", NULL }, handle_recvtext, NULL, NULL, 0 }, { { "record", "file", NULL }, handle_recordfile, NULL, NULL, 0 },