Asterisk - The Open Source Telephony Project GIT-master-b023714
Loading...
Searching...
No Matches
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 = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "AudioSocket Application" , .key = ASTERISK_GPL_KEY , .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:5732
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:5773
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.
#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 struct @519 args
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

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)
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:2960
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:5114
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition channel.c:4225
ast_channel_state
ast_channel states
@ AST_STATE_UP
#define AST_FRAME_DTMF
#define ast_frfree(fr)
#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 = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "AudioSocket Application" , .key = ASTERISK_GPL_KEY , .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.