00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "asterisk.h"
00033
00034 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 182945 $")
00035
00036 #include <fcntl.h>
00037 #include <sys/time.h>
00038 #include <sys/socket.h>
00039 #include <signal.h>
00040 #ifdef HAVE_CAP
00041 #include <sys/capability.h>
00042 #endif
00043
00044 #include "asterisk/lock.h"
00045 #include "asterisk/file.h"
00046 #include "asterisk/channel.h"
00047 #include "asterisk/frame.h"
00048 #include "asterisk/pbx.h"
00049 #include "asterisk/module.h"
00050 #include "asterisk/translate.h"
00051
00052 #define LOCAL_NBSCAT "/usr/local/bin/nbscat8k"
00053 #define NBSCAT "/usr/bin/nbscat8k"
00054
00055 #ifndef AF_LOCAL
00056 #define AF_LOCAL AF_UNIX
00057 #endif
00058
00059 static char *app = "NBScat";
00060
00061 static char *synopsis = "Play an NBS local stream";
00062
00063 static char *descrip =
00064 " NBScat(): Executes nbscat to listen to the local NBS stream.\n"
00065 "User can exit by pressing any key.\n";
00066
00067
00068 static int NBScatplay(int fd)
00069 {
00070 int res;
00071 int x;
00072 sigset_t fullset, oldset;
00073 #ifdef HAVE_CAP
00074 cap_t cap;
00075 #endif
00076
00077 sigfillset(&fullset);
00078 pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
00079
00080 res = fork();
00081 if (res < 0)
00082 ast_log(LOG_WARNING, "Fork failed\n");
00083 if (res) {
00084 pthread_sigmask(SIG_SETMASK, &oldset, NULL);
00085 return res;
00086 }
00087 signal(SIGPIPE, SIG_DFL);
00088 pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
00089
00090 #ifdef HAVE_CAP
00091 cap = cap_from_text("cap_net_admin-eip");
00092
00093 if (cap_set_proc(cap)) {
00094
00095 ast_log(LOG_WARNING, "Unable to remove capabilities.\n");
00096 }
00097 cap_free(cap);
00098 #endif
00099 if (ast_opt_high_priority)
00100 ast_set_priority(0);
00101
00102 dup2(fd, STDOUT_FILENO);
00103 for (x = STDERR_FILENO + 1; x < 1024; x++) {
00104 if (x != STDOUT_FILENO)
00105 close(x);
00106 }
00107
00108 execl(NBSCAT, "nbscat8k", "-d", (char *)NULL);
00109 execl(LOCAL_NBSCAT, "nbscat8k", "-d", (char *)NULL);
00110 ast_log(LOG_WARNING, "Execute of nbscat8k failed\n");
00111 _exit(0);
00112 }
00113
00114 static int timed_read(int fd, void *data, int datalen)
00115 {
00116 int res;
00117 struct pollfd fds[1];
00118 fds[0].fd = fd;
00119 fds[0].events = POLLIN;
00120 res = ast_poll(fds, 1, 2000);
00121 if (res < 1) {
00122 ast_log(LOG_NOTICE, "Selected timed out/errored out with %d\n", res);
00123 return -1;
00124 }
00125 return read(fd, data, datalen);
00126
00127 }
00128
00129 static int NBScat_exec(struct ast_channel *chan, void *data)
00130 {
00131 int res=0;
00132 int fds[2];
00133 int ms = -1;
00134 int pid = -1;
00135 int owriteformat;
00136 struct timeval next;
00137 struct ast_frame *f;
00138 struct myframe {
00139 struct ast_frame f;
00140 char offset[AST_FRIENDLY_OFFSET];
00141 short frdata[160];
00142 } myf;
00143
00144 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds)) {
00145 ast_log(LOG_WARNING, "Unable to create socketpair\n");
00146 return -1;
00147 }
00148
00149 ast_stopstream(chan);
00150
00151 owriteformat = chan->writeformat;
00152 res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
00153 if (res < 0) {
00154 ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
00155 return -1;
00156 }
00157
00158 res = NBScatplay(fds[1]);
00159
00160 next = ast_tvnow();
00161 next.tv_sec += 1;
00162 if (res >= 0) {
00163 pid = res;
00164
00165
00166 for (;;) {
00167 ms = ast_tvdiff_ms(next, ast_tvnow());
00168 if (ms <= 0) {
00169 res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata));
00170 if (res > 0) {
00171 myf.f.frametype = AST_FRAME_VOICE;
00172 myf.f.subclass = AST_FORMAT_SLINEAR;
00173 myf.f.datalen = res;
00174 myf.f.samples = res / 2;
00175 myf.f.mallocd = 0;
00176 myf.f.offset = AST_FRIENDLY_OFFSET;
00177 myf.f.src = __PRETTY_FUNCTION__;
00178 myf.f.delivery.tv_sec = 0;
00179 myf.f.delivery.tv_usec = 0;
00180 myf.f.data = myf.frdata;
00181 if (ast_write(chan, &myf.f) < 0) {
00182 res = -1;
00183 break;
00184 }
00185 } else {
00186 ast_debug(1, "No more mp3\n");
00187 res = 0;
00188 break;
00189 }
00190 next = ast_tvadd(next, ast_samp2tv(myf.f.samples, 8000));
00191 } else {
00192 ms = ast_waitfor(chan, ms);
00193 if (ms < 0) {
00194 ast_debug(1, "Hangup detected\n");
00195 res = -1;
00196 break;
00197 }
00198 if (ms) {
00199 f = ast_read(chan);
00200 if (!f) {
00201 ast_debug(1, "Null frame == hangup() detected\n");
00202 res = -1;
00203 break;
00204 }
00205 if (f->frametype == AST_FRAME_DTMF) {
00206 ast_debug(1, "User pressed a key\n");
00207 ast_frfree(f);
00208 res = 0;
00209 break;
00210 }
00211 ast_frfree(f);
00212 }
00213 }
00214 }
00215 }
00216 close(fds[0]);
00217 close(fds[1]);
00218
00219 if (pid > -1)
00220 kill(pid, SIGKILL);
00221 if (!res && owriteformat)
00222 ast_set_write_format(chan, owriteformat);
00223
00224 return res;
00225 }
00226
00227 static int unload_module(void)
00228 {
00229 return ast_unregister_application(app);
00230 }
00231
00232 static int load_module(void)
00233 {
00234 return ast_register_application(app, NBScat_exec, synopsis, descrip);
00235 }
00236
00237 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Silly NBS Stream Application");