⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aststubs.c

📁 asterisk1.4.6版本下 7#信令驱动 源码
💻 C
字号:
/* aststubs.c - asterisk stubs
 * Copyright (C) 2007, Anders Baekgaard
 *
 * Author: Anders Baekgaard <ab@dicea.dk>
 * This work is included with chan_ss7, see copyright below.
 */

/*
 * This file is part of chan_ss7.
 *
 * chan_ss7 is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * chan_ss7 is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with chan_ss7; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */


#include <stdio.h>
#include <stdarg.h>
#include <malloc.h>
#include <pthread.h>

#define AST_API_MODULE
#include <asterisk/linkedlists.h>
#include <asterisk/time.h>
#include <asterisk/options.h>
#include <asterisk/utils.h>
#include "asterisk/abstract_jb.h"

#include "aststubs.h"

int option_debug;
struct ast_cli_entry;

int option_verbose;
int option_debug;
struct ast_flags ast_options;

char ast_config_AST_CONFIG_DIR[PATH_MAX];


#undef pthread_mutex_init
#undef pthread_mutex_lock
#undef pthread_mutex_unlock
#undef pthread_mutex_t
#undef ast_calloc
#define ast_mutex_init(m) pthread_mutex_init(m,0)
#define ast_mutex_lock pthread_mutex_lock
#define ast_mutex_unlock pthread_mutex_unlock
#define ast_mutex_t pthread_mutex_t
#define ast_calloc calloc

//define DEBUG(x) {if (option_debug) x;}
#define DEBUG(x)


int ast_safe_system(const char *s);
void ast_register_file_version(const char *file, const char *version);
void ast_unregister_file_version(const char *file);
void ast_cli_register_multiple(struct ast_cli_entry *e, int len);
void ast_cli(int fd, char *fmt, ...);

int ast_safe_system(const char *s)
{
  return -1;
}

void ast_register_file_version(const char *file, const char *version)
{
}

void ast_unregister_file_version(const char *file)
{
}

void ast_cli_register_multiple(struct ast_cli_entry *e, int len)
{
}

void ast_cli(int fd, char *fmt, ...)
{
}

void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
{
  va_list ap;
  char *l;
  char buff[1024];

  if ((level == __LOG_DEBUG) && !option_debug)
    return;
  switch (level) {
  case __LOG_DEBUG: l= "DEBUG"; break;
  case __LOG_EVENT: l= "EVENT"; break;
  case __LOG_NOTICE: l= "NOTICE"; break;
  case __LOG_WARNING: l= "WARNING"; break;
  case __LOG_ERROR: l= "ERROR"; break;
  default: l = "unknown";
  }
  sprintf(buff, "[%s] %s:%d %s %s", l, file, line, function, fmt);
  va_start(ap, fmt);
  vprintf(buff, ap);
  fflush(stdout);
}

void ast_verbose(const char *fmt, ...)
{
  va_list ap;
  va_start(ap, fmt);
  vprintf(fmt, ap);
  fflush(stdout);
}


#ifndef AST_LIST_INSERT_BEFORE_CURRENT
/* Asterisk 1.2.x */
#define AST_LIST_INSERT_BEFORE_CURRENT(head, elm, field) do {		\
	if (__list_prev) {						\
		(elm)->field.next = __list_prev->field.next;		\
		__list_prev->field.next = elm;				\
	} else {							\
		(elm)->field.next = (head)->first;			\
		(head)->first = (elm);					\
	}								\
	__new_prev = (elm);						\
} while (0)
#endif

struct sched {
	AST_LIST_ENTRY(sched) list;
	int id;                       /*!< ID number of event */
	struct timeval when;          /*!< Absolute time event should take place */
	int resched;                  /*!< When to reschedule */
	int variable;                 /*!< Use return value from callback to reschedule */
	void *data;                   /*!< Data */
	ast_sched_cb callback;        /*!< Callback */
};

struct sched_context {
	ast_mutex_t lock;
	unsigned int eventcnt;                  /*!< Number of events processed */
	unsigned int schedcnt;                  /*!< Number of outstanding schedule events */
	AST_LIST_HEAD_NOLOCK(, sched) schedq;   /*!< Schedule entry and main queue */

#ifdef SCHED_MAX_CACHE
	AST_LIST_HEAD_NOLOCK(, sched) schedc;   /*!< Cache of unused schedule structures and how many */
	unsigned int schedccnt;
#endif
};

#define ONE_MILLION	1000000
static struct timeval tvfix(struct timeval a)
{
	if (a.tv_usec >= ONE_MILLION) {
		ast_log(LOG_WARNING, "warning too large timestamp %ld.%ld\n",
			a.tv_sec, (long int) a.tv_usec);
		a.tv_sec += a.tv_usec / ONE_MILLION;
		a.tv_usec %= ONE_MILLION;
	} else if (a.tv_usec < 0) {
		ast_log(LOG_WARNING, "warning negative timestamp %ld.%ld\n",
			a.tv_sec, (long int) a.tv_usec);
		a.tv_usec = 0;
	}
	return a;
}

struct timeval ast_tvadd(struct timeval a, struct timeval b)
{
	/* consistency checks to guarantee usec in 0..999999 */
	a = tvfix(a);
	b = tvfix(b);
	a.tv_sec += b.tv_sec;
	a.tv_usec += b.tv_usec;
	if (a.tv_usec >= ONE_MILLION) {
		a.tv_sec++;
		a.tv_usec -= ONE_MILLION;
	}
	return a;
}

struct sched_context *mtp_sched_context_create(void)
{
	struct sched_context *tmp;

	if (!(tmp = ast_calloc(1, sizeof(*tmp))))
		return NULL;

	ast_mutex_init(&tmp->lock);
	tmp->eventcnt = 1;
	
	return tmp;
}

void mtp_sched_context_destroy(struct sched_context *con)
{
	struct sched *s;

	ast_mutex_lock(&con->lock);

#ifdef SCHED_MAX_CACHE
	/* Eliminate the cache */
	while ((s = AST_LIST_REMOVE_HEAD(&con->schedc, list)))
		free(s);
#endif

	/* And the queue */
	while ((s = AST_LIST_REMOVE_HEAD(&con->schedq, list)))
		free(s);
	
	/* And the context */
	ast_mutex_unlock(&con->lock);
	ast_mutex_destroy(&con->lock);
	free(con);
}

static struct sched *sched_alloc(struct sched_context *con)
{
	struct sched *tmp;

	/*
	 * We keep a small cache of schedule entries
	 * to minimize the number of necessary malloc()'s
	 */
#ifdef SCHED_MAX_CACHE
	if ((tmp = AST_LIST_REMOVE_HEAD(&con->schedc, list)))
		con->schedccnt--;
	else
#endif
		tmp = ast_calloc(1, sizeof(*tmp));

	return tmp;
}

static void sched_release(struct sched_context *con, struct sched *tmp)
{
	/*
	 * Add to the cache, or just free() if we
	 * already have too many cache entries
	 */

#ifdef SCHED_MAX_CACHE	 
	if (con->schedccnt < SCHED_MAX_CACHE) {
		AST_LIST_INSERT_HEAD(&con->schedc, tmp, list);
		con->schedccnt++;
	} else
#endif
		free(tmp);
}

int mtp_sched_wait(struct sched_context *con)
{
	int ms;

	DEBUG(ast_log(LOG_DEBUG, "ast_sched_wait()\n"));

	ast_mutex_lock(&con->lock);
	if (AST_LIST_EMPTY(&con->schedq)) {
		ms = -1;
	} else {
		ms = ast_tvdiff_ms(AST_LIST_FIRST(&con->schedq)->when, ast_tvnow());
		if (ms < 0)
			ms = 0;
	}
	ast_mutex_unlock(&con->lock);

	return ms;
}


static void schedule(struct sched_context *con, struct sched *s)
{
	 
	struct sched *cur = NULL;
	
	AST_LIST_TRAVERSE_SAFE_BEGIN(&con->schedq, cur, list) {
		if (ast_tvcmp(s->when, cur->when) == -1) {
			AST_LIST_INSERT_BEFORE_CURRENT(&con->schedq, s, list);
			break;
		}
	}
	AST_LIST_TRAVERSE_SAFE_END
	if (!cur)
		AST_LIST_INSERT_TAIL(&con->schedq, s, list);
	
	con->schedcnt++;
}

static int sched_settime(struct timeval *tv, int when)
{
	struct timeval now = ast_tvnow();

	/*ast_log(LOG_DEBUG, "TV -> %lu,%lu\n", tv->tv_sec, tv->tv_usec);*/
	if (ast_tvzero(*tv))	/* not supplied, default to now */
		*tv = now;
	*tv = ast_tvadd(*tv, ast_samp2tv(when, 1000));
	if (ast_tvcmp(*tv, now) < 0) {
		ast_log(LOG_DEBUG, "Request to schedule in the past?!?!\n");
		*tv = now;
	}
	return 0;
}

static int ast_sched_add_variable(struct sched_context *con, int when, ast_sched_cb callback, void *data, int variable)
{
	struct sched *tmp;
	int res = -1;
	DEBUG(ast_log(LOG_DEBUG, "ast_sched_add()\n"));
	if (!when) {
		ast_log(LOG_NOTICE, "Scheduled event in 0 ms?\n");
		return -1;
	}
	ast_mutex_lock(&con->lock);
	if ((tmp = sched_alloc(con))) {
		tmp->id = con->eventcnt++;
		tmp->callback = callback;
		tmp->data = data;
		tmp->resched = when;
		tmp->variable = variable;
		tmp->when = ast_tv(0, 0);
		if (sched_settime(&tmp->when, when)) {
			sched_release(con, tmp);
		} else {
			schedule(con, tmp);
			res = tmp->id;
		}
	}
#ifdef DUMP_SCHEDULER
	/* Dump contents of the context while we have the lock so nothing gets screwed up by accident. */
	if (option_debug)
		ast_sched_dump(con);
#endif
	ast_mutex_unlock(&con->lock);
	return res;
}

int mtp_sched_add(struct sched_context *con, int when, ast_sched_cb callback, void *data)
{
	return ast_sched_add_variable(con, when, callback, data, 0);
}

int mtp_sched_del(struct sched_context *con, int id)
{
	struct sched *s;

	DEBUG(ast_log(LOG_DEBUG, "ast_sched_del()\n"));
	
	ast_mutex_lock(&con->lock);
	AST_LIST_TRAVERSE_SAFE_BEGIN(&con->schedq, s, list) {
		if (s->id == id) {
			AST_LIST_REMOVE_CURRENT(&con->schedq, list);
			con->schedcnt--;
			sched_release(con, s);
			break;
		}
	}
	AST_LIST_TRAVERSE_SAFE_END

#ifdef DUMP_SCHEDULER
	/* Dump contents of the context while we have the lock so nothing gets screwed up by accident. */
	if (option_debug)
		ast_sched_dump(con);
#endif
	ast_mutex_unlock(&con->lock);

	if (!s) {
		if (option_debug)
			ast_log(LOG_DEBUG, "Attempted to delete nonexistent schedule entry %d!\n", id);
#ifdef DO_CRASH
		CRASH;
#endif
		return -1;
	}
	
	return 0;
}

int mtp_sched_runq(struct sched_context *con)
{
	struct sched *current;
	struct timeval tv;
	int numevents;
	int res;

	DEBUG(ast_log(LOG_DEBUG, "ast_sched_runq()\n"));
		
	ast_mutex_lock(&con->lock);

	for (numevents = 0; !AST_LIST_EMPTY(&con->schedq); numevents++) {
		/* schedule all events which are going to expire within 1ms.
		 * We only care about millisecond accuracy anyway, so this will
		 * help us get more than one event at one time if they are very
		 * close together.
		 */
		tv = ast_tvadd(ast_tvnow(), ast_tv(0, 1000));
		if (ast_tvcmp(AST_LIST_FIRST(&con->schedq)->when, tv) != -1)
			break;
		
		current = AST_LIST_REMOVE_HEAD(&con->schedq, list);
		con->schedcnt--;

		/*
		 * At this point, the schedule queue is still intact.  We
		 * have removed the first event and the rest is still there,
		 * so it's permissible for the callback to add new events, but
		 * trying to delete itself won't work because it isn't in
		 * the schedule queue.  If that's what it wants to do, it 
		 * should return 0.
		 */
			
		ast_mutex_unlock(&con->lock);
		res = current->callback(current->data);
		ast_mutex_lock(&con->lock);
			
		if (res) {
		 	/*
			 * If they return non-zero, we should schedule them to be
			 * run again.
			 */
			if (sched_settime(&current->when, current->variable? res : current->resched)) {
				sched_release(con, current);
			} else
				schedule(con, current);
		} else {
			/* No longer needed, so release it */
		 	sched_release(con, current);
		}
	}

	ast_mutex_unlock(&con->lock);
	
	return numevents;
}


int ast_jb_read_conf(struct ast_jb_conf *conf, char *varname, char *value)
{
  return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -