Skip to content
Snippets Groups Projects
iax2-parser.c 37.1 KiB
Newer Older
 * Asterisk -- An open source telephony toolkit.
 * Copyright (C) 1999 - 2005, Digium, Inc.
 * Mark Spencer <markster@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.
 */

 * \brief Implementation of Inter-Asterisk eXchange Protocol, v 2
 *
 * \author Mark Spencer <markster@digium.com> 
/*** MODULEINFO
	<support_level>core</support_level>
 ***/

#include "asterisk.h"

ASTERISK_FILE_VERSION(__FILE__, "$Revision$")

#include <sys/socket.h>
#include <netinet/in.h>
Kevin P. Fleming's avatar
Kevin P. Fleming committed
#include <arpa/inet.h>
#include "asterisk/frame.h"
#include "asterisk/utils.h"
#include "asterisk/unaligned.h"
#include "asterisk/config.h"
#include "asterisk/threadstorage.h"
#include "iax2.h"
#include "iax2-parser.h"
#include "iax2-provision.h"
Mark Spencer's avatar
Mark Spencer committed
static int frames = 0;
static int iframes = 0;
static int oframes = 0;

#if !defined(LOW_MEMORY)
static void frame_cache_cleanup(void *data);

/*! \brief A per-thread cache of iax_frame structures */
AST_THREADSTORAGE_CUSTOM(frame_cache, NULL, frame_cache_cleanup);

/*! \brief This is just so iax_frames, a list head struct for holding a list of
 *  iax_frame structures, is defined. */
AST_LIST_HEAD_NOLOCK(iax_frame_list, iax_frame);

struct iax_frames {
	struct iax_frame_list list;
	size_t size;
};

#define FRAME_CACHE_MAX_SIZE	20
static void internaloutput(const char *str)
{
James Golovich's avatar
James Golovich committed
	fputs(str, stdout);
}

static void internalerror(const char *str)
{
	fprintf(stderr, "WARNING: %s", str);
}

static void (*outputf)(const char *str) = internaloutput;
static void (*errorf)(const char *str) = internalerror;

static void dump_addr(char *output, int maxlen, void *value, int len)
{
	struct sockaddr_in sin;
	if (len == (int)sizeof(sin)) {
		memcpy(&sin, value, len);
		snprintf(output, maxlen, "IPV4 %s:%d", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
	} else {
		ast_copy_string(output, "Invalid Address", maxlen);
static void dump_string_hex(char *output, int maxlen, void *value, int len)
{
	int i = 0;

	while (len-- && (i + 1) * 4 < maxlen) {
		sprintf(output + (4 * i), "\\x%2.2x", *((unsigned char *)value + i));
		i++;
	}
}

static void dump_string(char *output, int maxlen, void *value, int len)
{
	maxlen--;
	if (maxlen > len)
		maxlen = len;
	output[maxlen] = '\0';
}

static void dump_prefs(char *output, int maxlen, void *value, int len)
{
	struct ast_codec_pref pref;
	int total_len = 0;

	maxlen--;
	total_len = maxlen;

	if (maxlen > len)
		maxlen = len;

	output[maxlen] = '\0';
	
	ast_codec_pref_convert(&pref, output, total_len, 0);
	memset(output,0,total_len);
	ast_codec_pref_string(&pref, output, total_len);
}

static void dump_int(char *output, int maxlen, void *value, int len)
{
	if (len == (int)sizeof(unsigned int))
		snprintf(output, maxlen, "%lu", (unsigned long)ntohl(get_unaligned_uint32(value)));
		ast_copy_string(output, "Invalid INT", maxlen);	
}

static void dump_short(char *output, int maxlen, void *value, int len)
{
	if (len == (int)sizeof(unsigned short))
		snprintf(output, maxlen, "%d", ntohs(get_unaligned_uint16(value)));
		ast_copy_string(output, "Invalid SHORT", maxlen);
}

static void dump_byte(char *output, int maxlen, void *value, int len)
{
	if (len == (int)sizeof(unsigned char))
		snprintf(output, maxlen, "%d", *((unsigned char *)value));
		ast_copy_string(output, "Invalid BYTE", maxlen);
}

static void dump_datetime(char *output, int maxlen, void *value, int len)
{
	unsigned long val = (unsigned long) ntohl(get_unaligned_uint32(value));
	if (len == (int)sizeof(unsigned int)) {
		tm.tm_sec  = (val & 0x1f) << 1;
		tm.tm_min  = (val >> 5) & 0x3f;
		tm.tm_hour = (val >> 11) & 0x1f;
		tm.tm_mday = (val >> 16) & 0x1f;
		tm.tm_mon  = ((val >> 21) & 0x0f) - 1;
		tm.tm_year = ((val >> 25) & 0x7f) + 100;
		ast_strftime(output, maxlen, "%Y-%m-%d  %T", &tm); 
	} else
		ast_copy_string(output, "Invalid DATETIME format!", maxlen);
static void dump_ipaddr(char *output, int maxlen, void *value, int len)
{
	struct sockaddr_in sin;
	if (len == (int)sizeof(unsigned int)) {
		memcpy(&sin.sin_addr, value, len);
		snprintf(output, maxlen, "%s", ast_inet_ntoa(sin.sin_addr));
		ast_copy_string(output, "Invalid IPADDR", maxlen);
}


static void dump_prov_flags(char *output, int maxlen, void *value, int len)
{
	char buf[256] = "";
	if (len == (int)sizeof(unsigned int))
		snprintf(output, maxlen, "%lu (%s)", (unsigned long)ntohl(get_unaligned_uint32(value)),
			iax_provflags2str(buf, sizeof(buf), ntohl(get_unaligned_uint32(value))));
		ast_copy_string(output, "Invalid INT", maxlen);
Mark Spencer's avatar
Mark Spencer committed
static void dump_samprate(char *output, int maxlen, void *value, int len)
{
	char tmp[256]="";
	int sr;
	if (len == (int)sizeof(unsigned short)) {
		sr = ntohs(*((unsigned short *)value));
		if (sr & IAX_RATE_8KHZ)
Loading
Loading full blame...