[asterisk-commits] branch russell/codetest r8722 - in
/team/russell/codetest: ./ apps/ channels/...
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Thu Jan 26 11:29:40 MST 2006
Author: russell
Date: Thu Jan 26 12:29:29 2006
New Revision: 8722
URL: http://svn.digium.com/view/asterisk?rev=8722&view=rev
Log:
constify arguments to tests and add some missing files
Added:
team/russell/codetest/apps/app_morsecode.c
team/russell/codetest/formats/format_h264.c
team/russell/codetest/funcs/func_base64.c
team/russell/codetest/include/asterisk/stringfields.h
team/russell/codetest/udptl.c
Modified:
team/russell/codetest/channels/chan_sip.c
team/russell/codetest/include/asterisk/codetest.h
Added: team/russell/codetest/apps/app_morsecode.c
URL: http://svn.digium.com/view/asterisk/team/russell/codetest/apps/app_morsecode.c?rev=8722&view=auto
==============================================================================
--- team/russell/codetest/apps/app_morsecode.c (added)
+++ team/russell/codetest/apps/app_morsecode.c Thu Jan 26 12:29:29 2006
@@ -1,0 +1,185 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (c) 2006, Tilghman Lesher. All rights reserved.
+ *
+ * Tilghman Lesher <app_morsecode__v001 at the-tilghman.com>
+ *
+ * This code is released by the author with no restrictions on usage.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ */
+
+/*! \file
+ *
+ * \brief Morsecode application
+ *
+ * \author Tilghman Lesher <app_morsecode__v001 at the-tilghman.com>
+ *
+ * \ingroup applications
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 7221 $")
+
+#include "asterisk/file.h"
+#include "asterisk/logger.h"
+#include "asterisk/options.h"
+#include "asterisk/channel.h"
+#include "asterisk/pbx.h"
+#include "asterisk/module.h"
+#include "asterisk/indications.h"
+
+static char *tdesc = "Morse code";
+
+static char *app_morsecode = "Morsecode";
+
+static char *morsecode_synopsis = "Plays morse code";
+
+static char *morsecode_descrip =
+"Usage: Morsecode(<string>)\n"
+"Plays the Morse code equivalent of the passed string\n";
+
+STANDARD_LOCAL_USER;
+
+LOCAL_USER_DECL;
+
+#define TONE 800
+#define DITLEN 80
+
+static char *morsecode[] = {
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 0-15 */
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 16-31 */
+ " ", /* 32 - <space> */
+ ".-.-.-", /* 33 - ! */
+ ".-..-.", /* 34 - " */
+ "", /* 35 - # */
+ "", /* 36 - $ */
+ "", /* 37 - % */
+ "", /* 38 - & */
+ ".----.", /* 39 - ' */
+ "-.--.-", /* 40 - ( */
+ "-.--.-", /* 41 - ) */
+ "", /* 42 - * */
+ "", /* 43 - + */
+ "--..--", /* 44 - , */
+ "-....-", /* 45 - - */
+ ".-.-.-", /* 46 - . */
+ "-··-·", /* 47 - / */
+ "-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----.", /* 48-57 - 0-9 */
+ "---...", /* 58 - : */
+ "-·-·-·", /* 59 - ; */
+ "", /* 60 - < */
+ "-...-", /* 61 - = */
+ "", /* 62 - > */
+ "..--..", /* 63 - ? */
+ ".--.-.", /* 64 - @ */
+ ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--",
+ "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..",
+ "-.--.-", /* 91 - [ (really '(') */
+ "-··-·", /* 92 - \ (really '/') */
+ "-.--.-", /* 93 - ] (really ')') */
+ "", /* 94 - ^ */
+ "··--·-", /* 95 - _ */
+ ".----.", /* 96 - ` */
+ ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--",
+ "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..",
+ "-.--.-", /* 123 - { (really '(') */
+ "", /* 124 - | */
+ "-.--.-", /* 125 - } (really ')') */
+ "-··-·", /* 126 - ~ (really bar) */
+ "· · ·", /* 127 - <del> (error) */
+};
+
+static void playtone(struct ast_channel *chan, int tone, int len)
+{
+ char dtmf[20];
+ snprintf(dtmf, sizeof(dtmf), "%d/%d", tone, DITLEN * len);
+ ast_playtones_start(chan, 0, dtmf, 0);
+ ast_safe_sleep(chan, DITLEN * len);
+ ast_playtones_stop(chan);
+}
+
+static int morsecode_exec(struct ast_channel *chan, void *data)
+{
+ int res=0;
+ char *digit;
+ struct localuser *u;
+
+ LOCAL_USER_ADD(u);
+
+ if (ast_strlen_zero(data)) {
+ ast_log(LOG_WARNING, "Syntax: Morsecode(<string>) - no argument found\n");
+ LOCAL_USER_REMOVE(u);
+ return 0;
+ }
+
+ for (digit = data; *digit; digit++) {
+ char *dahdit;
+ if (*digit < 0) {
+ continue;
+ }
+ for (dahdit = morsecode[(int)*digit]; *dahdit; dahdit++) {
+ if (*dahdit == '-') {
+ playtone(chan, TONE, 3);
+ } else if (*dahdit == '.') {
+ playtone(chan, TONE, 1);
+ } else {
+ /* Account for ditlen of silence immediately following */
+ playtone(chan, 0, 2);
+ }
+
+ /* Pause slightly between each dit and dah */
+ playtone(chan, 0, 1);
+ }
+ /* Pause between characters */
+ playtone(chan, 0, 2);
+ }
+
+ LOCAL_USER_REMOVE(u);
+ return res;
+}
+
+int unload_module(void)
+{
+ int res;
+
+ res = ast_unregister_application(app_morsecode);
+
+ STANDARD_HANGUP_LOCALUSERS;
+
+ return res;
+}
+
+int load_module(void)
+{
+ return ast_register_application(app_morsecode, morsecode_exec, morsecode_synopsis, morsecode_descrip);
+}
+
+char *description(void)
+{
+ return tdesc;
+}
+
+int usecount(void)
+{
+ int res;
+ STANDARD_USECOUNT(res);
+ return res;
+}
+
+char *key()
+{
+ return ASTERISK_GPL_KEY;
+}
Modified: team/russell/codetest/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/russell/codetest/channels/chan_sip.c?rev=8722&r1=8721&r2=8722&view=diff
==============================================================================
--- team/russell/codetest/channels/chan_sip.c (original)
+++ team/russell/codetest/channels/chan_sip.c Thu Jan 26 12:29:29 2006
@@ -948,14 +948,6 @@
int find_sip_method(char *msg);
unsigned int parse_sip_options(struct sip_pvt *pvt, char *supported);
-#ifdef ENABLE_CODE_TEST
-static int test_tags_func(int fd, int argc, char *argv[]);
-static int test_callid_uniqueness_func(void);
-static struct sip_request *create_sip_message(int number);
-#endif
-
-AST_DEFINE_CODE_TEST(test_tags, "tags", test_tags_func);
-AST_DEFINE_CODE_TEST(test_callid_uniqueness, "callid_uniqueness", test_callid_uniqueness_func);
/*! \brief Definition of this channel for PBX channel registration */
static const struct ast_channel_tech sip_tech = {
@@ -13131,7 +13123,7 @@
#ifdef ENABLE_CODE_TEST
/*! \brief Test tag retrieval code */
-static int test_tags_func(int fd, int argc, char *argv[])
+static int test_tags_func(int fd, int argc, char * const argv[])
{
struct sip_request *req;
char buf[BUFSIZ];
@@ -13167,7 +13159,7 @@
#ifdef ENABLE_CODE_TEST
/* Test call ID generation */
/* Generate 10.000 call id:s and check if they are identical */
-static int test_callid_uniqueness_func(void)
+static int test_callid_uniqueness_func(int fd, int argc, char * const argv[])
{
char *call_ids[10000];
char *our_ip="192.168.40.1";
@@ -13209,6 +13201,9 @@
return errors;
}
#endif
+
+AST_DEFINE_CODE_TEST(test_tags, "tags", test_tags_func);
+AST_DEFINE_CODE_TEST(test_callid_uniqueness, "callid_uniqueness", test_callid_uniqueness_func);
/*! \brief sip_do_reload: Reload module */
static int sip_do_reload(enum channelreloadreason reason)
Added: team/russell/codetest/formats/format_h264.c
URL: http://svn.digium.com/view/asterisk/team/russell/codetest/formats/format_h264.c?rev=8722&view=auto
==============================================================================
--- team/russell/codetest/formats/format_h264.c (added)
+++ team/russell/codetest/formats/format_h264.c Thu Jan 26 12:29:29 2006
@@ -1,0 +1,281 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 1999 - 2005, Digium, Inc.
+ *
+ * Mark Spencer <markster at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Save to raw, headerless h264 data.
+ * \arg File name extension: h264
+ * \ingroup formats
+ */
+
+#include <unistd.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 7221 $")
+
+#include "asterisk/lock.h"
+#include "asterisk/channel.h"
+#include "asterisk/file.h"
+#include "asterisk/logger.h"
+#include "asterisk/sched.h"
+#include "asterisk/module.h"
+#include "asterisk/endian.h"
+
+/* Some Ideas for this code came from makeh264e.c by Jeffrey Chilton */
+
+/* Portions of the conversion code are by guido at sienanet.it */
+
+struct ast_filestream {
+ void *reserved[AST_RESERVED_POINTERS];
+ /* Believe it or not, we must decode/recode to account for the
+ weird MS format */
+ /* This is what a filestream means to us */
+ FILE *f; /* Descriptor */
+ unsigned int lastts;
+ struct ast_frame fr; /* Frame information */
+ char waste[AST_FRIENDLY_OFFSET]; /* Buffer for sending frames, etc */
+ char empty; /* Empty character */
+ unsigned char h264[4096]; /* Two Real h264 Frames */
+};
+
+
+AST_MUTEX_DEFINE_STATIC(h264_lock);
+static int glistcnt = 0;
+
+static char *name = "h264";
+static char *desc = "Raw h264 data";
+static char *exts = "h264";
+
+static struct ast_filestream *h264_open(FILE *f)
+{
+ /* We don't have any header to read or anything really, but
+ if we did, it would go here. We also might want to check
+ and be sure it's a valid file. */
+ struct ast_filestream *tmp;
+ unsigned int ts;
+ int res;
+ if ((res = fread(&ts, 1, sizeof(ts), f)) < sizeof(ts)) {
+ ast_log(LOG_WARNING, "Empty file!\n");
+ return NULL;
+ }
+
+ if ((tmp = malloc(sizeof(struct ast_filestream)))) {
+ memset(tmp, 0, sizeof(struct ast_filestream));
+ if (ast_mutex_lock(&h264_lock)) {
+ ast_log(LOG_WARNING, "Unable to lock h264 list\n");
+ free(tmp);
+ return NULL;
+ }
+ tmp->f = f;
+ tmp->fr.data = tmp->h264;
+ tmp->fr.frametype = AST_FRAME_VIDEO;
+ tmp->fr.subclass = AST_FORMAT_H264;
+ /* datalen will vary for each frame */
+ tmp->fr.src = name;
+ tmp->fr.mallocd = 0;
+ glistcnt++;
+ ast_mutex_unlock(&h264_lock);
+ ast_update_use_count();
+ }
+ return tmp;
+}
+
+static struct ast_filestream *h264_rewrite(FILE *f, const char *comment)
+{
+ /* We don't have any header to read or anything really, but
+ if we did, it would go here. We also might want to check
+ and be sure it's a valid file. */
+ struct ast_filestream *tmp;
+ if ((tmp = malloc(sizeof(struct ast_filestream)))) {
+ memset(tmp, 0, sizeof(struct ast_filestream));
+ if (ast_mutex_lock(&h264_lock)) {
+ ast_log(LOG_WARNING, "Unable to lock h264 list\n");
+ free(tmp);
+ return NULL;
+ }
+ tmp->f = f;
+ glistcnt++;
+ ast_mutex_unlock(&h264_lock);
+ ast_update_use_count();
+ } else
+ ast_log(LOG_WARNING, "Out of memory\n");
+ return tmp;
+}
+
+static void h264_close(struct ast_filestream *s)
+{
+ if (ast_mutex_lock(&h264_lock)) {
+ ast_log(LOG_WARNING, "Unable to lock h264 list\n");
+ return;
+ }
+ glistcnt--;
+ ast_mutex_unlock(&h264_lock);
+ ast_update_use_count();
+ fclose(s->f);
+ free(s);
+ s = NULL;
+}
+
+static struct ast_frame *h264_read(struct ast_filestream *s, int *whennext)
+{
+ int res;
+ int mark=0;
+ unsigned short len;
+ unsigned int ts;
+ /* Send a frame from the file to the appropriate channel */
+ s->fr.frametype = AST_FRAME_VIDEO;
+ s->fr.subclass = AST_FORMAT_H264;
+ s->fr.offset = AST_FRIENDLY_OFFSET;
+ s->fr.mallocd = 0;
+ s->fr.data = s->h264;
+ if ((res = fread(&len, 1, sizeof(len), s->f)) < 1) {
+ return NULL;
+ }
+ len = ntohs(len);
+ if (len & 0x8000) {
+ mark = 1;
+ }
+ len &= 0x7fff;
+ if (len > sizeof(s->h264)) {
+ ast_log(LOG_WARNING, "Length %d is too long\n", len);
+ }
+ if ((res = fread(s->h264, 1, len, s->f)) != len) {
+ if (res)
+ ast_log(LOG_WARNING, "Short read (%d of %d) (%s)!\n", res, len, strerror(errno));
+ return NULL;
+ }
+ s->fr.samples = s->lastts;
+ s->fr.datalen = len;
+ s->fr.subclass |= mark;
+ s->fr.delivery.tv_sec = 0;
+ s->fr.delivery.tv_usec = 0;
+ if ((res = fread(&ts, 1, sizeof(ts), s->f)) == sizeof(ts)) {
+ s->lastts = ntohl(ts);
+ *whennext = s->lastts * 4/45;
+ } else
+ *whennext = 0;
+ return &s->fr;
+}
+
+static int h264_write(struct ast_filestream *fs, struct ast_frame *f)
+{
+ int res;
+ unsigned int ts;
+ unsigned short len;
+ int subclass;
+ int mark=0;
+ if (f->frametype != AST_FRAME_VIDEO) {
+ ast_log(LOG_WARNING, "Asked to write non-video frame!\n");
+ return -1;
+ }
+ subclass = f->subclass;
+ if (subclass & 0x1)
+ mark=0x8000;
+ subclass &= ~0x1;
+ if (subclass != AST_FORMAT_H264) {
+ ast_log(LOG_WARNING, "Asked to write non-h264 frame (%d)!\n", f->subclass);
+ return -1;
+ }
+ ts = htonl(f->samples);
+ if ((res = fwrite(&ts, 1, sizeof(ts), fs->f)) != sizeof(ts)) {
+ ast_log(LOG_WARNING, "Bad write (%d/4): %s\n", res, strerror(errno));
+ return -1;
+ }
+ len = htons(f->datalen | mark);
+ if ((res = fwrite(&len, 1, sizeof(len), fs->f)) != sizeof(len)) {
+ ast_log(LOG_WARNING, "Bad write (%d/2): %s\n", res, strerror(errno));
+ return -1;
+ }
+ if ((res = fwrite(f->data, 1, f->datalen, fs->f)) != f->datalen) {
+ ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+static char *h264_getcomment(struct ast_filestream *s)
+{
+ return NULL;
+}
+
+static int h264_seek(struct ast_filestream *fs, long sample_offset, int whence)
+{
+ /* No way Jose */
+ return -1;
+}
+
+static int h264_trunc(struct ast_filestream *fs)
+{
+ /* Truncate file to current length */
+ if (ftruncate(fileno(fs->f), ftell(fs->f)) < 0)
+ return -1;
+ return 0;
+}
+
+static long h264_tell(struct ast_filestream *fs)
+{
+ /* XXX This is totally bogus XXX */
+ off_t offset;
+ offset = ftell(fs->f);
+ return (offset/20)*160;
+}
+
+int load_module()
+{
+ return ast_format_register(name, exts, AST_FORMAT_H264,
+ h264_open,
+ h264_rewrite,
+ h264_write,
+ h264_seek,
+ h264_trunc,
+ h264_tell,
+ h264_read,
+ h264_close,
+ h264_getcomment);
+
+
+}
+
+int unload_module()
+{
+ return ast_format_unregister(name);
+}
+
+int usecount()
+{
+ return glistcnt;
+}
+
+char *description()
+{
+ return desc;
+}
+
+
+char *key()
+{
+ return ASTERISK_GPL_KEY;
+}
Added: team/russell/codetest/funcs/func_base64.c
URL: http://svn.digium.com/view/asterisk/team/russell/codetest/funcs/func_base64.c?rev=8722&view=auto
==============================================================================
--- team/russell/codetest/funcs/func_base64.c (added)
+++ team/russell/codetest/funcs/func_base64.c Thu Jan 26 12:29:29 2006
@@ -1,0 +1,85 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2005, Digium, Inc.
+ * Copyright (C) 2005, Claude Patry
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Use the base64 as functions
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "asterisk.h"
+
+/* ASTERISK_FILE_VERSION(__FILE__, "Revision: 7221 ") */
+
+#include "asterisk/channel.h"
+#include "asterisk/pbx.h"
+#include "asterisk/logger.h"
+#include "asterisk/utils.h"
+#include "asterisk/app.h"
+
+static char *builtin_function_base64_encode(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
+{
+ int res = 0;
+
+ if (ast_strlen_zero(data) ) {
+ ast_log(LOG_WARNING, "Syntax: BASE64_ENCODE(<data>) - missing argument!\n");
+ return NULL;
+ }
+
+ ast_log(LOG_DEBUG, "data=%s\n",data);
+ res = ast_base64encode(buf, data, strlen(data), len);
+ ast_log(LOG_DEBUG, "res=%d\n", res);
+ return buf;
+}
+
+static char *builtin_function_base64_decode(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
+{
+ if (ast_strlen_zero(data) ) {
+ ast_log(LOG_WARNING, "Syntax: BASE64_DECODE(<base_64 string>) - missing argument!\n");
+ return NULL;
+ }
+
+ ast_log(LOG_DEBUG, "data=%s\n", data);
+ ast_base64decode(buf, data, len);
+ return buf;
+}
+
+#ifndef BUILTIN_FUNC
+static
+#endif
+struct ast_custom_function base64_encode_function = {
+ .name = "BASE64_ENCODE",
+ .synopsis = "Encode a string in base64",
+ .desc = "Returns the base64 string\n",
+ .syntax = "BASE64_ENCODE(<string>)",
+ .read = builtin_function_base64_encode,
+};
+
+#ifndef BUILTIN_FUNC
+static
+#endif
+struct ast_custom_function base64_decode_function = {
+ .name = "BASE64_DECODE",
+ .synopsis = "Decode a base64 string",
+ .desc = "Returns the plain text string\n",
+ .syntax = "BASE64_DECODE(<base64_string>)",
+ .read = builtin_function_base64_decode,
+};
Modified: team/russell/codetest/include/asterisk/codetest.h
URL: http://svn.digium.com/view/asterisk/team/russell/codetest/include/asterisk/codetest.h?rev=8722&r1=8721&r2=8722&view=diff
==============================================================================
--- team/russell/codetest/include/asterisk/codetest.h (original)
+++ team/russell/codetest/include/asterisk/codetest.h Thu Jan 26 12:29:29 2006
@@ -41,7 +41,7 @@
/*! The name of the test */
const char *testname;
/*! The codetest callback function */
- int (*codetest)(int fd, int argc, char *argv[]);
+ int (*codetest)(int fd, int argc, char * const argv[]);
/*! For linking, used only in codetest.c */
AST_LIST_ENTRY(ast_codetest) list;
};
Added: team/russell/codetest/include/asterisk/stringfields.h
URL: http://svn.digium.com/view/asterisk/team/russell/codetest/include/asterisk/stringfields.h?rev=8722&view=auto
==============================================================================
--- team/russell/codetest/include/asterisk/stringfields.h (added)
+++ team/russell/codetest/include/asterisk/stringfields.h Thu Jan 26 12:29:29 2006
@@ -1,0 +1,308 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2006, Digium, Inc.
+ *
+ * Kevin P. Fleming <kpfleming at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ \brief String fields in structures
+
+ This file contains objects and macros used to manage string
+ fields in structures without requiring them to be allocated
+ as fixed-size buffers or requiring individual allocations for
+ for each field.
+
+ Using this functionality is quite simple... an example structure
+ with three fields is defined like this:
+
+ \code
+ struct sample_fields {
+ int x1;
+ AST_DECLARE_STRING_FIELDS(
+ AST_STRING_FIELD(name);
+ AST_STRING_FIELD(address);
+ AST_STRING_FIELD(password);
+ );
+ long x2;
+ };
+ \endcode
+
+ When an instance of this structure is allocated, the fields
+ (and the pool of storage for them) must be initialized:
+
+ \code
+ struct sample_fields *sample;
+
+ sample = calloc(1, sizeof(*sample));
+ if (sample) {
+ if (!ast_string_field_init(sample)) {
+ free(sample);
+ sample = NULL;
+ }
+ }
+
+ if (!sample) {
+ ...
+ }
+ \endcode
+
+ Fields will default to pointing to an empty string, and will
+ revert to that when ast_string_field_free() is called. This means
+ that a string field will \b never contain NULL.
+
+ Using the fields is much like using regular 'char *' fields
+ in the structure, except that writing into them must be done
+ using wrapper macros defined in this file.
+
+ Storing simple values into fields can be done using ast_string_field_set();
+ more complex values (using printf-style format strings) can be stored
+ using ast_string_field_build().
+
+ When the structure instance is no longer needed, the fields
+ and their storage pool must be freed:
+
+ \code
+ ast_string_field_free_all(sample);
+ free(sample);
+ \endcode
+*/
+
+#ifndef _ASTERISK_STRINGFIELDS_H
+#define _ASTERISK_STRINGFIELDS_H
+
+#include <string.h>
+#include <stdarg.h>
+#include <stddef.h>
+
+#include "asterisk/inline_api.h"
+#include "asterisk/compiler.h"
+#include "asterisk/compat.h"
+
+/*!
+ \internal
+ \brief An opaque type for managed string fields in structures
+
+ Don't declare instances of this type directly; use the AST_STRING_FIELD()
+ macro instead.
+*/
+typedef const char * ast_string_field;
+
+/*!
+ \internal
+ \brief A constant empty string used for fields that have no other value
+*/
+extern const char *__ast_string_field_empty;
+
+/*!
+ \internal
+ \brief Structure used to hold a pool of space for string fields
+*/
+struct ast_string_field_pool {
+ struct ast_string_field_pool *prev; /*!< pointer to the previous pool, if any */
+ char base[0]; /*!< storage space for the fields */
+};
+
+/*!
+ \internal
+ \brief Structure used to manage the storage for a set of string fields
+*/
+struct ast_string_field_mgr {
+ struct ast_string_field_pool *pool; /*!< the address of the pool's structure */
+ size_t size; /*!< the total size of the current pool */
+ size_t space; /*!< the space available in the current pool */
+ size_t used; /*!< the space used in the current pool */
+};
+
+/*!
+ \internal
+ \brief Initialize a field pool manager and fields
+ \param mgr Pointer to the pool manager structure
+ \param size Amount of storage to allocate
+ \param fields Pointer to the first entry of the field array
+ \param num_fields Number of fields in the array
+ \return 0 on failure, non-zero on success
+*/
+int __ast_string_field_init(struct ast_string_field_mgr *mgr, size_t size,
+ ast_string_field *fields, int num_fields);
+
+/*!
+ \internal
+ \brief Allocate space for a field
+ \param mgr Pointer to the pool manager structure
+ \param needed Amount of space needed for this field
+ \param fields Pointer to the first entry of the field array
+ \param num_fields Number of fields in the array
+ \return NULL on failure, an address for the field on success
+
+ This function will allocate the requested amount of space from
+ the field pool. If the requested amount of space is not available,
+ an additional pool will be allocated.
+*/
+ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr, size_t needed,
+ ast_string_field *fields, int num_fields);
+
+/*!
+ \internal
+ \brief Set a field to a complex (built) value
+ \param mgr Pointer to the pool manager structure
+ \param fields Pointer to the first entry of the field array
+ \param num_fields Number of fields in the array
+ \param index Index position of the field within the structure
+ \param format printf-style format string
+ \return nothing
+*/
+void __ast_string_field_index_build(struct ast_string_field_mgr *mgr,
+ ast_string_field *fields, int num_fields,
+ int index, const char *format, ...);
+
+/*!
+ The default amount of storage to be allocated for a field pool.
+*/
+#define AST_STRING_FIELD_DEFAULT_POOL 512
+
+/*!
+ \brief Declare a string field
+ \param name The field name
+*/
+#define AST_STRING_FIELD(name) const ast_string_field name;
+
+/*!
+ \brief Declare the fields needed in a structure
+ \param field_list The list of fields to declare, using AST_STRING_FIELD() for each one
+*/
+#define AST_DECLARE_STRING_FIELDS(field_list) \
+ ast_string_field __begin_field[0]; \
+ field_list \
+ ast_string_field __end_field[0]; \
+ struct ast_string_field_mgr __field_mgr;
+
+/*!
+ \brief Get the number of string fields in a structure
+ \param x Pointer to a structure containing fields
+ \return the number of fields in the structure's definition
+*/
+#define ast_string_field_count(x) \
+ (offsetof(typeof(*x), __end_field) - offsetof(typeof(*x), __begin_field)) / sizeof(ast_string_field)
+
+/*!
+ \brief Get the index of a field in a structure
+ \param x Pointer to a structure containing fields
+ \param field Name of the field to locate
+ \return the position (index) of the field within the structure's
+ array of fields
+*/
+#define ast_string_field_index(x, field) \
+ (offsetof(typeof(*x), field) - offsetof(typeof(*x), __begin_field)) / sizeof(ast_string_field)
+
+/*!
+ \brief Initialize a field pool and fields
+ \param x Pointer to a structure containing fields
+ \return 0 on failure, non-zero on success
+*/
+#define ast_string_field_init(x) \
+ __ast_string_field_init(&x->__field_mgr, AST_STRING_FIELD_DEFAULT_POOL, &x->__begin_field[0], ast_string_field_count(x))
+
+/*!
+ \brief Set a field to a simple string value
+ \param x Pointer to a structure containing fields
+ \param index Index position of the field within the structure
+ \param data String value to be copied into the field
+ \return nothing
+*/
+#define ast_string_field_index_set(x, index, data) do { \
+ if ((x->__begin_field[index] = __ast_string_field_alloc_space(&x->__field_mgr, strlen(data) + 1, &x->__begin_field[0], ast_string_field_count(x)))) \
+ strcpy((char *) x->__begin_field[index], data); \
+ } while (0)
+
+/*!
+ \brief Set a field to a simple string value
+ \param x Pointer to a structure containing fields
+ \param field Name of the field to set
+ \param data String value to be copied into the field
+ \return nothing
+*/
+#define ast_string_field_set(x, field, data) \
+ ast_string_field_index_set(x, ast_string_field_index(x, field), data)
+
+/*!
+ \brief Set a field to a complex (built) value
+ \param x Pointer to a structure containing fields
+ \param index Index position of the field within the structure
+ \param fmt printf-style format string
+ \param args Arguments for format string
+ \return nothing
+*/
+#define ast_string_field_index_build(x, index, fmt, args...) \
+ __ast_string_field_index_build(&x->__field_mgr, &x->__begin_field[0], ast_string_field_count(x), index, fmt, args)
+
+/*!
+ \brief Set a field to a complex (built) value
+ \param x Pointer to a structure containing fields
+ \param field Name of the field to set
+ \param fmt printf-style format string
+ \param args Arguments for format string
+ \return nothing
+*/
+#define ast_string_field_build(x, field, fmt, args...) \
+ ast_string_field_index_build(x, ast_string_field_index(x, field), fmt, args)
+
+/*!
+ \brief Free a field's value.
+ \param x Pointer to a structure containing fields
+ \param index Index position of the field within the structure
+ \return nothing
+
+ \note Because of the storage pool used, the memory
+ occupied by the field's value is \b not recovered; the field
+ pointer is just changed to point to an empty string.
+*/
+#define ast_string_field_index_free(x, index) do { \
+ x->__begin_field[index] = __ast_string_field_empty; \
+ } while(0)
+
+/*!
+ \brief Free a field's value.
+ \param x Pointer to a structure containing fields
+ \param field Name of the field to free
+ \return nothing
+
+ \note Because of the storage pool used, the memory
+ occupied by the field's value is \b not recovered; the field
+ pointer is just changed to point to an empty string.
+*/
+#define ast_string_field_free(x, field) \
+ ast_string_field_index_free(x, ast_string_field_index(x, field))
+
+/*!
+ \brief Free all fields (and the storage pool) in a structure
+ \param x Pointer to a structure containing fields
+ \return nothing
+
+ After calling this macro, fields can no longer be accessed in
+ structure; it should only be called immediately before freeing
+ the structure itself.
+*/
+#define ast_string_field_free_all(x) do { \
+ int index; \
+ struct ast_string_field_pool *this, *prev; \
+ for (index = 0; index < ast_string_field_count(x); index ++) \
+ ast_string_field_index_free(x, index); \
+ for (this = x->__field_mgr.pool; this; this = prev) { \
+ prev = this->prev; \
+ free(this); \
+ } \
+ } while(0)
+
+#endif /* _ASTERISK_STRINGFIELDS_H */
Added: team/russell/codetest/udptl.c
URL: http://svn.digium.com/view/asterisk/team/russell/codetest/udptl.c?rev=8722&view=auto
==============================================================================
--- team/russell/codetest/udptl.c (added)
+++ team/russell/codetest/udptl.c Thu Jan 26 12:29:29 2006
@@ -1,0 +1,1260 @@
+/*
+ * Asterisk -- A telephony toolkit for Linux.
+ *
+ * UDPTL support for T.38
+ *
+ * Copyright (C) 2005, Steve Underwood, partly based on RTP code which is
+ * Copyright (C) 1999-2006, Digium, Inc.
+ *
+ * Steve Underwood <steveu at coppice.org>
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License
+ *
+ * This version is disclaimed to DIGIUM for inclusion in the Asterisk project.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 8038 $")
+
+#include "asterisk/udptl.h"
+#include "asterisk/frame.h"
+#include "asterisk/logger.h"
+#include "asterisk/options.h"
+#include "asterisk/channel.h"
+#include "asterisk/acl.h"
+#include "asterisk/channel.h"
+#include "asterisk/config.h"
+#include "asterisk/lock.h"
+#include "asterisk/utils.h"
+#include "asterisk/cli.h"
+#include "asterisk/unaligned.h"
+#include "asterisk/utils.h"
+
+#define UDPTL_MTU 1200
+
+#if !defined(FALSE)
+#define FALSE 0
+#endif
+#if !defined(TRUE)
+#define TRUE (!FALSE)
+#endif
+
+static int udptlstart = 0;
+static int udptlend = 0;
+static int udptldebug = 0; /* Are we debugging? */
+static struct sockaddr_in udptldebugaddr; /* Debug packets to/from this host */
+#ifdef SO_NO_CHECK
+static int nochecksums = 0;
+#endif
+static int udptlfectype = 0;
+static int udptlfecentries = 0;
+static int udptlfecspan = 0;
+static int udptlmaxdatagram = 0;
+
+#define LOCAL_FAX_MAX_DATAGRAM 400
+#define MAX_FEC_ENTRIES 5
+#define MAX_FEC_SPAN 5
+
+#define UDPTL_BUF_MASK 15
+
+typedef struct {
+ int buf_len;
+ uint8_t buf[LOCAL_FAX_MAX_DATAGRAM];
+} udptl_fec_tx_buffer_t;
+
+typedef struct {
+ int buf_len;
+ uint8_t buf[LOCAL_FAX_MAX_DATAGRAM];
+ int fec_len[MAX_FEC_ENTRIES];
+ uint8_t fec[MAX_FEC_ENTRIES][LOCAL_FAX_MAX_DATAGRAM];
+ int fec_span;
+ int fec_entries;
+} udptl_fec_rx_buffer_t;
+
+struct ast_udptl {
+ int fd;
+ char resp;
+ struct ast_frame f[16];
+ unsigned char rawdata[8192 + AST_FRIENDLY_OFFSET];
+ unsigned int lasteventseqn;
+ int nat;
+ int flags;
+ struct sockaddr_in us;
+ struct sockaddr_in them;
+ int *ioid;
+ uint16_t seqno;
+ struct sched_context *sched;
+ struct io_context *io;
+ void *data;
+ ast_udptl_callback callback;
+ int udptl_offered_from_local;
+
+ /*! This option indicates the error correction scheme used in transmitted UDPTL
+ packets. */
+ int error_correction_scheme;
+
+ /*! This option indicates the number of error correction entries transmitted in
+ UDPTL packets. */
+ int error_correction_entries;
+
+ /*! This option indicates the span of the error correction entries in transmitted
+ UDPTL packets (FEC only). */
+ int error_correction_span;
+
+ /*! This option indicates the maximum size of a UDPTL packet that can be accepted by
+ the remote device. */
+ int far_max_datagram_size;
+
+ /*! This option indicates the maximum size of a UDPTL packet that we are prepared to
+ accept. */
+ int local_max_datagram_size;
+
+ int verbose;
+
+ struct sockaddr_in far;
+
+ int tx_seq_no;
+ int rx_seq_no;
+ int rx_expected_seq_no;
+
+ udptl_fec_tx_buffer_t tx[UDPTL_BUF_MASK + 1];
+ udptl_fec_rx_buffer_t rx[UDPTL_BUF_MASK + 1];
+};
+
+static struct ast_udptl_protocol *protos = NULL;
+
+static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, int len);
+static int udptl_build_packet(struct ast_udptl *s, uint8_t *buf, uint8_t *ifp, int ifp_len);
+
+static inline int udptl_debug_test_addr(struct sockaddr_in *addr)
+{
+ if (udptldebug == 0)
+ return 0;
+ if (udptldebugaddr.sin_addr.s_addr) {
+ if (((ntohs(udptldebugaddr.sin_port) != 0)
+ && (udptldebugaddr.sin_port != addr->sin_port))
+ || (udptldebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
+ return 0;
+ }
+ return 1;
+}
+
+static int decode_length(uint8_t *buf, int limit, int *len, int *pvalue)
+{
+ if ((buf[*len] & 0x80) == 0) {
+ if (*len >= limit)
+ return -1;
+ *pvalue = buf[*len];
+ (*len)++;
+ return 0;
+ }
+ if ((buf[*len] & 0x40) == 0) {
+ if (*len >= limit - 1)
+ return -1;
+ *pvalue = (buf[*len] & 0x3F) << 8;
+ (*len)++;
+ *pvalue |= buf[*len];
+ (*len)++;
+ return 0;
+ }
+ if (*len >= limit)
+ return -1;
+ *pvalue = (buf[*len] & 0x3F) << 14;
+ (*len)++;
+ /* Indicate we have a fragment */
+ return 1;
+}
+/*- End of function --------------------------------------------------------*/
+
+static int decode_open_type(uint8_t *buf, int limit, int *len, const uint8_t **p_object, int *p_num_octets)
+{
+ int octet_cnt;
+ int octet_idx;
+ int stat;
+ int i;
+ const uint8_t **pbuf;
+
+ for (octet_idx = 0, *p_num_octets = 0; ; octet_idx += octet_cnt) {
+ if ((stat = decode_length(buf, limit, len, &octet_cnt)) < 0)
+ return -1;
+ if (octet_cnt > 0) {
+ *p_num_octets += octet_cnt;
+
+ pbuf = &p_object[octet_idx];
+ i = 0;
+ /* Make sure the buffer contains at least the number of bits requested */
+ if ((*len + octet_cnt) > limit)
+ return -1;
+
+ *pbuf = &buf[*len];
+ *len += octet_cnt;
+ }
+ if (stat == 0)
+ break;
+ }
+ return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+static int encode_length(uint8_t *buf, int *len, int value)
+{
+ int multiplier;
+
+ if (value < 0x80) {
+ /* 1 octet */
+ buf[*len] = value;
+ (*len)++;
+ return value;
+ }
+ if (value < 0x4000) {
+ /* 2 octets */
+ /* Set the first bit of the first octet */
+ buf[*len] = ((0x8000 | value) >> 8) & 0xFF;
+ (*len)++;
+ buf[*len] = value & 0xFF;
+ (*len)++;
+ return value;
+ }
+ /* Fragmentation */
+ multiplier = (value < 0x10000) ? (value >> 14) : 4;
+ /* Set the first 2 bits of the octet */
+ buf[*len] = 0xC0 | multiplier;
+ (*len)++;
+ return multiplier << 14;
+}
+/*- End of function --------------------------------------------------------*/
+
+static int encode_open_type(uint8_t *buf, int *len, const uint8_t *data, int num_octets)
+{
+ int enclen;
+ int octet_idx;
+ uint8_t zero_byte;
+
+ /* If open type is of zero length, add a single zero byte (10.1) */
+ if (num_octets == 0) {
+ zero_byte = 0;
+ data = &zero_byte;
+ num_octets = 1;
+ }
+ /* Encode the open type */
+ for (octet_idx = 0; ; num_octets -= enclen, octet_idx += enclen) {
+ if ((enclen = encode_length(buf, len, num_octets)) < 0)
+ return -1;
+ if (enclen > 0) {
+ memcpy(&buf[*len], &data[octet_idx], enclen);
+ *len += enclen;
+ }
+ if (enclen >= num_octets)
+ break;
+ }
+
+ return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, int len)
+{
+ int stat;
+ int stat2;
+ int i;
+ int j;
+ int k;
+ int l;
+ int m;
+ int x;
+ int limit;
+ int which;
+ int ptr;
+ int count;
+ int total_count;
+ int seq_no;
+ const uint8_t *ifp;
+ const uint8_t *data;
+ int ifp_len;
+ int repaired[16];
+ const uint8_t *bufs[16];
+ int lengths[16];
+ int span;
+ int entries;
+ int ifp_no;
+
+ ptr = 0;
+ ifp_no = 0;
+ s->f[0].prev = NULL;
+ s->f[0].next = NULL;
+
+ /* Decode seq_number */
+ if (ptr + 2 > len)
+ return -1;
+ seq_no = (buf[0] << 8) | buf[1];
+ ptr += 2;
+
+ /* Break out the primary packet */
+ if ((stat = decode_open_type(buf, len, &ptr, &ifp, &ifp_len)) != 0)
+ return -1;
+ /* Decode error_recovery */
+ if (ptr + 1 > len)
+ return -1;
+ if ((buf[ptr++] & 0x80) == 0) {
+ /* Secondary packet mode for error recovery */
+ if (seq_no > s->rx_seq_no) {
+ /* We received a later packet than we expected, so we need to check if we can fill in the gap from the
+ secondary packets. */
+ total_count = 0;
+ do {
+ if ((stat2 = decode_length(buf, len, &ptr, &count)) < 0)
+ return -1;
+ for (i = 0; i < count; i++) {
+ if ((stat = decode_open_type(buf, len, &ptr, &bufs[total_count + i], &lengths[total_count + i])) != 0)
+ return -1;
+ }
+ total_count += count;
+ }
+ while (stat2 > 0);
+ /* Step through in reverse order, so we go oldest to newest */
+ for (i = total_count; i > 0; i--) {
+ if (seq_no - i >= s->rx_seq_no) {
+ /* This one wasn't seen before */
+ /* Decode the secondary IFP packet */
+ //fprintf(stderr, "Secondary %d, len %d\n", seq_no - i, lengths[i - 1]);
+ s->f[ifp_no].frametype = AST_FRAME_MODEM;
+ s->f[ifp_no].subclass = AST_MODEM_T38;
+
+ s->f[ifp_no].mallocd = 0;
+ //s->f[ifp_no].???seq_no = seq_no - i;
+ s->f[ifp_no].datalen = lengths[i - 1];
+ s->f[ifp_no].data = (uint8_t *) bufs[i - 1];
+ s->f[ifp_no].offset = 0;
+ s->f[ifp_no].src = "UDPTL";
+ if (ifp_no > 0) {
+ s->f[ifp_no].prev = &s->f[ifp_no - 1];
+ s->f[ifp_no - 1].next = &s->f[ifp_no];
+ }
+ s->f[ifp_no].next = NULL;
+ ifp_no++;
+ }
+ }
+ }
+ /* If packets are received out of sequence, we may have already processed this packet from the error
+ recovery information in a packet already received. */
+ if (seq_no >= s->rx_seq_no) {
+ /* Decode the primary IFP packet */
+ s->f[ifp_no].frametype = AST_FRAME_MODEM;
+ s->f[ifp_no].subclass = AST_MODEM_T38;
+
+ s->f[ifp_no].mallocd = 0;
+ //s->f[ifp_no].???seq_no = seq_no;
+ s->f[ifp_no].datalen = ifp_len;
+ s->f[ifp_no].data = (uint8_t *) ifp;
+ s->f[ifp_no].offset = 0;
+ s->f[ifp_no].src = "UDPTL";
+ if (ifp_no > 0) {
+ s->f[ifp_no].prev = &s->f[ifp_no - 1];
+ s->f[ifp_no - 1].next = &s->f[ifp_no];
+ }
+ s->f[ifp_no].next = NULL;
+ }
+ }
+ else
+ {
+ /* FEC mode for error recovery */
+ /* Our buffers cannot tolerate overlength IFP packets in FEC mode */
+ if (ifp_len > LOCAL_FAX_MAX_DATAGRAM)
+ return -1;
+ /* Update any missed slots in the buffer */
+ for ( ; seq_no > s->rx_seq_no; s->rx_seq_no++) {
+ x = s->rx_seq_no & UDPTL_BUF_MASK;
+ s->rx[x].buf_len = -1;
+ s->rx[x].fec_len[0] = 0;
+ s->rx[x].fec_span = 0;
+ s->rx[x].fec_entries = 0;
+ }
+
+ x = seq_no & UDPTL_BUF_MASK;
+
+ memset(repaired, 0, sizeof(repaired));
+
+ /* Save the new IFP packet */
+ memcpy(s->rx[x].buf, ifp, ifp_len);
+ s->rx[x].buf_len = ifp_len;
+ repaired[x] = TRUE;
+
+ /* Decode the FEC packets */
+ /* The span is defined as an unconstrained integer, but will never be more
+ than a small value. */
+ if (ptr + 2 > len)
+ return -1;
+ if (buf[ptr++] != 1)
+ return -1;
+ span = buf[ptr++];
+ s->rx[x].fec_span = span;
+
[... 855 lines stripped ...]
More information about the asterisk-commits
mailing list