2
* Asterisk -- A telephony toolkit for Linux.
4
* Frame manipulation routines
6
* Copyright (C) 1999, Mark Spencer
8
* Mark Spencer <markster@linux-support.net>
10
* This program is free software, distributed under the terms of
11
* the GNU General Public License
14
#include <asterisk/frame.h>
15
#include <asterisk/logger.h>
16
#include <asterisk/options.h>
17
#include <asterisk/cli.h>
26
static int headers = 0;
27
static struct ast_frame *headerlist = NULL;
28
static pthread_mutex_t framelock = PTHREAD_MUTEX_INITIALIZER;
31
static struct ast_frame *ast_frame_header_new(void)
34
f = malloc(sizeof(struct ast_frame));
39
pthread_mutex_lock(&framelock);
44
pthread_mutex_unlock(&framelock);
51
* Important: I should be made more efficient. Frame headers should
52
* most definitely be cached
55
void ast_frfree(struct ast_frame *fr)
57
if (fr->mallocd & AST_MALLOCD_DATA) {
59
free(fr->data - fr->offset);
61
if (fr->mallocd & AST_MALLOCD_SRC) {
65
if (fr->mallocd & AST_MALLOCD_HDR) {
68
pthread_mutex_lock(&framelock);
70
fr->next->prev = fr->prev;
72
fr->prev->next = fr->next;
74
headerlist = fr->next;
75
pthread_mutex_unlock(&framelock);
81
struct ast_frame *ast_frisolate(struct ast_frame *fr)
83
struct ast_frame *out;
84
if (!(fr->mallocd & AST_MALLOCD_HDR)) {
85
/* Allocate a new header if needed */
86
out = ast_frame_header_new();
88
ast_log(LOG_WARNING, "Out of memory\n");
91
out->frametype = fr->frametype;
92
out->subclass = fr->subclass;
94
out->timelen = fr->timelen;
101
if (!(fr->mallocd & AST_MALLOCD_SRC)) {
103
out->src = strdup(fr->src);
106
if (!(fr->mallocd & AST_MALLOCD_DATA)) {
107
out->data = malloc(fr->datalen + AST_FRIENDLY_OFFSET);
110
ast_log(LOG_WARNING, "Out of memory\n");
113
out->data += AST_FRIENDLY_OFFSET;
114
out->offset = AST_FRIENDLY_OFFSET;
115
out->datalen = fr->datalen;
116
memcpy(out->data, fr->data, fr->datalen);
118
out->mallocd = AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA;
122
struct ast_frame *ast_frdup(struct ast_frame *f)
124
struct ast_frame *ret;
128
/* Make frisolate think this is a 100% static frame, and make a duplicate */
129
ret = ast_frisolate(f);
130
/* Restore its true malloc status */
135
struct ast_frame *ast_fr_fdread(int fd)
139
int ttl = sizeof(struct ast_frame);
140
struct ast_frame *f = (struct ast_frame *)buf;
141
/* Read a frame directly from there. They're always in the
145
res = read(fd, buf, ttl);
147
ast_log(LOG_WARNING, "Bad read on %d: %s\n", fd, strerror(errno));
153
/* read the frame header */
155
/* Re-write data position */
156
f->data = buf + sizeof(struct ast_frame);
158
/* Forget about being mallocd */
160
/* Re-write the source */
161
f->src = __FUNCTION__;
162
if (f->datalen > sizeof(buf) - sizeof(struct ast_frame)) {
163
/* Really bad read */
164
ast_log(LOG_WARNING, "Strange read (%d bytes)\n", f->datalen);
168
if ((res = read(fd, f->data, f->datalen)) != f->datalen) {
170
ast_log(LOG_WARNING, "How very strange, expected %d, got %d\n", f->datalen, res);
174
if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
177
return ast_frisolate(f);
180
/* Some convenient routines for sending frames to/from stream or datagram
181
sockets, pipes, etc (maybe even files) */
183
int ast_fr_fdwrite(int fd, struct ast_frame *frame)
185
/* Write the frame exactly */
186
if (write(fd, frame, sizeof(struct ast_frame)) != sizeof(struct ast_frame)) {
187
ast_log(LOG_WARNING, "Write error: %s\n", strerror(errno));
190
if (write(fd, frame->data, frame->datalen) != frame->datalen) {
191
ast_log(LOG_WARNING, "Write error: %s\n", strerror(errno));
197
int ast_fr_fdhangup(int fd)
199
struct ast_frame hangup = {
203
return ast_fr_fdwrite(fd, &hangup);
206
int ast_getformatbyname(char *name)
208
if (!strcasecmp(name, "g723.1"))
209
return AST_FORMAT_G723_1;
210
else if (!strcasecmp(name, "gsm"))
211
return AST_FORMAT_GSM;
212
else if (!strcasecmp(name, "ulaw"))
213
return AST_FORMAT_ULAW;
214
else if (!strcasecmp(name, "alaw"))
215
return AST_FORMAT_ALAW;
216
else if (!strcasecmp(name, "mp3"))
217
return AST_FORMAT_MP3;
218
else if (!strcasecmp(name, "slinear"))
219
return AST_FORMAT_SLINEAR;
220
else if (!strcasecmp(name, "lpc10"))
221
return AST_FORMAT_LPC10;
222
else if (!strcasecmp(name, "adpcm"))
223
return AST_FORMAT_ADPCM;
224
else if (!strcasecmp(name, "all"))
230
static int show_frame_stats(int fd, int argc, char *argv[])
235
return RESULT_SHOWUSAGE;
236
ast_cli(fd, " Framer Statistics \n");
237
ast_cli(fd, "---------------------------\n");
238
ast_cli(fd, "Total allocated headers: %d\n", headers);
239
ast_cli(fd, "Queue Dump:\n");
240
pthread_mutex_lock(&framelock);
241
for (f=headerlist; f; f = f->next) {
242
ast_cli(fd, "%d. Type %d, subclass %d from %s\n", x++, f->frametype, f->subclass, f->src ? f->src : "<Unknown>");
244
pthread_mutex_unlock(&framelock);
245
return RESULT_SUCCESS;
248
static char frame_stats_usage[] =
249
"Usage: show frame stats\n"
250
" Displays debugging statistics from framer\n";
252
struct ast_cli_entry cli_frame_stats =
253
{ { "show", "frame", "stats", NULL }, show_frame_stats, "Shows frame statistics", frame_stats_usage };
256
int init_framer(void)
259
ast_cli_register(&cli_frame_stats);