#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 <errno.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 | path_BIN "/usr/bin/" |
#define | path_LOCAL "/usr/local/bin/" |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static int | ices_exec (struct ast_channel *chan, void *data) |
static int | icesencode (char *filename, int fd) |
static int | load_module (void) |
static int | unload_module (void) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "Encode and Stream via icecast and ices" , .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 = "ICES" |
static const struct ast_module_info * | ast_module_info = &__mod_info |
static char * | descrip |
static char * | synopsis = "Encode and stream using 'ices'" |
Definition in file app_ices.c.
#define path_BIN "/usr/bin/" |
#define path_LOCAL "/usr/local/bin/" |
static void __reg_module | ( | void | ) | [static] |
Definition at line 253 of file app_ices.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 253 of file app_ices.c.
static int ices_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 132 of file app_ices.c.
References ast_channel::_state, ast_answer(), ast_config_AST_CONFIG_DIR, ast_copy_string(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_frfree, ast_log(), ast_module_user_add, ast_module_user_remove, ast_read(), ast_set_read_format(), AST_STATE_UP, ast_stopstream(), ast_strlen_zero(), ast_tv(), ast_waitfor(), errno, f, icesencode(), LOG_DEBUG, LOG_WARNING, and ast_channel::readformat.
Referenced by load_module().
00133 { 00134 int res=0; 00135 struct ast_module_user *u; 00136 int fds[2]; 00137 int ms = -1; 00138 int pid = -1; 00139 int flags; 00140 int oreadformat; 00141 struct timeval last; 00142 struct ast_frame *f; 00143 char filename[256]=""; 00144 char *c; 00145 00146 if (ast_strlen_zero(data)) { 00147 ast_log(LOG_WARNING, "ICES requires an argument (configfile.xml)\n"); 00148 return -1; 00149 } 00150 00151 u = ast_module_user_add(chan); 00152 00153 last = ast_tv(0, 0); 00154 00155 if (pipe(fds)) { 00156 ast_log(LOG_WARNING, "Unable to create pipe\n"); 00157 ast_module_user_remove(u); 00158 return -1; 00159 } 00160 flags = fcntl(fds[1], F_GETFL); 00161 fcntl(fds[1], F_SETFL, flags | O_NONBLOCK); 00162 00163 ast_stopstream(chan); 00164 00165 if (chan->_state != AST_STATE_UP) 00166 res = ast_answer(chan); 00167 00168 if (res) { 00169 close(fds[0]); 00170 close(fds[1]); 00171 ast_log(LOG_WARNING, "Answer failed!\n"); 00172 ast_module_user_remove(u); 00173 return -1; 00174 } 00175 00176 oreadformat = chan->readformat; 00177 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); 00178 if (res < 0) { 00179 close(fds[0]); 00180 close(fds[1]); 00181 ast_log(LOG_WARNING, "Unable to set write format to signed linear\n"); 00182 ast_module_user_remove(u); 00183 return -1; 00184 } 00185 if (((char *)data)[0] == '/') 00186 ast_copy_string(filename, (char *) data, sizeof(filename)); 00187 else 00188 snprintf(filename, sizeof(filename), "%s/%s", (char *)ast_config_AST_CONFIG_DIR, (char *)data); 00189 /* Placeholder for options */ 00190 c = strchr(filename, '|'); 00191 if (c) 00192 *c = '\0'; 00193 res = icesencode(filename, fds[0]); 00194 if (res >= 0) { 00195 pid = res; 00196 for (;;) { 00197 /* Wait for audio, and stream */ 00198 ms = ast_waitfor(chan, -1); 00199 if (ms < 0) { 00200 ast_log(LOG_DEBUG, "Hangup detected\n"); 00201 res = -1; 00202 break; 00203 } 00204 f = ast_read(chan); 00205 if (!f) { 00206 ast_log(LOG_DEBUG, "Null frame == hangup() detected\n"); 00207 res = -1; 00208 break; 00209 } 00210 if (f->frametype == AST_FRAME_VOICE) { 00211 res = write(fds[1], f->data, f->datalen); 00212 if (res < 0) { 00213 if (errno != EAGAIN) { 00214 ast_log(LOG_WARNING, "Write failed to pipe: %s\n", strerror(errno)); 00215 res = -1; 00216 ast_frfree(f); 00217 break; 00218 } 00219 } 00220 } 00221 ast_frfree(f); 00222 } 00223 } 00224 close(fds[0]); 00225 close(fds[1]); 00226 00227 if (pid > -1) 00228 kill(pid, SIGKILL); 00229 if (!res && oreadformat) 00230 ast_set_read_format(chan, oreadformat); 00231 00232 ast_module_user_remove(u); 00233 00234 return res; 00235 }
static int icesencode | ( | char * | filename, | |
int | fd | |||
) | [static] |
Definition at line 70 of file app_ices.c.
References ast_log(), ast_opt_high_priority, ast_set_priority(), LOG_DEBUG, LOG_WARNING, option_debug, path_BIN, and path_LOCAL.
Referenced by ices_exec().
00071 { 00072 int res; 00073 int x; 00074 sigset_t fullset, oldset; 00075 #ifdef HAVE_CAP 00076 cap_t cap; 00077 #endif 00078 00079 sigfillset(&fullset); 00080 pthread_sigmask(SIG_BLOCK, &fullset, &oldset); 00081 00082 res = fork(); 00083 if (res < 0) 00084 ast_log(LOG_WARNING, "Fork failed\n"); 00085 if (res) { 00086 pthread_sigmask(SIG_SETMASK, &oldset, NULL); 00087 return res; 00088 } 00089 00090 /* Stop ignoring PIPE */ 00091 signal(SIGPIPE, SIG_DFL); 00092 pthread_sigmask(SIG_UNBLOCK, &fullset, NULL); 00093 00094 #ifdef HAVE_CAP 00095 cap = cap_from_text("cap_net_admin-eip"); 00096 00097 if (cap_set_proc(cap)) { 00098 /* Careful with order! Logging cannot happen after we close FDs */ 00099 ast_log(LOG_WARNING, "Unable to remove capabilities.\n"); 00100 } 00101 cap_free(cap); 00102 #endif 00103 00104 if (ast_opt_high_priority) 00105 ast_set_priority(0); 00106 dup2(fd, STDIN_FILENO); 00107 for (x=STDERR_FILENO + 1;x<1024;x++) { 00108 if ((x != STDIN_FILENO) && (x != STDOUT_FILENO)) 00109 close(x); 00110 } 00111 00112 /* Most commonly installed in /usr/local/bin 00113 * But many places has it in /usr/bin 00114 * As a last-ditch effort, try to use PATH 00115 */ 00116 execl(path_LOCAL "ices2", "ices", filename, (char *)NULL); 00117 execl(path_BIN "ices2", "ices", filename, (char *)NULL); 00118 execlp("ices2", "ices", filename, (char *)NULL); 00119 00120 if (option_debug) 00121 ast_log(LOG_DEBUG, "Couldn't find ices version 2, attempting to use ices version 1."); 00122 00123 execl(path_LOCAL "ices", "ices", filename, (char *)NULL); 00124 execl(path_BIN "ices", "ices", filename, (char *)NULL); 00125 execlp("ices", "ices", filename, (char *)NULL); 00126 00127 ast_log(LOG_WARNING, "Execute of ices failed, could not be found.\n"); 00128 close(fd); 00129 _exit(0); 00130 }
static int load_module | ( | void | ) | [static] |
Definition at line 248 of file app_ices.c.
References ast_register_application(), and ices_exec().
00249 { 00250 return ast_register_application(app, ices_exec, synopsis, descrip); 00251 }
static int unload_module | ( | void | ) | [static] |
Definition at line 237 of file app_ices.c.
References ast_module_user_hangup_all, and ast_unregister_application().
00238 { 00239 int res; 00240 00241 res = ast_unregister_application(app); 00242 00243 ast_module_user_hangup_all(); 00244 00245 return res; 00246 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "Encode and Stream via icecast and ices" , .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 253 of file app_ices.c.
char* app = "ICES" [static] |
Definition at line 61 of file app_ices.c.
const struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 253 of file app_ices.c.
char* descrip [static] |
Initial value:
" ICES(config.xml) Streams to an icecast server using ices\n" "(available separately). A configuration file must be supplied\n" "for ices (see contrib/asterisk-ices.xml). \n"
Definition at line 65 of file app_ices.c.
char* synopsis = "Encode and stream using 'ices'" [static] |
Definition at line 63 of file app_ices.c.