[svn-commits] branch russell/codetest r8722 - in /team/russell/codetest: ./ apps/ channels/...

svn-commits at lists.digium.com svn-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 svn-commits mailing list