Asterisk - The Open Source Telephony Project GIT-master-754dea3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
Enumerations | Functions
res_audiosocket.h File Reference

AudioSocket support functions. More...

#include <uuid/uuid.h>
#include "asterisk/frame.h"
#include "asterisk/uuid.h"
Include dependency graph for res_audiosocket.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Enumerations

enum  ast_audiosocket_msg_kind {
  AST_AUDIOSOCKET_KIND_HANGUP = 0x00 , AST_AUDIOSOCKET_KIND_UUID = 0x01 , AST_AUDIOSOCKET_KIND_DTMF = 0x03 , AST_AUDIOSOCKET_KIND_AUDIO = 0x10 ,
  AST_AUDIOSOCKET_KIND_ERROR = 0xFF
}
 

Functions

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...
 
struct ast_frameast_audiosocket_receive_frame_with_hangup (const int svc, int *const hangup)
 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...
 

Detailed Description

AudioSocket support functions.

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

Definition in file res_audiosocket.h.

Enumeration Type Documentation

◆ ast_audiosocket_msg_kind

Enumerator
AST_AUDIOSOCKET_KIND_HANGUP 

Message indicates the channel should be hung up, direction: Sent only.

AST_AUDIOSOCKET_KIND_UUID 

Message contains the connection's UUID, direction: Received only.

AST_AUDIOSOCKET_KIND_DTMF 

Message contains a DTMF digit, direction: Received only.

AST_AUDIOSOCKET_KIND_AUDIO 

Messages contains audio data, direction: Sent and received.

AST_AUDIOSOCKET_KIND_ERROR 

An Asterisk-side error occurred, direction: Received only.

Definition at line 40 of file res_audiosocket.h.

40 {
41 /*! \brief Message indicates the channel should be hung up, direction: Sent only. */
43
44 /*! \brief Message contains the connection's UUID, direction: Received only. */
46
47 /*! \brief Message contains a DTMF digit, direction: Received only. */
49
50 /*! \brief Messages contains audio data, direction: Sent and received. */
52
53 /*! \brief An Asterisk-side error occurred, direction: Received only. */
55};
@ AST_AUDIOSOCKET_KIND_AUDIO
Messages contains audio data, direction: Sent and received.
@ AST_AUDIOSOCKET_KIND_HANGUP
Message indicates the channel should be hung up, direction: Sent only.
@ AST_AUDIOSOCKET_KIND_UUID
Message contains the connection's UUID, direction: Received only.
@ AST_AUDIOSOCKET_KIND_DTMF
Message contains a DTMF digit, direction: Received only.
@ AST_AUDIOSOCKET_KIND_ERROR
An Asterisk-side error occurred, direction: Received only.

Function Documentation

◆ 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 100 of file res_audiosocket.c.

101{
102 int s = -1;
103 struct ast_sockaddr *addrs = NULL;
104 int num_addrs = 0, i = 0;
105
106 if (chan && ast_autoservice_start(chan) < 0) {
107 ast_log(LOG_WARNING, "Failed to start autoservice for channel "
108 "'%s'\n", ast_channel_name(chan));
109 goto end;
110 }
111
112 if (ast_strlen_zero(server)) {
113 ast_log(LOG_ERROR, "No AudioSocket server provided\n");
114 goto end;
115 }
116
117 if (!(num_addrs = ast_sockaddr_resolve(&addrs, server, PARSE_PORT_REQUIRE,
118 AST_AF_UNSPEC))) {
119 ast_log(LOG_ERROR, "Failed to resolve AudioSocket service using '%s' - "
120 "requires a valid hostname and port\n", server);
121 goto end;
122 }
123
124 /* Connect to AudioSocket service */
125 for (i = 0; i < num_addrs; i++) {
126
127 if (!ast_sockaddr_port(&addrs[i])) {
128 /* If there's no port, other addresses should have the
129 * same problem. Stop here.
130 */
131 ast_log(LOG_ERROR, "No port provided for '%s'\n",
132 ast_sockaddr_stringify(&addrs[i]));
133 s = -1;
134 goto end;
135 }
136
137 if ((s = ast_socket_nonblock(addrs[i].ss.ss_family, SOCK_STREAM,
138 IPPROTO_TCP)) < 0) {
139 ast_log(LOG_WARNING, "Unable to create socket: '%s'\n", strerror(errno));
140 continue;
141 }
142
143 if (ast_connect(s, &addrs[i]) && errno == EINPROGRESS) {
144
145 if (handle_audiosocket_connection(server, addrs[i], s)) {
146 close(s);
147 continue;
148 }
149
150 } else {
151 ast_log(LOG_ERROR, "Connection to '%s' failed with unexpected error: %s\n",
152 ast_sockaddr_stringify(&addrs[i]), strerror(errno));
153 close(s);
154 s = -1;
155 }
156
157 break;
158 }
159
160end:
161 if (addrs) {
162 ast_free(addrs);
163 }
164
165 if (chan && ast_autoservice_stop(chan) < 0) {
166 ast_log(LOG_WARNING, "Failed to stop autoservice for channel '%s'\n",
167 ast_channel_name(chan));
168 close(s);
169 return -1;
170 }
171
172 if (i == num_addrs) {
173 ast_log(LOG_ERROR, "Failed to connect to AudioSocket service\n");
174 close(s);
175 return -1;
176 }
177
178 return s;
179}
#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
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
@ AST_AF_UNSPEC
Definition: netsock2.h:54
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 181 of file res_audiosocket.c.

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

References AST_AUDIOSOCKET_KIND_UUID, ast_log, ast_strlen_zero(), buf, errno, 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 248 of file res_audiosocket.c.

249{
251}
struct ast_frame * ast_audiosocket_receive_frame_with_hangup(const int svc, int *const hangup)
Receive an Asterisk frame from an AudioSocket server.

References ast_audiosocket_receive_frame_with_hangup(), and NULL.

◆ ast_audiosocket_receive_frame_with_hangup()

struct ast_frame * ast_audiosocket_receive_frame_with_hangup ( const int  svc,
int *const  hangup 
)

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.
hangupWill be true if the AudioSocket server requested the channel be hung up, otherwise false. Used as an out-parameter only, pass NULL if not needed. The function return value will always be NULL when true.
Return values
Aast_frame on success
NULLon error or when the hungup parameter is true.

Definition at line 253 of file res_audiosocket.c.

255{
256 int i = 0, n = 0, ret = 0;
257 struct ast_frame f = {
259 .subclass.format = ast_format_slin,
260 .src = "AudioSocket",
261 .mallocd = AST_MALLOCD_DATA,
262 };
263 uint8_t header[3];
264 uint8_t *kind = &header[0];
265 uint16_t *length = (uint16_t *) &header[1];
266 uint8_t *data;
267
268 if (hangup) {
269 *hangup = 0;
270 }
271
272 n = read(svc, &header, 3);
273 if (n == -1) {
274 ast_log(LOG_WARNING, "Failed to read header from AudioSocket because: %s\n", strerror(errno));
275 return NULL;
276 }
277
278 if (n == 0 || *kind == AST_AUDIOSOCKET_KIND_HANGUP) {
279 /* Socket closure or requested hangup. */
280 if (hangup) {
281 *hangup = 1;
282 }
283 return NULL;
284 }
285
286 if (*kind != AST_AUDIOSOCKET_KIND_AUDIO) {
287 ast_log(LOG_ERROR, "Received AudioSocket message other than hangup or audio, refer to protocol specification for valid message types\n");
288 return NULL;
289 }
290
291 /* Swap endianess of length if needed. */
292 *length = ntohs(*length);
293 if (*length < 1) {
294 ast_log(LOG_ERROR, "Invalid message length received from AudioSocket server. \n");
295 return NULL;
296 }
297
298 data = ast_malloc(*length);
299 if (!data) {
300 ast_log(LOG_ERROR, "Failed to allocate for data from AudioSocket\n");
301 return NULL;
302 }
303
304 ret = 0;
305 n = 0;
306 i = 0;
307 while (i < *length) {
308 n = read(svc, data + i, *length - i);
309 if (n == -1) {
310 ast_log(LOG_ERROR, "Failed to read payload from AudioSocket: %s\n", strerror(errno));
311 ret = -1;
312 break;
313 }
314 if (n == 0) {
315 ast_log(LOG_ERROR, "Insufficient payload read from AudioSocket\n");
316 ret = -1;
317 break;
318 }
319 i += n;
320 }
321
322 if (ret != 0) {
323 ast_free(data);
324 return NULL;
325 }
326
327 f.data.ptr = data;
328 f.datalen = *length;
329 f.samples = *length / 2;
330
331 /* The frame steals data, so it doesn't need to be freed here */
332 return ast_frisolate(&f);
333}
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
static int hangup(void *data)
Definition: chan_pjsip.c:2520
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
#define AST_MALLOCD_DATA
@ AST_FRAME_VOICE
Data structure associated with a single frame of data.
union ast_frame::@228 data
enum ast_frame_type frametype

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

Referenced by ast_audiosocket_receive_frame(), 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 210 of file res_audiosocket.c.

211{
212 int datalen = f->datalen;
213 if (f->frametype == AST_FRAME_DTMF) {
214 datalen = 1;
215 }
216
217 {
218 uint8_t buf[3 + datalen];
219 uint16_t *length = (uint16_t *) &buf[1];
220
221 /* Audio format is 16-bit, 8kHz signed linear mono for dialplan app,
222 depends on agreed upon audio codec for channel driver interface. */
223 switch (f->frametype) {
224 case AST_FRAME_VOICE:
226 *length = htons(datalen);
227 memcpy(&buf[3], f->data.ptr, datalen);
228 break;
229 case AST_FRAME_DTMF:
231 buf[3] = (uint8_t) f->subclass.integer;
232 *length = htons(1);
233 break;
234 default:
235 ast_log(LOG_ERROR, "Unsupported frame type %d for AudioSocket\n", f->frametype);
236 return -1;
237 }
238
239 if (write(svc, buf, 3 + datalen) != 3 + datalen) {
240 ast_log(LOG_WARNING, "Failed to write data to AudioSocket because: %s\n", strerror(errno));
241 return -1;
242 }
243 }
244
245 return 0;
246}
#define AST_FRAME_DTMF
struct ast_frame_subclass subclass

References AST_AUDIOSOCKET_KIND_AUDIO, AST_AUDIOSOCKET_KIND_DTMF, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_log, buf, ast_frame::data, ast_frame::datalen, errno, ast_frame::frametype, ast_frame_subclass::integer, LOG_ERROR, LOG_WARNING, ast_frame::ptr, and ast_frame::subclass.

Referenced by audiosocket_run(), audiosocket_send_dtmf(), and audiosocket_write().