Wed Jan 8 2020 09:49:39

Asterisk developer's documentation


app_ices.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*! \file
20  *
21  * \brief Stream to an icecast server via ICES (see contrib/asterisk-ices.xml)
22  *
23  * \author Mark Spencer <markster@digium.com>
24  *
25  * \extref ICES - http://www.icecast.org/ices.php
26  *
27  * \ingroup applications
28  */
29 
30 /*** MODULEINFO
31  <support_level>extended</support_level>
32  ***/
33 
34 #include "asterisk.h"
35 
36 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 361471 $")
37 
38 #include <signal.h>
39 #include <fcntl.h>
40 #include <sys/time.h>
41 
42 #include "asterisk/paths.h" /* use ast_config_AST_CONFIG_DIR */
43 #include "asterisk/lock.h"
44 #include "asterisk/file.h"
45 #include "asterisk/channel.h"
46 #include "asterisk/frame.h"
47 #include "asterisk/pbx.h"
48 #include "asterisk/module.h"
49 #include "asterisk/translate.h"
50 #include "asterisk/app.h"
51 
52 /*** DOCUMENTATION
53  <application name="ICES" language="en_US">
54  <synopsis>
55  Encode and stream using 'ices'.
56  </synopsis>
57  <syntax>
58  <parameter name="config" required="true">
59  <para>ICES configuration file.</para>
60  </parameter>
61  </syntax>
62  <description>
63  <para>Streams to an icecast server using ices (available separately).
64  A configuration file must be supplied for ices (see contrib/asterisk-ices.xml).</para>
65  <note><para>ICES version 2 client and server required.</para></note>
66  </description>
67  </application>
68 
69  ***/
70 
71 #define path_BIN "/usr/bin/"
72 #define path_LOCAL "/usr/local/bin/"
73 
74 static char *app = "ICES";
75 
76 static int icesencode(char *filename, int fd)
77 {
78  int res;
79 
80  res = ast_safe_fork(0);
81  if (res < 0)
82  ast_log(LOG_WARNING, "Fork failed\n");
83  if (res) {
84  return res;
85  }
86 
89  dup2(fd, STDIN_FILENO);
90  ast_close_fds_above_n(STDERR_FILENO);
91 
92  /* Most commonly installed in /usr/local/bin
93  * But many places has it in /usr/bin
94  * As a last-ditch effort, try to use PATH
95  */
96  execl(path_LOCAL "ices2", "ices", filename, SENTINEL);
97  execl(path_BIN "ices2", "ices", filename, SENTINEL);
98  execlp("ices2", "ices", filename, SENTINEL);
99 
100  ast_debug(1, "Couldn't find ices version 2, attempting to use ices version 1.\n");
101 
102  execl(path_LOCAL "ices", "ices", filename, SENTINEL);
103  execl(path_BIN "ices", "ices", filename, SENTINEL);
104  execlp("ices", "ices", filename, SENTINEL);
105 
106  ast_log(LOG_WARNING, "Execute of ices failed, could not find command.\n");
107  close(fd);
108  _exit(0);
109 }
110 
111 static int ices_exec(struct ast_channel *chan, const char *data)
112 {
113  int res = 0;
114  int fds[2];
115  int ms = -1;
116  int pid = -1;
117  int flags;
118  int oreadformat;
119  struct ast_frame *f;
120  char filename[256]="";
121  char *c;
122 
123  if (ast_strlen_zero(data)) {
124  ast_log(LOG_WARNING, "ICES requires an argument (configfile.xml)\n");
125  return -1;
126  }
127 
128  if (pipe(fds)) {
129  ast_log(LOG_WARNING, "Unable to create pipe\n");
130  return -1;
131  }
132  flags = fcntl(fds[1], F_GETFL);
133  fcntl(fds[1], F_SETFL, flags | O_NONBLOCK);
134 
135  ast_stopstream(chan);
136 
137  if (chan->_state != AST_STATE_UP)
138  res = ast_answer(chan);
139 
140  if (res) {
141  close(fds[0]);
142  close(fds[1]);
143  ast_log(LOG_WARNING, "Answer failed!\n");
144  return -1;
145  }
146 
147  oreadformat = chan->readformat;
149  if (res < 0) {
150  close(fds[0]);
151  close(fds[1]);
152  ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
153  return -1;
154  }
155  if (((char *)data)[0] == '/')
156  ast_copy_string(filename, (char *) data, sizeof(filename));
157  else
158  snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_CONFIG_DIR, (char *)data);
159  /* Placeholder for options */
160  c = strchr(filename, '|');
161  if (c)
162  *c = '\0';
163  res = icesencode(filename, fds[0]);
164  if (res >= 0) {
165  pid = res;
166  for (;;) {
167  /* Wait for audio, and stream */
168  ms = ast_waitfor(chan, -1);
169  if (ms < 0) {
170  ast_debug(1, "Hangup detected\n");
171  res = -1;
172  break;
173  }
174  f = ast_read(chan);
175  if (!f) {
176  ast_debug(1, "Null frame == hangup() detected\n");
177  res = -1;
178  break;
179  }
180  if (f->frametype == AST_FRAME_VOICE) {
181  res = write(fds[1], f->data.ptr, f->datalen);
182  if (res < 0) {
183  if (errno != EAGAIN) {
184  ast_log(LOG_WARNING, "Write failed to pipe: %s\n", strerror(errno));
185  res = -1;
186  ast_frfree(f);
187  break;
188  }
189  }
190  }
191  ast_frfree(f);
192  }
193  }
194  close(fds[0]);
195  close(fds[1]);
196 
197  if (pid > -1)
198  kill(pid, SIGKILL);
199  if (!res && oreadformat)
200  ast_set_read_format(chan, oreadformat);
201 
202  return res;
203 }
204 
205 static int unload_module(void)
206 {
207  return ast_unregister_application(app);
208 }
209 
210 static int load_module(void)
211 {
213 }
214 
215 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Encode and Stream via icecast and ices");
Main Channel structure associated with a channel.
Definition: channel.h:742
static int ices_exec(struct ast_channel *chan, const char *data)
Definition: app_ices.c:111
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:396
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
#define path_BIN
Definition: app_ices.c:71
int ast_safe_fork(int stop_reaper)
Common routine to safely fork without a chance of a signal handler firing badly in the child...
Definition: app.c:2242
Support for translation of data formats. translate.c.
void * ptr
Definition: frame.h:160
#define LOG_WARNING
Definition: logger.h:144
unsigned int flags
Definition: utils.h:201
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
static int icesencode(char *filename, int fd)
Definition: app_ices.c:76
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
static int unload_module(void)
Definition: app_ices.c:205
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
static char * app
Definition: app_ices.c:74
static int load_module(void)
Definition: app_ices.c:210
int ast_set_read_format(struct ast_channel *chan, format_t format)
Sets read format on channel chan Set read format for channel to whichever component of &quot;format&quot; is be...
Definition: channel.c:5301
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define SENTINEL
Definition: compiler.h:75
General Asterisk PBX channel definitions.
Asterisk file paths, configured in asterisk.conf.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
Asterisk internal frame definitions.
int datalen
Definition: frame.h:148
Core PBX routines and definitions.
int ast_set_priority(int)
We set ourselves to a high priority, that we might pre-empt everything else. If your PBX has heavy ac...
Definition: asterisk.c:1650
const char * ast_config_AST_CONFIG_DIR
Definition: asterisk.c:256
enum ast_channel_state _state
Definition: channel.h:839
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int errno
void ast_close_fds_above_n(int n)
Common routine for child processes, to close all fds prior to exec(2)
Definition: app.c:2237
static struct ast_format f[]
Definition: format_g726.c:181
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3539
format_t readformat
Definition: channel.h:853
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
Data structure associated with a single frame of data.
Definition: frame.h:142
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_frfree(fr)
Definition: frame.h:583
#define path_LOCAL
Definition: app_ices.c:72
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:38
Asterisk module definitions.
union ast_frame::@172 data
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:128
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
#define ast_opt_high_priority
Definition: options.h:108