Asterisk - The Open Source Telephony Project GIT-master-2de1a68
Macros | Functions | Variables
res_audiosocket.c File Reference

AudioSocket support for Asterisk. More...

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

Go to the source code of this file.

Macros

#define MAX_CONNECT_TIMEOUT_MSEC   2000
 
#define MODULE_DESCRIPTION   "AudioSocket support functions for Asterisk"
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
const int ast_audiosocket_connect (const char *server, struct ast_channel *chan)
 Send the initial message to an AudioSocket server. More...
 
const int ast_audiosocket_init (const int svc, const char *id)
 Send the initial message to an AudioSocket server. More...
 
struct ast_frameast_audiosocket_receive_frame (const int svc)
 Receive an Asterisk frame from an AudioSocket server. More...
 
const int ast_audiosocket_send_frame (const int svc, const struct ast_frame *f)
 Send an Asterisk audio frame to an AudioSocket server. More...
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int handle_audiosocket_connection (const char *server, const struct ast_sockaddr addr, const int netsockfd)
 
static int load_module (void)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "AudioSocket support" , .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_DEPEND, }
 
static const struct ast_module_infoast_module_info = &__mod_info
 

Detailed Description

AudioSocket support for Asterisk.

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

Definition in file res_audiosocket.c.

Macro Definition Documentation

◆ MAX_CONNECT_TIMEOUT_MSEC

#define MAX_CONNECT_TIMEOUT_MSEC   2000

Definition at line 44 of file res_audiosocket.c.

◆ MODULE_DESCRIPTION

#define MODULE_DESCRIPTION   "AudioSocket support functions for Asterisk"

Definition at line 42 of file res_audiosocket.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 344 of file res_audiosocket.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 344 of file res_audiosocket.c.

◆ ast_audiosocket_connect()

const int ast_audiosocket_connect ( const char *  server,
struct ast_channel chan 
)

Send the initial message to an AudioSocket server.

Parameters
serverThe server address, including port.
chanAn optional channel which will be put into autoservice during the connection period. If there is no channel to be autoserviced, pass NULL instead.
Return values
socketfile descriptor for AudioSocket on success
-1on error

Definition at line 99 of file res_audiosocket.c.

100{
101 int s = -1;
102 struct ast_sockaddr *addrs = NULL;
103 int num_addrs = 0, i = 0;
104
105 if (chan && ast_autoservice_start(chan) < 0) {
106 ast_log(LOG_WARNING, "Failed to start autoservice for channel "
107 "%s\n", ast_channel_name(chan));
108 goto end;
109 }
110
111 if (ast_strlen_zero(server)) {
112 ast_log(LOG_ERROR, "No AudioSocket server provided\n");
113 goto end;
114 }
115
116 if (!(num_addrs = ast_sockaddr_resolve(&addrs, server, PARSE_PORT_REQUIRE,
117 AST_AF_UNSPEC))) {
118 ast_log(LOG_ERROR, "Failed to resolve AudioSocket service using %s - "
119 "requires a valid hostname and port\n", server);
120 goto end;
121 }
122
123 /* Connect to AudioSocket service */
124 for (i = 0; i < num_addrs; i++) {
125
126 if (!ast_sockaddr_port(&addrs[i])) {
127 /* If there's no port, other addresses should have the
128 * same problem. Stop here.
129 */
130 ast_log(LOG_ERROR, "No port provided for %s\n",
131 ast_sockaddr_stringify(&addrs[i]));
132 s = -1;
133 goto end;
134 }
135
136 if ((s = ast_socket_nonblock(addrs[i].ss.ss_family, SOCK_STREAM,
137 IPPROTO_TCP)) < 0) {
138 ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
139 continue;
140 }
141
142 if (ast_connect(s, &addrs[i]) && errno == EINPROGRESS) {
143
144 if (handle_audiosocket_connection(server, addrs[i], s)) {
145 close(s);
146 continue;
147 }
148
149 } else {
150 ast_log(LOG_ERROR, "Connection to %s failed with unexpected error: %s\n",
151 ast_sockaddr_stringify(&addrs[i]), strerror(errno));
152 close(s);
153 s = -1;
154 }
155
156 break;
157 }
158
159end:
160 if (addrs) {
161 ast_free(addrs);
162 }
163
164 if (chan && ast_autoservice_stop(chan) < 0) {
165 ast_log(LOG_WARNING, "Failed to stop autoservice for channel %s\n",
166 ast_channel_name(chan));
167 close(s);
168 return -1;
169 }
170
171 if (i == num_addrs) {
172 ast_log(LOG_ERROR, "Failed to connect to AudioSocket service\n");
173 close(s);
174 return -1;
175 }
176
177 return s;
178}
#define ast_free(a)
Definition: astmm.h:180
#define ast_log
Definition: astobj2.c:42
const char * ast_channel_name(const struct ast_channel *chan)
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:266
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:200
char * end
Definition: eagi_proxy.c:73
@ PARSE_PORT_REQUIRE
#define LOG_ERROR
#define LOG_WARNING
int errno
@ AST_AF_UNSPEC
Definition: netsock2.h:54
int ast_connect(int sockfd, const struct ast_sockaddr *addr)
Wrapper around connect(2) that uses struct ast_sockaddr.
Definition: netsock2.c:595
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:256
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:517
int ast_sockaddr_resolve(struct ast_sockaddr **addrs, const char *str, int flags, int family)
Parses a string with an IPv4 or IPv6 address and place results into an array.
Definition: netsock2.c:280
static int handle_audiosocket_connection(const char *server, const struct ast_sockaddr addr, const int netsockfd)
#define NULL
Definition: resample.c:96
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
Socket address structure.
Definition: netsock2.h:97
struct sockaddr_storage ss
Definition: netsock2.h:98
#define ast_socket_nonblock(domain, type, protocol)
Create a non-blocking socket.
Definition: utils.h:1073

References AST_AF_UNSPEC, ast_autoservice_start(), ast_autoservice_stop(), ast_channel_name(), ast_connect(), ast_free, ast_log, ast_sockaddr_port, ast_sockaddr_resolve(), ast_sockaddr_stringify(), ast_socket_nonblock, ast_strlen_zero(), end, errno, handle_audiosocket_connection(), LOG_ERROR, LOG_WARNING, NULL, PARSE_PORT_REQUIRE, and ast_sockaddr::ss.

Referenced by audiosocket_exec(), and audiosocket_request().

◆ ast_audiosocket_init()

const int ast_audiosocket_init ( const int  svc,
const char *  id 
)

Send the initial message to an AudioSocket server.

Parameters
svcThe file descriptor of the network socket to the AudioSocket server.
idThe UUID to send to the AudioSocket server to uniquely identify this connection.
Return values
0on success
-1on error

Definition at line 180 of file res_audiosocket.c.

181{
182 uuid_t uu;
183 int ret = 0;
184 uint8_t buf[3 + 16];
185
186 if (ast_strlen_zero(id)) {
187 ast_log(LOG_ERROR, "No UUID for AudioSocket\n");
188 return -1;
189 }
190
191 if (uuid_parse(id, uu)) {
192 ast_log(LOG_ERROR, "Failed to parse UUID '%s'\n", id);
193 return -1;
194 }
195
196 buf[0] = 0x01;
197 buf[1] = 0x00;
198 buf[2] = 0x10;
199 memcpy(buf + 3, uu, 16);
200
201 if (write(svc, buf, 3 + 16) != 3 + 16) {
202 ast_log(LOG_WARNING, "Failed to write data to AudioSocket\n");
203 ret = -1;
204 }
205
206 return ret;
207}
char buf[BUFSIZE]
Definition: eagi_proxy.c:66

References ast_log, ast_strlen_zero(), buf, LOG_ERROR, and LOG_WARNING.

Referenced by audiosocket_call(), and audiosocket_run().

◆ ast_audiosocket_receive_frame()

struct ast_frame * ast_audiosocket_receive_frame ( const int  svc)

Receive an Asterisk frame from an AudioSocket server.

This returned object is a pointer to an Asterisk frame which must be manually freed by the caller.

Parameters
svcThe file descriptor of the network socket to the AudioSocket server.
Return values
Aast_frame on success
NULLon error

Definition at line 231 of file res_audiosocket.c.

232{
233
234 int i = 0, n = 0, ret = 0, not_audio = 0;
235 struct ast_frame f = {
237 .subclass.format = ast_format_slin,
238 .src = "AudioSocket",
239 .mallocd = AST_MALLOCD_DATA,
240 };
241 uint8_t kind;
242 uint8_t len_high;
243 uint8_t len_low;
244 uint16_t len = 0;
245 uint8_t *data;
246
247 n = read(svc, &kind, 1);
248 if (n < 0 && errno == EAGAIN) {
249 return &ast_null_frame;
250 }
251 if (n == 0) {
252 return &ast_null_frame;
253 }
254 if (n != 1) {
255 ast_log(LOG_WARNING, "Failed to read type header from AudioSocket\n");
256 return NULL;
257 }
258 if (kind == 0x00) {
259 /* AudioSocket ended by remote */
260 return NULL;
261 }
262 if (kind != 0x10) {
263 /* read but ignore non-audio message */
264 ast_log(LOG_WARNING, "Received non-audio AudioSocket message\n");
265 not_audio = 1;
266 }
267
268 n = read(svc, &len_high, 1);
269 if (n != 1) {
270 ast_log(LOG_WARNING, "Failed to read data length from AudioSocket\n");
271 return NULL;
272 }
273 len += len_high * 256;
274 n = read(svc, &len_low, 1);
275 if (n != 1) {
276 ast_log(LOG_WARNING, "Failed to read data length from AudioSocket\n");
277 return NULL;
278 }
279 len += len_low;
280
281 if (len < 1) {
282 return &ast_null_frame;
283 }
284
286 if (!data) {
287 ast_log(LOG_ERROR, "Failed to allocate for data from AudioSocket\n");
288 return NULL;
289 }
290
291 ret = 0;
292 n = 0;
293 i = 0;
294 while (i < len) {
295 n = read(svc, data + i, len - i);
296 if (n < 0) {
297 ast_log(LOG_ERROR, "Failed to read data from AudioSocket\n");
298 ret = n;
299 break;
300 }
301 if (n == 0) {
302 ast_log(LOG_ERROR, "Insufficient data read from AudioSocket\n");
303 ret = -1;
304 break;
305 }
306 i += n;
307 }
308
309 if (ret != 0) {
310 ast_free(data);
311 return NULL;
312 }
313
314 if (not_audio) {
315 ast_free(data);
316 return &ast_null_frame;
317 }
318
319 f.data.ptr = data;
320 f.datalen = len;
321 f.samples = len / 2;
322
323 /* The frame steals data, so it doesn't need to be freed here */
324 return ast_frisolate(&f);
325}
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
#define AST_MALLOCD_DATA
@ AST_FRAME_VOICE
struct ast_frame ast_null_frame
Definition: main/frame.c:79
Data structure associated with a single frame of data.
union ast_frame::@226 data
enum ast_frame_type frametype

References ast_format_slin, AST_FRAME_VOICE, ast_free, ast_frisolate, ast_log, ast_malloc, AST_MALLOCD_DATA, ast_null_frame, ast_frame::data, ast_frame::datalen, errno, ast_frame::frametype, len(), LOG_ERROR, LOG_WARNING, NULL, ast_frame::ptr, and ast_frame::samples.

Referenced by audiosocket_read(), and audiosocket_run().

◆ ast_audiosocket_send_frame()

const int ast_audiosocket_send_frame ( const int  svc,
const struct ast_frame f 
)

Send an Asterisk audio frame to an AudioSocket server.

Parameters
svcThe file descriptor of the network socket to the AudioSocket server.
fThe Asterisk audio frame to send.
Return values
0on success
-1on error

Definition at line 209 of file res_audiosocket.c.

210{
211 int ret = 0;
212 uint8_t kind = 0x10; /* always 16-bit, 8kHz signed linear mono, for now */
213 uint8_t *p;
214 uint8_t buf[3 + f->datalen];
215
216 p = buf;
217
218 *(p++) = kind;
219 *(p++) = f->datalen >> 8;
220 *(p++) = f->datalen & 0xff;
221 memcpy(p, f->data.ptr, f->datalen);
222
223 if (write(svc, buf, 3 + f->datalen) != 3 + f->datalen) {
224 ast_log(LOG_WARNING, "Failed to write data to AudioSocket\n");
225 ret = -1;
226 }
227
228 return ret;
229}

References ast_log, buf, ast_frame::data, ast_frame::datalen, LOG_WARNING, and ast_frame::ptr.

Referenced by audiosocket_run(), and audiosocket_write().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 344 of file res_audiosocket.c.

◆ handle_audiosocket_connection()

static int handle_audiosocket_connection ( const char *  server,
const struct ast_sockaddr  addr,
const int  netsockfd 
)
static

Definition at line 57 of file res_audiosocket.c.

59{
60 struct pollfd pfds[1];
61 int res, conresult;
62 socklen_t reslen;
63
64 reslen = sizeof(conresult);
65
66 pfds[0].fd = netsockfd;
67 pfds[0].events = POLLOUT;
68
69 while ((res = ast_poll(pfds, 1, MAX_CONNECT_TIMEOUT_MSEC)) != 1) {
70 if (errno != EINTR) {
71 if (!res) {
72 ast_log(LOG_WARNING, "AudioSocket connection to '%s' timed"
73 "out after MAX_CONNECT_TIMEOUT_MSEC (%d) milliseconds.\n",
75 } else {
76 ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", server,
77 strerror(errno));
78 }
79
80 return -1;
81 }
82 }
83
84 if (getsockopt(pfds[0].fd, SOL_SOCKET, SO_ERROR, &conresult, &reslen) < 0) {
85 ast_log(LOG_WARNING, "Connection to %s failed with error: %s\n",
86 ast_sockaddr_stringify(&addr), strerror(errno));
87 return -1;
88 }
89
90 if (conresult) {
91 ast_log(LOG_WARNING, "Connecting to '%s' failed for url '%s': %s\n",
92 ast_sockaddr_stringify(&addr), server, strerror(conresult));
93 return -1;
94 }
95
96 return 0;
97}
#define ast_poll(a, b, c)
Definition: poll-compat.h:88
#define MAX_CONNECT_TIMEOUT_MSEC

References ast_log, ast_poll, ast_sockaddr_stringify(), errno, LOG_WARNING, and MAX_CONNECT_TIMEOUT_MSEC.

Referenced by ast_audiosocket_connect().

◆ load_module()

static int load_module ( void  )
static

Definition at line 327 of file res_audiosocket.c.

328{
329 ast_verb(5, "Loading AudioSocket Support module\n");
331}
#define ast_verb(level,...)
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70

References AST_MODULE_LOAD_SUCCESS, and ast_verb.

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 333 of file res_audiosocket.c.

334{
335 ast_verb(5, "Unloading AudioSocket Support module\n");
337}

References AST_MODULE_LOAD_SUCCESS, and ast_verb.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "AudioSocket support" , .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_DEPEND, }
static

Definition at line 344 of file res_audiosocket.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 344 of file res_audiosocket.c.