~ubuntu-branches/ubuntu/karmic/asterisk/karmic

« back to all changes in this revision

Viewing changes to frame.c

  • Committer: Bazaar Package Importer
  • Author(s): Mark Purcell
  • Date: 2002-04-27 21:19:32 UTC
  • Revision ID: james.westby@ubuntu.com-20020427211932-kqaertc4bg7ss5mc
Tags: upstream-0.1.11
ImportĀ upstreamĀ versionĀ 0.1.11

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Asterisk -- A telephony toolkit for Linux.
 
3
 *
 
4
 * Frame manipulation routines
 
5
 * 
 
6
 * Copyright (C) 1999, Mark Spencer
 
7
 *
 
8
 * Mark Spencer <markster@linux-support.net>
 
9
 *
 
10
 * This program is free software, distributed under the terms of
 
11
 * the GNU General Public License
 
12
 */
 
13
 
 
14
#include <asterisk/frame.h>
 
15
#include <asterisk/logger.h>
 
16
#include <asterisk/options.h>
 
17
#include <asterisk/cli.h>
 
18
#include <stdlib.h>
 
19
#include <unistd.h>
 
20
#include <string.h>
 
21
#include <errno.h>
 
22
#include <pthread.h>
 
23
#include "asterisk.h"
 
24
 
 
25
#ifdef TRACE_FRAMES
 
26
static int headers = 0;
 
27
static struct ast_frame *headerlist = NULL;
 
28
static pthread_mutex_t framelock = PTHREAD_MUTEX_INITIALIZER;
 
29
#endif
 
30
 
 
31
static struct ast_frame *ast_frame_header_new(void)
 
32
{
 
33
        struct ast_frame *f;
 
34
        f = malloc(sizeof(struct ast_frame));
 
35
#ifdef TRACE_FRAMES
 
36
        if (f) {
 
37
                headers++;
 
38
                f->prev = NULL;
 
39
                pthread_mutex_lock(&framelock);
 
40
                f->next = headerlist;
 
41
                if (headerlist)
 
42
                        headerlist->prev = f;
 
43
                headerlist = f;
 
44
                pthread_mutex_unlock(&framelock);
 
45
        }
 
46
#endif  
 
47
        return f;
 
48
}
 
49
 
 
50
/*
 
51
 * Important: I should be made more efficient.  Frame headers should
 
52
 * most definitely be cached
 
53
 */
 
54
 
 
55
void ast_frfree(struct ast_frame *fr)
 
56
{
 
57
        if (fr->mallocd & AST_MALLOCD_DATA) {
 
58
                if (fr->data) 
 
59
                        free(fr->data - fr->offset);
 
60
        }
 
61
        if (fr->mallocd & AST_MALLOCD_SRC) {
 
62
                if (fr->src)
 
63
                        free(fr->src);
 
64
        }
 
65
        if (fr->mallocd & AST_MALLOCD_HDR) {
 
66
#ifdef TRACE_FRAMES
 
67
                headers--;
 
68
                pthread_mutex_lock(&framelock);
 
69
                if (fr->next)
 
70
                        fr->next->prev = fr->prev;
 
71
                if (fr->prev)
 
72
                        fr->prev->next = fr->next;
 
73
                else
 
74
                        headerlist = fr->next;
 
75
                pthread_mutex_unlock(&framelock);
 
76
#endif                  
 
77
                free(fr);
 
78
        }
 
79
}
 
80
 
 
81
struct ast_frame *ast_frisolate(struct ast_frame *fr)
 
82
{
 
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();
 
87
                if (!out) {
 
88
                        ast_log(LOG_WARNING, "Out of memory\n");
 
89
                        return NULL;
 
90
                }
 
91
                out->frametype = fr->frametype;
 
92
                out->subclass = fr->subclass;
 
93
                out->datalen = 0;
 
94
                out->timelen = fr->timelen;
 
95
                out->offset = 0;
 
96
                out->src = NULL;
 
97
                out->data = NULL;
 
98
        } else {
 
99
                out = fr;
 
100
        }
 
101
        if (!(fr->mallocd & AST_MALLOCD_SRC)) {
 
102
                if (fr->src)
 
103
                        out->src = strdup(fr->src);
 
104
        } else
 
105
                out->src = fr->src;
 
106
        if (!(fr->mallocd & AST_MALLOCD_DATA))  {
 
107
                out->data = malloc(fr->datalen + AST_FRIENDLY_OFFSET);
 
108
                if (!out->data) {
 
109
                        free(out);
 
110
                        ast_log(LOG_WARNING, "Out of memory\n");
 
111
                        return NULL;
 
112
                }
 
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);
 
117
        }
 
118
        out->mallocd = AST_MALLOCD_HDR | AST_MALLOCD_SRC | AST_MALLOCD_DATA;
 
119
        return out;
 
120
}
 
121
 
 
122
struct ast_frame *ast_frdup(struct ast_frame *f)
 
123
{
 
124
        struct ast_frame *ret;
 
125
        int p;
 
126
        p = f->mallocd;
 
127
        f->mallocd = 0;
 
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 */
 
131
        f->mallocd = p;
 
132
        return ret;
 
133
}
 
134
 
 
135
struct ast_frame *ast_fr_fdread(int fd)
 
136
{
 
137
        char buf[65536];
 
138
        int res;
 
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
 
142
           right format. */
 
143
        
 
144
        while(ttl) {
 
145
                res = read(fd, buf, ttl);
 
146
                if (res < 0) {
 
147
                        ast_log(LOG_WARNING, "Bad read on %d: %s\n", fd, strerror(errno));
 
148
                        return NULL;
 
149
                }
 
150
                ttl -= res;
 
151
        }
 
152
        
 
153
        /* read the frame header */
 
154
        f->mallocd = 0;
 
155
        /* Re-write data position */
 
156
        f->data = buf + sizeof(struct ast_frame);
 
157
        f->offset = 0;
 
158
        /* Forget about being mallocd */
 
159
        f->mallocd = 0;
 
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);
 
165
                return NULL;
 
166
        }
 
167
        if (f->datalen) {
 
168
                if ((res = read(fd, f->data, f->datalen)) != f->datalen) {
 
169
                        /* Bad read */
 
170
                        ast_log(LOG_WARNING, "How very strange, expected %d, got %d\n", f->datalen, res);
 
171
                        return NULL;
 
172
                }
 
173
        }
 
174
        if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
 
175
                return NULL;
 
176
        }
 
177
        return ast_frisolate(f);
 
178
}
 
179
 
 
180
/* Some convenient routines for sending frames to/from stream or datagram
 
181
   sockets, pipes, etc (maybe even files) */
 
182
 
 
183
int ast_fr_fdwrite(int fd, struct ast_frame *frame)
 
184
{
 
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));
 
188
                return -1;
 
189
        }
 
190
        if (write(fd, frame->data, frame->datalen) != frame->datalen) {
 
191
                ast_log(LOG_WARNING, "Write error: %s\n", strerror(errno));
 
192
                return -1;
 
193
        }
 
194
        return 0;
 
195
}
 
196
 
 
197
int ast_fr_fdhangup(int fd)
 
198
{
 
199
        struct ast_frame hangup = {
 
200
                AST_FRAME_CONTROL,
 
201
                AST_CONTROL_HANGUP
 
202
        };
 
203
        return ast_fr_fdwrite(fd, &hangup);
 
204
}
 
205
 
 
206
int ast_getformatbyname(char *name)
 
207
{
 
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"))
 
225
                return 0x7FFFFFFF;
 
226
        return 0;
 
227
}
 
228
 
 
229
#ifdef TRACE_FRAMES
 
230
static int show_frame_stats(int fd, int argc, char *argv[])
 
231
{
 
232
        struct ast_frame *f;
 
233
        int x=1;
 
234
        if (argc != 3)
 
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>");
 
243
        }
 
244
        pthread_mutex_unlock(&framelock);
 
245
        return RESULT_SUCCESS;
 
246
}
 
247
 
 
248
static char frame_stats_usage[] =
 
249
"Usage: show frame stats\n"
 
250
"       Displays debugging statistics from framer\n";
 
251
 
 
252
struct ast_cli_entry cli_frame_stats =
 
253
{ { "show", "frame", "stats", NULL }, show_frame_stats, "Shows frame statistics", frame_stats_usage };
 
254
#endif
 
255
 
 
256
int init_framer(void)
 
257
{
 
258
#ifdef TRACE_FRAMES
 
259
        ast_cli_register(&cli_frame_stats);
 
260
#endif
 
261
        return 0;       
 
262
}