Asterisk - The Open Source Telephony Project GIT-master-8f1982c
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
Macros | Functions | Variables
app_audiosocket.c File Reference

AudioSocket application – transmit and receive audio through a TCP socket. More...

#include "asterisk.h"
#include "errno.h"
#include <uuid/uuid.h>
#include "asterisk/file.h"
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/app.h"
#include "asterisk/pbx.h"
#include "asterisk/res_audiosocket.h"
#include "asterisk/utils.h"
#include "asterisk/format_cache.h"
Include dependency graph for app_audiosocket.c:

Go to the source code of this file.

Macros

#define AST_MODULE   "app_audiosocket"
 
#define AUDIOSOCKET_CONFIG   "audiosocket.conf"
 
#define MAX_WAIT_TIMEOUT_MSEC   2000
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int audiosocket_exec (struct ast_channel *chan, const char *data)
 
static int audiosocket_run (struct ast_channel *chan, const char *id, const int svc, const char *server)
 
static int load_module (void)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = "app_audiosocket" , .flags = AST_MODFLAG_LOAD_ORDER , .description = "AudioSocket 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 = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .requires = "res_audiosocket", }
 
static const char app [] = "AudioSocket"
 
static const struct ast_module_infoast_module_info = &__mod_info
 

Detailed Description

AudioSocket application – transmit and receive audio through a TCP socket.

Author
Seán C McCord scm@c.nosp@m.ycor.nosp@m.esys..nosp@m.com

Definition in file app_audiosocket.c.

Macro Definition Documentation

◆ AST_MODULE

#define AST_MODULE   "app_audiosocket"

Definition at line 46 of file app_audiosocket.c.

◆ AUDIOSOCKET_CONFIG

#define AUDIOSOCKET_CONFIG   "audiosocket.conf"

Definition at line 47 of file app_audiosocket.c.

◆ MAX_WAIT_TIMEOUT_MSEC

#define MAX_WAIT_TIMEOUT_MSEC   2000

Definition at line 48 of file app_audiosocket.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 247 of file app_audiosocket.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 247 of file app_audiosocket.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 247 of file app_audiosocket.c.

◆ audiosocket_exec()

static int audiosocket_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 78 of file app_audiosocket.c.

79{
80 char *parse;
81 struct ast_format *readFormat, *writeFormat;
82 const char *chanName;
83 int res;
84
86 AST_APP_ARG(idStr);
87 AST_APP_ARG(server);
88 );
89
90 int s = 0;
91 uuid_t uu;
92
93
94 chanName = ast_channel_name(chan);
95
96 /* Parse and validate arguments */
97 parse = ast_strdupa(data);
99 if (ast_strlen_zero(args.idStr)) {
100 ast_log(LOG_ERROR, "UUID is required\n");
101 return -1;
102 }
103 if (uuid_parse(args.idStr, uu)) {
104 ast_log(LOG_ERROR, "Failed to parse UUID '%s'\n", args.idStr);
105 return -1;
106 }
107 if ((s = ast_audiosocket_connect(args.server, chan)) < 0) {
108 /* The res module will already output a log message, so another is not needed */
109 return -1;
110 }
111
112 /* Save current channel audio format and force to linear PCM. */
113
114 writeFormat = ao2_bump(ast_channel_writeformat(chan));
115 readFormat = ao2_bump(ast_channel_readformat(chan));
116
118 ast_log(LOG_ERROR, "Failed to set write format to SLINEAR for channel '%s'\n", chanName);
119 res = -1;
120 goto end;
121 }
122
124 ast_log(LOG_ERROR, "Failed to set read format to SLINEAR for channel '%s'\n", chanName);
125 res = -1;
126 goto end;
127 }
128
129 /* Only a requested hangup or socket closure from the remote end will
130 return a 0 value (normal exit). All other events that disrupt an
131 active connection are treated as errors for now (non-zero). */
132
133 res = audiosocket_run(chan, args.idStr, s, args.server);
134
135end:
136
137 /* Restore previous formats and close the connection */
138 if (ast_set_write_format(chan, writeFormat)) {
139 ast_log(LOG_ERROR, "Failed to restore write format for channel '%s'\n", chanName);
140 }
141 if (ast_set_read_format(chan, readFormat)) {
142 ast_log(LOG_ERROR, "Failed to restore read format for channel '%s'\n", chanName);
143 }
144 ao2_ref(writeFormat, -1);
145 ao2_ref(readFormat, -1);
146 close(s);
147
148 return res;
149}
static int audiosocket_run(struct ast_channel *chan, const char *id, const int svc, const char *server)
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
const char * ast_channel_name(const struct ast_channel *chan)
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition: channel.c:5721
struct ast_format * ast_channel_writeformat(struct ast_channel *chan)
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
Definition: channel.c:5762
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
char * end
Definition: eagi_proxy.c:73
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define LOG_ERROR
const int ast_audiosocket_connect(const char *server, struct ast_channel *chan)
Send the initial message to an AudioSocket server.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
Definition of a media format.
Definition: format.c:43
const char * args

References ao2_bump, ao2_ref, args, AST_APP_ARG, ast_audiosocket_connect(), ast_channel_name(), ast_channel_readformat(), ast_channel_writeformat(), AST_DECLARE_APP_ARGS, ast_format_slin, ast_log, ast_set_read_format(), ast_set_write_format(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), audiosocket_run(), end, and LOG_ERROR.

Referenced by load_module().

◆ audiosocket_run()

static int audiosocket_run ( struct ast_channel chan,
const char *  id,
const int  svc,
const char *  server 
)
static

Definition at line 151 of file app_audiosocket.c.

152{
153 const char *chanName;
154 struct ast_channel *targetChan;
155 int ms = MAX_WAIT_TIMEOUT_MSEC;
156 int outfd = -1;
157 struct ast_frame *f;
158 int hangup;
159
160 if (!chan || ast_channel_state(chan) != AST_STATE_UP) {
161 ast_log(LOG_ERROR, "Channel is %s\n", chan ? "not answered" : "missing");
162 return -1;
163 }
164
165 if (ast_audiosocket_init(svc, id)) {
166 ast_log(LOG_ERROR, "Failed to initialize AudioSocket\n");
167 return -1;
168 }
169
170 chanName = ast_channel_name(chan);
171
172 while (1) {
173 /* Timeout is hard-coded currently, could be made into an
174 argument if needed, but 2 seconds seems like a realistic
175 time range to give. */
176 targetChan = ast_waitfor_nandfds(&chan, 1, &svc, 1, NULL, &outfd, &ms);
178
179 if (targetChan) {
180 /* Receive frame from connected channel. */
181 f = ast_read(chan);
182 if (!f) {
183 ast_log(LOG_WARNING, "Failed to receive frame from channel '%s' connected to AudioSocket server '%s'", chanName, server);
184 return -1;
185 }
186
188 /* Send audio frame or DTMF frame to audiosocket */
189 if (ast_audiosocket_send_frame(svc, f)) {
190 ast_log(LOG_WARNING, "Failed to forward frame from channel '%s' to AudioSocket server '%s'\n",
191 chanName, server);
192 ast_frfree(f);
193 return -1;
194 }
195 }
196 ast_frfree(f);
197
198 } else if (outfd >= 0) {
199 /* Receive audio frame from audiosocket. */
201 if (hangup) {
202 /* Graceful termination, no frame to free. */
203 return 0;
204 }
205 if (!f) {
206 ast_log(LOG_WARNING, "Failed to receive frame from AudioSocket server '%s'"
207 " connected to channel '%s'\n", server, chanName);
208 return -1;
209 }
210 /* Send audio frame to connected channel. */
211 if (ast_write(chan, f)) {
212 ast_log(LOG_WARNING, "Failed to forward frame from AudioSocket server '%s' to channel '%s'\n", server, chanName);
213 ast_frfree(f);
214 return -1;
215 }
216 ast_frfree(f);
217
218 } else {
219 /* Neither the channel nor audio socket had activity
220 before timeout. Assume connection was lost. */
221 ast_log(LOG_ERROR, "Reached timeout after %d ms of no activity on AudioSocket connection between '%s' and '%s'\n", MAX_WAIT_TIMEOUT_MSEC, chanName, server);
222 return -1;
223 }
224 }
225 return 0;
226}
#define MAX_WAIT_TIMEOUT_MSEC
static int hangup(void *data)
Definition: chan_pjsip.c:2520
struct ast_channel * ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds, int nfds, int *exception, int *outfd, int *ms)
Waits for activity on a group of channels.
Definition: channel.c:2956
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
Definition: channel.c:5103
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4214
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_UP
Definition: channelstate.h:42
#define AST_FRAME_DTMF
#define ast_frfree(fr)
@ AST_FRAME_VOICE
#define LOG_WARNING
const int ast_audiosocket_init(const int svc, const char *id)
Send the initial message to an AudioSocket server.
const int ast_audiosocket_send_frame(const int svc, const struct ast_frame *f)
Send an Asterisk audio frame to an AudioSocket server.
struct ast_frame * ast_audiosocket_receive_frame_with_hangup(const int svc, int *const hangup)
Receive an Asterisk frame from an AudioSocket server.
#define NULL
Definition: resample.c:96
Main Channel structure associated with a channel.
Data structure associated with a single frame of data.
enum ast_frame_type frametype

References ast_audiosocket_init(), ast_audiosocket_receive_frame_with_hangup(), ast_audiosocket_send_frame(), ast_channel_name(), AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree, ast_log, ast_read(), AST_STATE_UP, ast_waitfor_nandfds(), ast_write(), ast_frame::frametype, hangup(), LOG_ERROR, LOG_WARNING, MAX_WAIT_TIMEOUT_MSEC, and NULL.

Referenced by audiosocket_exec().

◆ load_module()

static int load_module ( void  )
static

Definition at line 233 of file app_audiosocket.c.

234{
236}
static const char app[]
static int audiosocket_exec(struct ast_channel *chan, const char *data)
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:640

References app, ast_register_application_xml, and audiosocket_exec().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 228 of file app_audiosocket.c.

229{
231}
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392

References app, and ast_unregister_application().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = "app_audiosocket" , .flags = AST_MODFLAG_LOAD_ORDER , .description = "AudioSocket 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 = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .requires = "res_audiosocket", }
static

Definition at line 247 of file app_audiosocket.c.

◆ app

const char app[] = "AudioSocket"
static

Definition at line 74 of file app_audiosocket.c.

Referenced by load_module(), and unload_module().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 247 of file app_audiosocket.c.