#include "asterisk.h"
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/capability.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/frame.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/options.h"
Go to the source code of this file.
Defines | |
#define | AF_LOCAL AF_UNIX |
#define | LOCAL_NBSCAT "/usr/local/bin/nbscat8k" |
#define | NBSCAT "/usr/bin/nbscat8k" |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static int | load_module (void) |
static int | NBScat_exec (struct ast_channel *chan, void *data) |
static int | NBScatplay (int fd) |
static int | timed_read (int fd, void *data, int datalen) |
static int | unload_module (void) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "Silly NBS Stream Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, } |
static char * | app = "NBScat" |
static const struct ast_module_info * | ast_module_info = &__mod_info |
static char * | descrip |
static char * | synopsis = "Play an NBS local stream" |
Definition in file app_nbscat.c.
#define AF_LOCAL AF_UNIX |
Definition at line 62 of file app_nbscat.c.
#define LOCAL_NBSCAT "/usr/local/bin/nbscat8k" |
#define NBSCAT "/usr/bin/nbscat8k" |
static void __reg_module | ( | void | ) | [static] |
Definition at line 256 of file app_nbscat.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 256 of file app_nbscat.c.
static int load_module | ( | void | ) | [static] |
Definition at line 251 of file app_nbscat.c.
References ast_register_application(), and NBScat_exec().
00252 { 00253 return ast_register_application(app, NBScat_exec, synopsis, descrip); 00254 }
static int NBScat_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 135 of file app_nbscat.c.
References AF_LOCAL, AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree, AST_FRIENDLY_OFFSET, ast_log(), ast_module_user_add, ast_module_user_remove, ast_read(), ast_samp2tv(), ast_set_write_format(), ast_stopstream(), ast_tvadd(), ast_tvdiff_ms(), ast_tvnow(), ast_waitfor(), ast_write(), f, LOG_DEBUG, LOG_WARNING, NBScatplay(), offset, timed_read(), and ast_channel::writeformat.
Referenced by load_module().
00136 { 00137 int res=0; 00138 struct ast_module_user *u; 00139 int fds[2]; 00140 int ms = -1; 00141 int pid = -1; 00142 int owriteformat; 00143 struct timeval next; 00144 struct ast_frame *f; 00145 struct myframe { 00146 struct ast_frame f; 00147 char offset[AST_FRIENDLY_OFFSET]; 00148 short frdata[160]; 00149 } myf; 00150 00151 u = ast_module_user_add(chan); 00152 00153 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds)) { 00154 ast_log(LOG_WARNING, "Unable to create socketpair\n"); 00155 ast_module_user_remove(u); 00156 return -1; 00157 } 00158 00159 ast_stopstream(chan); 00160 00161 owriteformat = chan->writeformat; 00162 res = ast_set_write_format(chan, AST_FORMAT_SLINEAR); 00163 if (res < 0) { 00164 ast_log(LOG_WARNING, "Unable to set write format to signed linear\n"); 00165 ast_module_user_remove(u); 00166 return -1; 00167 } 00168 00169 res = NBScatplay(fds[1]); 00170 /* Wait 1000 ms first */ 00171 next = ast_tvnow(); 00172 next.tv_sec += 1; 00173 if (res >= 0) { 00174 pid = res; 00175 /* Order is important -- there's almost always going to be mp3... we want to prioritize the 00176 user */ 00177 for (;;) { 00178 ms = ast_tvdiff_ms(next, ast_tvnow()); 00179 if (ms <= 0) { 00180 res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata)); 00181 if (res > 0) { 00182 myf.f.frametype = AST_FRAME_VOICE; 00183 myf.f.subclass = AST_FORMAT_SLINEAR; 00184 myf.f.datalen = res; 00185 myf.f.samples = res / 2; 00186 myf.f.mallocd = 0; 00187 myf.f.offset = AST_FRIENDLY_OFFSET; 00188 myf.f.src = __PRETTY_FUNCTION__; 00189 myf.f.delivery.tv_sec = 0; 00190 myf.f.delivery.tv_usec = 0; 00191 myf.f.data = myf.frdata; 00192 if (ast_write(chan, &myf.f) < 0) { 00193 res = -1; 00194 break; 00195 } 00196 } else { 00197 ast_log(LOG_DEBUG, "No more mp3\n"); 00198 res = 0; 00199 break; 00200 } 00201 next = ast_tvadd(next, ast_samp2tv(myf.f.samples, 8000)); 00202 } else { 00203 ms = ast_waitfor(chan, ms); 00204 if (ms < 0) { 00205 ast_log(LOG_DEBUG, "Hangup detected\n"); 00206 res = -1; 00207 break; 00208 } 00209 if (ms) { 00210 f = ast_read(chan); 00211 if (!f) { 00212 ast_log(LOG_DEBUG, "Null frame == hangup() detected\n"); 00213 res = -1; 00214 break; 00215 } 00216 if (f->frametype == AST_FRAME_DTMF) { 00217 ast_log(LOG_DEBUG, "User pressed a key\n"); 00218 ast_frfree(f); 00219 res = 0; 00220 break; 00221 } 00222 ast_frfree(f); 00223 } 00224 } 00225 } 00226 } 00227 close(fds[0]); 00228 close(fds[1]); 00229 00230 if (pid > -1) 00231 kill(pid, SIGKILL); 00232 if (!res && owriteformat) 00233 ast_set_write_format(chan, owriteformat); 00234 00235 ast_module_user_remove(u); 00236 00237 return res; 00238 }
static int NBScatplay | ( | int | fd | ) | [static] |
Definition at line 74 of file app_nbscat.c.
References ast_log(), ast_opt_high_priority, ast_set_priority(), LOCAL_NBSCAT, LOG_WARNING, and NBSCAT.
Referenced by NBScat_exec().
00075 { 00076 int res; 00077 int x; 00078 sigset_t fullset, oldset; 00079 #ifdef HAVE_CAP 00080 cap_t cap; 00081 #endif 00082 00083 sigfillset(&fullset); 00084 pthread_sigmask(SIG_BLOCK, &fullset, &oldset); 00085 00086 res = fork(); 00087 if (res < 0) 00088 ast_log(LOG_WARNING, "Fork failed\n"); 00089 if (res) { 00090 pthread_sigmask(SIG_SETMASK, &oldset, NULL); 00091 return res; 00092 } 00093 signal(SIGPIPE, SIG_DFL); 00094 pthread_sigmask(SIG_UNBLOCK, &fullset, NULL); 00095 00096 #ifdef HAVE_CAP 00097 cap = cap_from_text("cap_net_admin-eip"); 00098 00099 if (cap_set_proc(cap)) { 00100 /* Careful with order! Logging cannot happen after we close FDs */ 00101 ast_log(LOG_WARNING, "Unable to remove capabilities.\n"); 00102 } 00103 cap_free(cap); 00104 #endif 00105 if (ast_opt_high_priority) 00106 ast_set_priority(0); 00107 00108 dup2(fd, STDOUT_FILENO); 00109 for (x = STDERR_FILENO + 1; x < 1024; x++) { 00110 if (x != STDOUT_FILENO) 00111 close(x); 00112 } 00113 /* Most commonly installed in /usr/local/bin */ 00114 execl(NBSCAT, "nbscat8k", "-d", (char *)NULL); 00115 execl(LOCAL_NBSCAT, "nbscat8k", "-d", (char *)NULL); 00116 ast_log(LOG_WARNING, "Execute of nbscat8k failed\n"); 00117 _exit(0); 00118 }
static int timed_read | ( | int | fd, | |
void * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 120 of file app_nbscat.c.
References ast_log(), ast_poll, and LOG_NOTICE.
00121 { 00122 int res; 00123 struct pollfd fds[1]; 00124 fds[0].fd = fd; 00125 fds[0].events = POLLIN; 00126 res = ast_poll(fds, 1, 2000); 00127 if (res < 1) { 00128 ast_log(LOG_NOTICE, "Selected timed out/errored out with %d\n", res); 00129 return -1; 00130 } 00131 return read(fd, data, datalen); 00132 00133 }
static int unload_module | ( | void | ) | [static] |
Definition at line 240 of file app_nbscat.c.
References ast_module_user_hangup_all, and ast_unregister_application().
00241 { 00242 int res; 00243 00244 res = ast_unregister_application(app); 00245 00246 ast_module_user_hangup_all(); 00247 00248 return res; 00249 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "Silly NBS Stream Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, } [static] |
Definition at line 256 of file app_nbscat.c.
char* app = "NBScat" [static] |
Definition at line 65 of file app_nbscat.c.
const struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 256 of file app_nbscat.c.
char* descrip [static] |
Initial value:
" NBScat: Executes nbscat to listen to the local NBS stream.\n" "User can exit by pressing any key\n."
Definition at line 69 of file app_nbscat.c.
char* synopsis = "Play an NBS local stream" [static] |
Definition at line 67 of file app_nbscat.c.