[svn-commits] branch crichter/0.3.0 - r8478 in
/team/crichter/0.3.0: ./ apps/ channels/
svn-commits at lists.digium.com
svn-commits at lists.digium.com
Mon Jan 23 08:35:26 MST 2006
Author: crichter
Date: Mon Jan 23 09:35:19 2006
New Revision: 8478
URL: http://svn.digium.com/view/asterisk?rev=8478&view=rev
Log:
Merged revisions 8394,8412,8414,8418,8429,8433,8437,8445 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.2
........
r8394 | tilghman | 2006-01-21 19:29:39 +0100 (Sa, 21 Jan 2006) | 2 lines
Bug 5936 - AddQueueMember fails on realtime queue, if queue not yet loaded
........
r8412 | russell | 2006-01-22 00:17:06 +0100 (So, 22 Jan 2006) | 2 lines
prevent the possibility of writing outside of the available workspace (issue #6271)
........
r8414 | russell | 2006-01-22 00:43:14 +0100 (So, 22 Jan 2006) | 2 lines
temporarily revert substring fix pending the result of the discussion in issue #6271
........
r8418 | russell | 2006-01-22 03:05:41 +0100 (So, 22 Jan 2006) | 3 lines
add a modified fix to prevent writing outside of the provided workspace when
calculating a substring (issue #6271)
........
r8429 | tilghman | 2006-01-22 09:52:49 +0100 (So, 22 Jan 2006) | 2 lines
Bug 6281 - Cannot set more than a single header with SIPAddHeader
........
r8433 | bweschke | 2006-01-22 16:13:41 +0100 (So, 22 Jan 2006) | 3 lines
Bug fix: Correct some scenarios where CALL_LIMIT could not be getting adjusted properly allowing chan_sip to send calls when it really shouldn't. Bug #6111
........
r8437 | russell | 2006-01-22 18:47:13 +0100 (So, 22 Jan 2006) | 2 lines
fix MixMonitor crash (issue #6321, probably others)
........
r8445 | russell | 2006-01-22 20:03:53 +0100 (So, 22 Jan 2006) | 2 lines
fix memory leak from not freeing the queue member list when freeing an old queue
........
Modified:
team/crichter/0.3.0/ (props changed)
team/crichter/0.3.0/apps/app_queue.c
team/crichter/0.3.0/channel.c
team/crichter/0.3.0/channels/chan_sip.c
team/crichter/0.3.0/pbx.c
Propchange: team/crichter/0.3.0/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Mon Jan 23 09:35:19 2006
@@ -1,1 +1,1 @@
-/branches/1.2:1-7496,7498-7914,7916-7959,7961-7964,7966-7969,7971-7975,7977-8350
+/branches/1.2:1-7496,7498-7914,7916-7959,7961-7964,7966-7969,7971-7975,7977-8477
Modified: team/crichter/0.3.0/apps/app_queue.c
URL: http://svn.digium.com/view/asterisk/team/crichter/0.3.0/apps/app_queue.c?rev=8478&r1=8477&r2=8478&view=diff
==============================================================================
--- team/crichter/0.3.0/apps/app_queue.c (original)
+++ team/crichter/0.3.0/apps/app_queue.c Mon Jan 23 09:35:19 2006
@@ -19,8 +19,6 @@
/*! \file
*
* \brief True call queues with optional send URL on answer
- *
- * \author Mark Spencer <markster at digium.com>
*
* \arg Config in \ref Config_qu queues.conf
*
@@ -286,7 +284,6 @@
time_t last_pos; /*!< Last time we told the user their position */
int opos; /*!< Where we started in the queue */
int handled; /*!< Whether our call was handled */
- int max_penalty; /*!< Limit the members that can take this call to this penalty or lower */
time_t start; /*!< When we started holding */
time_t expire; /*!< When this entry should expire (time out of queue) */
struct ast_channel *chan; /*!< Our channel */
@@ -427,15 +424,12 @@
QUEUE_NORMAL
};
-static enum queue_member_status get_member_status(const struct ast_call_queue *q, int max_penalty)
+static enum queue_member_status get_member_status(const struct ast_call_queue *q)
{
struct member *member;
enum queue_member_status result = QUEUE_NO_MEMBERS;
for (member = q->members; member; member = member->next) {
- if (max_penalty && (member->penalty > max_penalty))
- continue;
-
switch (member->status) {
case AST_DEVICE_INVALID:
/* nothing to do */
@@ -761,11 +755,52 @@
}
}
+static void free_members(struct ast_call_queue *q, int all)
+{
+ /* Free non-dynamic members */
+ struct member *curm, *next, *prev = NULL;
+
+ for (curm = q->members; curm; curm = next) {
+ next = curm->next;
+ if (all || !curm->dynamic) {
+ if (prev)
+ prev->next = next;
+ else
+ q->members = next;
+ free(curm);
+ } else
+ prev = curm;
+ }
+}
+
+static void destroy_queue(struct ast_call_queue *q)
+{
+ free_members(q, 1);
+ ast_mutex_destroy(&q->lock);
+ free(q);
+}
+
+static void remove_queue(struct ast_call_queue *q)
+{
+ struct ast_call_queue *cur, *prev = NULL;
+
+ ast_mutex_lock(&qlock);
+ for (cur = queues; cur; cur = cur->next) {
+ if (cur == q) {
+ if (prev)
+ prev->next = cur->next;
+ else
+ queues = cur->next;
+ } else {
+ prev = cur;
+ }
+ }
+ ast_mutex_unlock(&qlock);
+}
/*!\brief Reload a single queue via realtime.
\return Return the queue, or NULL if it doesn't exist.
- \note Should be called with the global qlock locked.
- When found, the queue is returned with q->lock locked. */
+ \note Should be called with the global qlock locked. */
static struct ast_call_queue *find_queue_by_name_rt(const char *queuename, struct ast_variable *queue_vars, struct ast_config *member_config)
{
struct ast_variable *v;
@@ -791,6 +826,7 @@
ast_mutex_unlock(&q->lock);
return NULL;
} else {
+ ast_mutex_unlock(&q->lock);
return q;
}
}
@@ -817,7 +853,7 @@
prev_q->next = q->next;
}
ast_mutex_unlock(&q->lock);
- free(q);
+ destroy_queue(q);
} else
ast_mutex_unlock(&q->lock);
}
@@ -885,13 +921,60 @@
m = next_m;
}
+ ast_mutex_unlock(&q->lock);
+
return q;
}
-static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason)
+static struct ast_call_queue *load_realtime_queue(char *queuename)
{
struct ast_variable *queue_vars = NULL;
struct ast_config *member_config = NULL;
+ struct ast_call_queue *q;
+
+ /* Find the queue in the in-core list first. */
+ ast_mutex_lock(&qlock);
+ for (q = queues; q; q = q->next) {
+ if (!strcasecmp(q->name, queuename)) {
+ break;
+ }
+ }
+ ast_mutex_unlock(&qlock);
+
+ if (!q) {
+ /*! \note Load from realtime before taking the global qlock, to avoid blocking all
+ queue operations while waiting for the DB.
+
+ This will be two separate database transactions, so we might
+ see queue parameters as they were before another process
+ changed the queue and member list as it was after the change.
+ Thus we might see an empty member list when a queue is
+ deleted. In practise, this is unlikely to cause a problem. */
+
+ queue_vars = ast_load_realtime("queues", "name", queuename, NULL);
+ if (queue_vars) {
+ member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, NULL);
+ if (!member_config) {
+ ast_log(LOG_ERROR, "no queue_members defined in your config (extconfig.conf).\n");
+ return NULL;
+ }
+ }
+
+ ast_mutex_lock(&qlock);
+
+ q = find_queue_by_name_rt(queuename, queue_vars, member_config);
+ if (member_config)
+ ast_config_destroy(member_config);
+ if (queue_vars)
+ ast_variables_destroy(queue_vars);
+
+ ast_mutex_unlock(&qlock);
+ }
+ return q;
+}
+
+static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason)
+{
struct ast_call_queue *q;
struct queue_ent *cur, *prev = NULL;
int res = -1;
@@ -899,38 +982,15 @@
int inserted = 0;
enum queue_member_status stat;
- /*! \note Load from realtime before taking the global qlock, to avoid blocking all
- queue operations while waiting for the DB.
-
- This will be two separate database transactions, so we might
- see queue parameters as they were before another process
- changed the queue and member list as it was after the change.
- Thus we might see an empty member list when a queue is
- deleted. In practise, this is unlikely to cause a problem. */
- queue_vars = ast_load_realtime("queues", "name", queuename, NULL);
- if (queue_vars) {
- member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, NULL);
- if (!member_config) {
- ast_log(LOG_ERROR, "no queue_members defined in your config (extconfig.conf).\n");
- return res;
- }
- }
+ q = load_realtime_queue(queuename);
+ if (!q)
+ return res;
ast_mutex_lock(&qlock);
- q = find_queue_by_name_rt(queuename, queue_vars, member_config);
- /* Note: If found, find_queue_by_name_rt() returns with q->lock locked. */
- if(member_config)
- ast_config_destroy(member_config);
- if(queue_vars)
- ast_variables_destroy(queue_vars);
-
- if (!q) {
- ast_mutex_unlock(&qlock);
- return res;
- }
+ ast_mutex_lock(&q->lock);
/* This is our one */
- stat = get_member_status(q, qe->max_penalty);
+ stat = get_member_status(q);
if (!q->joinempty && (stat == QUEUE_NO_MEMBERS))
*reason = QUEUE_JOINEMPTY;
else if ((q->joinempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS))
@@ -979,48 +1039,6 @@
return res;
}
-static void free_members(struct ast_call_queue *q, int all)
-{
- /* Free non-dynamic members */
- struct member *curm, *next, *prev;
-
- curm = q->members;
- prev = NULL;
- while(curm) {
- next = curm->next;
- if (all || !curm->dynamic) {
- if (prev)
- prev->next = next;
- else
- q->members = next;
- free(curm);
- } else
- prev = curm;
- curm = next;
- }
-}
-
-static void destroy_queue(struct ast_call_queue *q)
-{
- struct ast_call_queue *cur, *prev = NULL;
-
- ast_mutex_lock(&qlock);
- for (cur = queues; cur; cur = cur->next) {
- if (cur == q) {
- if (prev)
- prev->next = cur->next;
- else
- queues = cur->next;
- } else {
- prev = cur;
- }
- }
- ast_mutex_unlock(&qlock);
- free_members(q, 1);
- ast_mutex_destroy(&q->lock);
- free(q);
-}
-
static int play_file(struct ast_channel *chan, char *filename)
{
int res;
@@ -1228,6 +1246,7 @@
ast_mutex_unlock(&q->lock);
if (q->dead && !q->count) {
/* It's dead and nobody is in it, so kill it */
+ remove_queue(q);
destroy_queue(q);
}
}
@@ -1879,7 +1898,7 @@
break;
}
- stat = get_member_status(qe->parent, qe->max_penalty);
+ stat = get_member_status(qe->parent);
/* leave the queue if no agents, if enabled */
if (qe->parent->leavewhenempty && (stat == QUEUE_NO_MEMBERS)) {
@@ -1936,9 +1955,6 @@
static int calc_metric(struct ast_call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct localuser *tmp)
{
- if (mem->penalty > qe->max_penalty)
- return -1;
-
switch (q->strategy) {
case QUEUE_STRATEGY_RINGALL:
/* Everyone equal, except for penalty */
@@ -1999,6 +2015,7 @@
char oldcontext[AST_MAX_CONTEXT]="";
char queuename[256]="";
char *newnum;
+ char *monitorfilename;
struct ast_channel *peer;
struct ast_channel *which;
struct localuser *lpeer;
@@ -2091,18 +2108,15 @@
}
/* Special case: If we ring everyone, go ahead and ring them, otherwise
just calculate their metric for the appropriate strategy */
- if (!calc_metric(qe->parent, cur, x++, qe, tmp)) {
- /* Put them in the list of outgoing thingies... We're ready now.
- XXX If we're forcibly removed, these outgoing calls won't get
- hung up XXX */
- tmp->next = outgoing;
- outgoing = tmp;
- /* If this line is up, don't try anybody else */
- if (outgoing->chan && (outgoing->chan->_state == AST_STATE_UP))
- break;
- } else {
- free(tmp);
- }
+ calc_metric(qe->parent, cur, x++, qe, tmp);
+ /* Put them in the list of outgoing thingies... We're ready now.
+ XXX If we're forcibly removed, these outgoing calls won't get
+ hung up XXX */
+ tmp->next = outgoing;
+ outgoing = tmp;
+ /* If this line is up, don't try anybody else */
+ if (outgoing->chan && (outgoing->chan->_state == AST_STATE_UP))
+ break;
cur = cur->next;
}
@@ -2218,7 +2232,7 @@
}
/* Begin Monitoring */
if (qe->parent->monfmt && *qe->parent->monfmt) {
- const char *monitorfilename = pbx_builtin_getvar_helper(qe->chan, "MONITOR_FILENAME");
+ monitorfilename = pbx_builtin_getvar_helper(qe->chan, "MONITOR_FILENAME");
if (pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC") || pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC_ARGS"))
which = qe->chan;
else
@@ -2413,41 +2427,42 @@
struct member *new_member;
int res = RES_NOSUCHQUEUE;
+ /* \note Ensure the appropriate realtime queue is loaded. Note that this
+ * short-circuits if the queue is already in memory. */
+ q = load_realtime_queue(queuename);
+
ast_mutex_lock(&qlock);
- for (q = queues ; q ; q = q->next) {
+
+ if (q) {
ast_mutex_lock(&q->lock);
- if (!strcmp(q->name, queuename)) {
- if (interface_exists(q, interface) == NULL) {
- new_member = create_queue_member(interface, penalty, paused);
-
- if (new_member != NULL) {
- new_member->dynamic = 1;
- new_member->next = q->members;
- q->members = new_member;
- manager_event(EVENT_FLAG_AGENT, "QueueMemberAdded",
- "Queue: %s\r\n"
- "Location: %s\r\n"
- "Membership: %s\r\n"
- "Penalty: %d\r\n"
- "CallsTaken: %d\r\n"
- "LastCall: %d\r\n"
- "Status: %d\r\n"
- "Paused: %d\r\n",
- q->name, new_member->interface, new_member->dynamic ? "dynamic" : "static",
- new_member->penalty, new_member->calls, (int)new_member->lastcall, new_member->status, new_member->paused);
+ if (interface_exists(q, interface) == NULL) {
+ new_member = create_queue_member(interface, penalty, paused);
+
+ if (new_member != NULL) {
+ new_member->dynamic = 1;
+ new_member->next = q->members;
+ q->members = new_member;
+ manager_event(EVENT_FLAG_AGENT, "QueueMemberAdded",
+ "Queue: %s\r\n"
+ "Location: %s\r\n"
+ "Membership: %s\r\n"
+ "Penalty: %d\r\n"
+ "CallsTaken: %d\r\n"
+ "LastCall: %d\r\n"
+ "Status: %d\r\n"
+ "Paused: %d\r\n",
+ q->name, new_member->interface, new_member->dynamic ? "dynamic" : "static",
+ new_member->penalty, new_member->calls, (int)new_member->lastcall, new_member->status, new_member->paused);
- if (dump)
- dump_queue_members(q);
-
- res = RES_OKAY;
- } else {
- res = RES_OUTOFMEMORY;
- }
+ if (dump)
+ dump_queue_members(q);
+
+ res = RES_OKAY;
} else {
- res = RES_EXISTS;
- }
- ast_mutex_unlock(&q->lock);
- break;
+ res = RES_OUTOFMEMORY;
+ }
+ } else {
+ res = RES_EXISTS;
}
ast_mutex_unlock(&q->lock);
}
@@ -2627,7 +2642,7 @@
if (set_member_paused(args.queuename, args.interface, 1)) {
ast_log(LOG_WARNING, "Attempt to pause interface %s, not found\n", args.interface);
- if (priority_jump || ast_opt_priority_jumping) {
+ if (priority_jump || option_priority_jumping) {
if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101)) {
pbx_builtin_setvar_helper(chan, "PQMSTATUS", "NOTFOUND");
LOCAL_USER_REMOVE(u);
@@ -2683,7 +2698,7 @@
if (set_member_paused(args.queuename, args.interface, 0)) {
ast_log(LOG_WARNING, "Attempt to unpause interface %s, not found\n", args.interface);
- if (priority_jump || ast_opt_priority_jumping) {
+ if (priority_jump || option_priority_jumping) {
if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101)) {
pbx_builtin_setvar_helper(chan, "UPQMSTATUS", "NOTFOUND");
LOCAL_USER_REMOVE(u);
@@ -2748,7 +2763,7 @@
break;
case RES_EXISTS:
ast_log(LOG_WARNING, "Unable to remove interface '%s' from queue '%s': Not there\n", args.interface, args.queuename);
- if (priority_jump || ast_opt_priority_jumping)
+ if (priority_jump || option_priority_jumping)
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
pbx_builtin_setvar_helper(chan, "RQMSTATUS", "NOTINQUEUE");
res = 0;
@@ -2824,7 +2839,7 @@
break;
case RES_EXISTS:
ast_log(LOG_WARNING, "Unable to add interface '%s' to queue '%s': Already there\n", args.interface, args.queuename);
- if (priority_jump || ast_opt_priority_jumping)
+ if (priority_jump || option_priority_jumping)
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
pbx_builtin_setvar_helper(chan, "AQMSTATUS", "MEMBERALREADY");
res = 0;
@@ -2854,10 +2869,8 @@
char *options = NULL;
char *url = NULL;
char *announceoverride = NULL;
- const char *user_priority;
- const char *max_penalty_str;
+ char *user_priority;
int prio;
- int max_penalty;
char *queuetimeoutstr = NULL;
enum queue_result reason = QUEUE_UNKNOWN;
@@ -2910,31 +2923,15 @@
prio = 0;
}
- /* Get the maximum penalty from the variable ${QUEUE_MAX_PENALTY} */
- if ((max_penalty_str = pbx_builtin_getvar_helper(chan, "QUEUE_MAX_PENALTY"))) {
- if (sscanf(max_penalty_str, "%d", &max_penalty) == 1) {
- if (option_debug)
- ast_log(LOG_DEBUG, "%s: Got max penalty %d from ${QUEUE_MAX_PENALTY}.\n",
- chan->name, max_penalty);
- } else {
- ast_log(LOG_WARNING, "${QUEUE_MAX_PENALTY}: Invalid value (%s), channel %s.\n",
- max_penalty_str, chan->name);
- max_penalty = 0;
- }
- } else {
- max_penalty = 0;
- }
-
if (options && (strchr(options, 'r')))
ringing = 1;
if (option_debug)
ast_log(LOG_DEBUG, "queue: %s, options: %s, url: %s, announce: %s, expires: %ld, priority: %d\n",
- queuename, options, url, announceoverride, (long)qe.expire, prio);
+ queuename, options, url, announceoverride, (long)qe.expire, (int)prio);
qe.chan = chan;
- qe.prio = prio;
- qe.max_penalty = max_penalty;
+ qe.prio = (int)prio;
qe.last_pos_said = 0;
qe.last_pos = 0;
qe.last_periodic_announce_time = time(NULL);
@@ -3022,7 +3019,7 @@
break;
}
- stat = get_member_status(qe.parent, qe.max_penalty);
+ stat = get_member_status(qe.parent);
/* leave the queue if no agents, if enabled */
if (qe.parent->leavewhenempty && (stat == QUEUE_NO_MEMBERS)) {
@@ -3270,7 +3267,7 @@
else
queues = q->next;
if (!q->count) {
- free(q);
+ destroy_queue(q);
} else
ast_log(LOG_WARNING, "XXX Leaking a little memory :( XXX\n");
} else {
@@ -3299,7 +3296,13 @@
time(&now);
if ((!queue_show && argc != 2) || (queue_show && argc != 3))
return RESULT_SHOWUSAGE;
+
+ /* We only want to load realtime queues when a specific queue is asked for. */
+ if (queue_show)
+ load_realtime_queue(argv[2]);
+
ast_mutex_lock(&qlock);
+
q = queues;
if (!q) {
ast_mutex_unlock(&qlock);
@@ -3387,22 +3390,17 @@
static char *complete_queue(char *line, char *word, int pos, int state)
{
struct ast_call_queue *q;
- char *ret = NULL;
- int which = 0;
- int wordlen = strlen(word);
+ int which=0;
ast_mutex_lock(&qlock);
for (q = queues; q; q = q->next) {
- if (!strncasecmp(word, q->name, wordlen)) {
- if (++which > state) {
- ret = strdup(q->name);
+ if (!strncasecmp(word, q->name, strlen(word))) {
+ if (++which > state)
break;
- }
}
}
ast_mutex_unlock(&qlock);
-
- return ret;
+ return q ? strdup(q->name) : NULL;
}
/*!\brief callback to display queues status in manager
Modified: team/crichter/0.3.0/channel.c
URL: http://svn.digium.com/view/asterisk/team/crichter/0.3.0/channel.c?rev=8478&r1=8477&r2=8478&view=diff
==============================================================================
--- team/crichter/0.3.0/channel.c (original)
+++ team/crichter/0.3.0/channel.c Mon Jan 23 09:35:19 2006
@@ -3826,7 +3826,7 @@
}
tocopy = (f->samples > samples) ? samples : f->samples;
- bytestocopy = ast_codec_get_len(queue->format, samples);
+ bytestocopy = ast_codec_get_len(queue->format, tocopy);
memcpy(buf, f->data, bytestocopy);
samples -= tocopy;
buf += tocopy;
Modified: team/crichter/0.3.0/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/crichter/0.3.0/channels/chan_sip.c?rev=8478&r1=8477&r2=8478&view=diff
==============================================================================
--- team/crichter/0.3.0/channels/chan_sip.c (original)
+++ team/crichter/0.3.0/channels/chan_sip.c Mon Jan 23 09:35:19 2006
@@ -1,7 +1,7 @@
/*
* Asterisk -- An open source telephony toolkit.
*
- * Copyright (C) 1999 - 2006, Digium, Inc.
+ * Copyright (C) 1999 - 2005, Digium, Inc.
*
* Mark Spencer <markster at digium.com>
*
@@ -19,12 +19,7 @@
/*!
* \file
* \brief Implementation of Session Initiation Protocol
- *
- * \author Mark Spencer <markster at digium.com>
- *
- * See Also:
- * \arg \ref AstCREDITS
- *
+ *
* Implementation of RFC 3261 - without S/MIME, TCP and TLS support
* Configuration file \link Config_sip sip.conf \endlink
*
@@ -86,7 +81,6 @@
#include "asterisk/dnsmgr.h"
#include "asterisk/devicestate.h"
#include "asterisk/linkedlists.h"
-#include "asterisk/stringfields.h"
#ifdef OSP_SUPPORT
#include "asterisk/astosp.h"
@@ -105,7 +99,6 @@
#define SIPDUMPER
#define DEFAULT_DEFAULT_EXPIRY 120
-#define DEFAULT_MIN_EXPIRY 60
#define DEFAULT_MAX_EXPIRY 3600
#define DEFAULT_REGISTRATION_TIMEOUT 20
#define DEFAULT_MAX_FORWARDS "70"
@@ -122,7 +115,6 @@
#define EXPIRY_GUARD_PCT 0.20 /* Percentage of expires timeout to use when
below EXPIRY_GUARD_LIMIT */
-static int min_expiry = DEFAULT_MIN_EXPIRY;
static int max_expiry = DEFAULT_MAX_EXPIRY;
static int default_expiry = DEFAULT_DEFAULT_EXPIRY;
@@ -418,6 +410,9 @@
static struct sockaddr_in outboundproxyip;
static int ourport;
+#define SIP_DEBUG_CONFIG 1 << 0
+#define SIP_DEBUG_CONSOLE 1 << 1
+static int sipdebug = 0;
static struct sockaddr_in debugaddr;
static int tos = 0;
@@ -468,11 +463,11 @@
/*! \brief Parameters to the transmit_invite function */
struct sip_invite_param {
- const char *distinctive_ring; /*!< Distinctive ring header */
+ char *distinctive_ring; /*!< Distinctive ring header */
char *osptoken; /*!< OSP token for this call */
int addsipheaders; /*!< Add extra SIP headers */
- const char *uri_options; /*!< URI options to add to the URI */
- const char *vxml_url; /*!< VXML url for Cisco phones */
+ char *uri_options; /*!< URI options to add to the URI */
+ char *vxml_url; /*!< VXML url for Cisco phones */
char *auth; /*!< Authentication */
char *authheader; /*!< Auth header */
enum sip_auth_type auth_type; /*!< Authentication type */
@@ -501,11 +496,9 @@
/*! \brief sip_history: Structure for saving transactions within a SIP dialog */
struct sip_history {
- AST_LIST_ENTRY(sip_history) list;
- char event[0]; /* actually more, depending on needs */
+ char event[80];
+ struct sip_history *next;
};
-
-AST_LIST_HEAD_NOLOCK(sip_history_head, sip_history); /*!< history list, entry in sip_pvt */
/*! \brief sip_auth: Creadentials for authentication to other SIP services */
struct sip_auth {
@@ -567,6 +560,8 @@
#define SIP_CALL_LIMIT (1 << 29)
/* Remote Party-ID Support */
#define SIP_SENDRPID (1 << 30)
+/* Did this connection increment the counter of in-use calls? */
+#define SIP_INC_COUNT (1 << 31)
#define SIP_FLAGS_TO_COPY \
(SIP_PROMISCREDIR | SIP_TRUSTRPID | SIP_SENDRPID | SIP_DTMF | SIP_REINVITE | \
@@ -579,17 +574,10 @@
#define SIP_PAGE2_RTAUTOCLEAR (1 << 2)
#define SIP_PAGE2_IGNOREREGEXPIRE (1 << 3)
#define SIP_PAGE2_RT_FROMCONTACT (1 << 4)
-#define SIP_PAGE2_DEBUG (3 << 5)
-#define SIP_PAGE2_DEBUG_CONFIG (1 << 5)
-#define SIP_PAGE2_DEBUG_CONSOLE (1 << 6)
/* SIP packet flags */
#define SIP_PKT_DEBUG (1 << 0) /*!< Debug this packet */
#define SIP_PKT_WITH_TOTAG (1 << 1) /*!< This packet has a to-tag */
-
-#define sipdebug ast_test_flag(&global_flags_page2, SIP_PAGE2_DEBUG)
-#define sipdebug_config ast_test_flag(&global_flags_page2, SIP_PAGE2_DEBUG_CONFIG)
-#define sipdebug_console ast_test_flag(&global_flags_page2, SIP_PAGE2_DEBUG_CONSOLE)
static int global_rtautoclear = 120;
@@ -597,46 +585,8 @@
static struct sip_pvt {
ast_mutex_t lock; /*!< Channel private lock */
int method; /*!< SIP method of this packet */
- AST_DECLARE_STRING_FIELDS(
- AST_STRING_FIELD(callid); /*!< Global CallID */
- AST_STRING_FIELD(randdata); /*!< Random data */
- AST_STRING_FIELD(accountcode); /*!< Account code */
- AST_STRING_FIELD(realm); /*!< Authorization realm */
- AST_STRING_FIELD(nonce); /*!< Authorization nonce */
- AST_STRING_FIELD(opaque); /*!< Opaque nonsense */
- AST_STRING_FIELD(qop); /*!< Quality of Protection, since SIP wasn't complicated enough yet. */
- AST_STRING_FIELD(domain); /*!< Authorization domain */
- AST_STRING_FIELD(refer_to); /*!< Place to store REFER-TO extension */
- AST_STRING_FIELD(referred_by); /*!< Place to store REFERRED-BY extension */
- AST_STRING_FIELD(refer_contact);/*!< Place to store Contact info from a REFER extension */
- AST_STRING_FIELD(from); /*!< The From: header */
- AST_STRING_FIELD(useragent); /*!< User agent in SIP request */
- AST_STRING_FIELD(exten); /*!< Extension where to start */
- AST_STRING_FIELD(context); /*!< Context for this call */
- AST_STRING_FIELD(subscribecontext); /*!< Subscribecontext */
- AST_STRING_FIELD(fromdomain); /*!< Domain to show in the from field */
- AST_STRING_FIELD(fromuser); /*!< User to show in the user field */
- AST_STRING_FIELD(fromname); /*!< Name to show in the user field */
- AST_STRING_FIELD(tohost); /*!< Host we should put in the "to" field */
- AST_STRING_FIELD(language); /*!< Default language for this call */
- AST_STRING_FIELD(musicclass); /*!< Music on Hold class */
- AST_STRING_FIELD(rdnis); /*!< Referring DNIS */
- AST_STRING_FIELD(theirtag); /*!< Their tag */
- AST_STRING_FIELD(username); /*!< [user] name */
- AST_STRING_FIELD(peername); /*!< [peer] name, not set if [user] */
- AST_STRING_FIELD(authname); /*!< Who we use for authentication */
- AST_STRING_FIELD(uri); /*!< Original requested URI */
- AST_STRING_FIELD(okcontacturi); /*!< URI from the 200 OK on INVITE */
- AST_STRING_FIELD(peersecret); /*!< Password */
- AST_STRING_FIELD(peermd5secret);
- AST_STRING_FIELD(cid_num); /*!< Caller*ID */
- AST_STRING_FIELD(cid_name); /*!< Caller*ID */
- AST_STRING_FIELD(via); /*!< Via: header */
- AST_STRING_FIELD(fullcontact); /*!< The Contact: that the UA registers with us */
- AST_STRING_FIELD(our_contact); /*!< Our contact header */
- AST_STRING_FIELD(rpid); /*!< Our RPID header */
- AST_STRING_FIELD(rpid_from); /*!< Our RPID From header */
- );
+ char callid[80]; /*!< Global CallID */
+ char randdata[80]; /*!< Random data */
struct ast_codec_pref prefs; /*!< codec prefs */
unsigned int ocseq; /*!< Current outgoing seqno */
unsigned int icseq; /*!< Current incoming seqno */
@@ -665,11 +615,47 @@
struct sockaddr_in recv; /*!< Received as */
struct in_addr ourip; /*!< Our IP */
struct ast_channel *owner; /*!< Who owns us */
+ char exten[AST_MAX_EXTENSION]; /*!< Extension where to start */
+ char refer_to[AST_MAX_EXTENSION]; /*!< Place to store REFER-TO extension */
+ char referred_by[AST_MAX_EXTENSION]; /*!< Place to store REFERRED-BY extension */
+ char refer_contact[AST_MAX_EXTENSION]; /*!< Place to store Contact info from a REFER extension */
struct sip_pvt *refer_call; /*!< Call we are referring */
struct sip_route *route; /*!< Head of linked list of routing steps (fm Record-Route) */
int route_persistant; /*!< Is this the "real" route? */
+ char from[256]; /*!< The From: header */
+ char useragent[256]; /*!< User agent in SIP request */
+ char context[AST_MAX_CONTEXT]; /*!< Context for this call */
+ char subscribecontext[AST_MAX_CONTEXT]; /*!< Subscribecontext */
+ char fromdomain[MAXHOSTNAMELEN]; /*!< Domain to show in the from field */
+ char fromuser[AST_MAX_EXTENSION]; /*!< User to show in the user field */
+ char fromname[AST_MAX_EXTENSION]; /*!< Name to show in the user field */
+ char tohost[MAXHOSTNAMELEN]; /*!< Host we should put in the "to" field */
+ char language[MAX_LANGUAGE]; /*!< Default language for this call */
+ char musicclass[MAX_MUSICCLASS]; /*!< Music on Hold class */
+ char rdnis[256]; /*!< Referring DNIS */
+ char theirtag[256]; /*!< Their tag */
+ char username[256]; /*!< [user] name */
+ char peername[256]; /*!< [peer] name, not set if [user] */
+ char authname[256]; /*!< Who we use for authentication */
+ char uri[256]; /*!< Original requested URI */
+ char okcontacturi[256]; /*!< URI from the 200 OK on INVITE */
+ char peersecret[256]; /*!< Password */
+ char peermd5secret[256];
struct sip_auth *peerauth; /*!< Realm authentication */
+ char cid_num[256]; /*!< Caller*ID */
+ char cid_name[256]; /*!< Caller*ID */
+ char via[256]; /*!< Via: header */
+ char fullcontact[128]; /*!< The Contact: that the UA registers with us */
+ char accountcode[AST_MAX_ACCOUNT_CODE]; /*!< Account code */
+ char our_contact[256]; /*!< Our contact header */
+ char *rpid; /*!< Our RPID header */
+ char *rpid_from; /*!< Our RPID From header */
+ char realm[MAXHOSTNAMELEN]; /*!< Authorization realm */
+ char nonce[256]; /*!< Authorization nonce */
int noncecount; /*!< Nonce-count */
+ char opaque[256]; /*!< Opaque nonsense */
+ char qop[80]; /*!< Quality of Protection, since SIP wasn't complicated enough yet. */
+ char domain[MAXHOSTNAMELEN]; /*!< Authorization domain */
char lastmsg[256]; /*!< Last Message sent/received */
int amaflags; /*!< AMA Flags */
int pendinginvite; /*!< Any pending invite */
@@ -700,7 +686,7 @@
struct ast_rtp *rtp; /*!< RTP Session */
struct ast_rtp *vrtp; /*!< Video RTP session */
struct sip_pkt *packets; /*!< Packets scheduled for re-transmission */
- struct sip_history_head *history; /*!< History of this SIP dialog */
+ struct sip_history *history; /*!< History of this SIP dialog */
struct ast_variable *chanvars; /*!< Channel variables to set for call */
struct sip_pvt *next; /*!< Next call in chain */
struct sip_invite_param *options; /*!< Options for INVITE */
@@ -826,22 +812,14 @@
/*! \brief sip_registry: Registrations with other SIP proxies */
struct sip_registry {
ASTOBJ_COMPONENTS_FULL(struct sip_registry,1,1);
- AST_DECLARE_STRING_FIELDS(
- AST_STRING_FIELD(callid); /*!< Global Call-ID */
- AST_STRING_FIELD(realm); /*!< Authorization realm */
- AST_STRING_FIELD(nonce); /*!< Authorization nonce */
- AST_STRING_FIELD(opaque); /*!< Opaque nonsense */
- AST_STRING_FIELD(qop); /*!< Quality of Protection, since SIP wasn't complicated enough yet. */
- AST_STRING_FIELD(domain); /*!< Authorization domain */
- AST_STRING_FIELD(username); /*!< Who we are registering as */
- AST_STRING_FIELD(authuser); /*!< Who we *authenticate* as */
- AST_STRING_FIELD(hostname); /*!< Domain or host we register to */
- AST_STRING_FIELD(secret); /*!< Password in clear text */
- AST_STRING_FIELD(md5secret); /*!< Password in md5 */
- AST_STRING_FIELD(contact); /*!< Contact extension */
- AST_STRING_FIELD(random);
- );
int portno; /*!< Optional port override */
+ char username[80]; /*!< Who we are registering as */
+ char authuser[80]; /*!< Who we *authenticate* as */
+ char hostname[MAXHOSTNAMELEN]; /*!< Domain or host we register to */
+ char secret[80]; /*!< Password in clear text */
+ char md5secret[80]; /*!< Password in md5 */
+ char contact[256]; /*!< Contact extension */
+ char random[80];
int expire; /*!< Sched ID of expiration */
int regattempts; /*!< Number of attempts (since the last success) */
int timeout; /*!< sched id of sip_reg_timeout */
@@ -849,10 +827,19 @@
struct sip_pvt *call; /*!< create a sip_pvt structure for each outbound "registration call" in progress */
int regstate; /*!< Registration state (see above) */
int callid_valid; /*!< 0 means we haven't chosen callid for this registry yet. */
+ char callid[80]; /*!< Global CallID for this registry */
unsigned int ocseq; /*!< Sequence number we got to for REGISTERs for this registry */
struct sockaddr_in us; /*!< Who the server thinks we are */
+
+ /* Saved headers */
+ char realm[MAXHOSTNAMELEN]; /*!< Authorization realm */
+ char nonce[256]; /*!< Authorization nonce */
+ char domain[MAXHOSTNAMELEN]; /*!< Authorization domain */
+ char opaque[256]; /*!< Opaque nonsense */
+ char qop[80]; /*!< Quality of Protection. */
int noncecount; /*!< Nonce-count */
- char lastmsg[256]; /*!< Last Message sent/received */
+
+ char lastmsg[256]; /*!< Last Message sent/received */
};
/*! \brief The user list: Users and friends ---*/
@@ -883,18 +870,17 @@
static time_t externexpire = 0;
static int externrefresh = 10;
static struct ast_ha *localaddr;
-static int callevents; /*!< Whether we send manager events or not */
/* The list of manual NOTIFY types we know how to send */
struct ast_config *notify_types;
-static struct sip_auth *authl = NULL; /*!< Authentication list */
+static struct sip_auth *authl; /*!< Authentication list */
static int transmit_response(struct sip_pvt *p, char *msg, struct sip_request *req);
static int transmit_response_with_sdp(struct sip_pvt *p, char *msg, struct sip_request *req, int retrans);
static int transmit_response_with_unsupported(struct sip_pvt *p, char *msg, struct sip_request *req, char *unsupported);
-static int transmit_response_with_auth(struct sip_pvt *p, char *msg, struct sip_request *req, const char *rand, int reliable, char *header, int stale);
+static int transmit_response_with_auth(struct sip_pvt *p, char *msg, struct sip_request *req, char *rand, int reliable, char *header, int stale);
static int transmit_request(struct sip_pvt *p, int sipmethod, int inc, int reliable, int newbranch);
static int transmit_request_with_auth(struct sip_pvt *p, int sipmethod, int inc, int reliable, int newbranch);
static int transmit_invite(struct sip_pvt *p, int sipmethod, int sendsdp, int init);
@@ -913,6 +899,7 @@
static struct sip_user *build_user(const char *name, struct ast_variable *v, int realtime);
static int sip_do_reload(void);
static int expire_register(void *data);
+static int callevents = 0;
static struct ast_channel *sip_request_call(const char *type, int format, void *data, int *cause);
static int sip_devicestate(void *data);
@@ -928,7 +915,7 @@
static int sip_senddigit(struct ast_channel *ast, char digit);
static int clear_realm_authentication(struct sip_auth *authlist); /* Clear realm authentication list (at reload) */
static struct sip_auth *add_realm_authentication(struct sip_auth *authlist, char *configuration, int lineno); /* Add realm authentication in list */
-static struct sip_auth *find_realm_authentication(struct sip_auth *authlist, const char *realm); /* Find authentication for a specific realm */
+static struct sip_auth *find_realm_authentication(struct sip_auth *authlist, char *realm); /* Find authentication for a specific realm */
static int check_sip_domain(const char *domain, char *context, size_t len); /* Check if domain is one of our local domains */
static void append_date(struct sip_request *req); /* Append date to SIP packet */
static int determine_firstline_parts(struct sip_request *req);
@@ -936,8 +923,6 @@
static const struct cfsubscription_types *find_subscription_type(enum subscriptiontype subtype);
static int transmit_state_notify(struct sip_pvt *p, int state, int full, int substate);
static char *gettag(struct sip_request *req, char *header, char *tagbuf, int tagbufsize);
-int find_sip_method(char *msg);
-unsigned int parse_sip_options(struct sip_pvt *pvt, char *supported);
/*! \brief Definition of this channel for PBX channel registration */
static const struct ast_channel_tech sip_tech = {
@@ -1046,7 +1031,7 @@
/*! \brief sip_debug_test_addr: See if we pass debug IP filter */
static inline int sip_debug_test_addr(struct sockaddr_in *addr)
{
- if (!sipdebug)
+ if (sipdebug == 0)
return 0;
if (debugaddr.sin_addr.s_addr) {
if (((ntohs(debugaddr.sin_port) != 0)
@@ -1060,7 +1045,7 @@
/*! \brief sip_debug_test_pvt: Test PVT for debugging output */
static inline int sip_debug_test_pvt(struct sip_pvt *p)
{
- if (!sipdebug)
+ if (sipdebug == 0)
return 0;
return sip_debug_test_addr(((ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE) ? &p->recv : &p->sa));
}
@@ -1086,15 +1071,15 @@
static void sip_destroy(struct sip_pvt *p);
/*! \brief build_via: Build a Via header for a request ---*/
-static void build_via(struct sip_pvt *p)
+static void build_via(struct sip_pvt *p, char *buf, int len)
{
char iabuf[INET_ADDRSTRLEN];
- /* Work around buggy UNIDEN UIP200 firmware */
- const char *rport = ast_test_flag(p, SIP_NAT) & SIP_NAT_RFC3581 ? ";rport" : "";
/* z9hG4bK is a magic cookie. See RFC 3261 section 8.1.1.7 */
- ast_string_field_build(p, via, "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x%s",
- ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch, rport);
+ if (ast_test_flag(p, SIP_NAT) & SIP_NAT_RFC3581)
+ snprintf(buf, len, "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x;rport", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch);
+ else /* Work around buggy UNIDEN UIP200 firmware */
+ snprintf(buf, len, "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch);
}
/*! \brief ast_sip_ouraddrfor: NAT fix - decide which IP address to use for ASterisk server? ---*/
@@ -1132,45 +1117,40 @@
return 0;
}
-/*! \brief append_history: Append to SIP dialog history
- \return Always returns 0 */
-#define append_history(p, event, fmt , args... ) append_history_full(p, "%-15s " fmt, event, ## args)
-
-static int append_history_full(struct sip_pvt *p, const char *fmt, ...)
- __attribute__ ((format (printf, 2, 3)));
-
-/*! \brief Append to SIP dialog history with arg list */
-static void append_history_va(struct sip_pvt *p, const char *fmt, va_list ap)
-{
- char buf[80], *c = buf; /* max history length */
- struct sip_history *hist;
- int l;
-
- vsnprintf(buf, sizeof(buf), fmt, ap);
- strsep(&c, "\r\n"); /* Trim up everything after \r or \n */
- l = strlen(buf) + 1;
- if (!(hist = ast_calloc(1, sizeof(*hist) + l)))
- return;
- if (!p->history && !(p->history = ast_calloc(1, sizeof(*p->history)))) {
- free(hist);
- return;
- }
- memcpy(hist->event, buf, l);
- AST_LIST_INSERT_TAIL(p->history, hist, list);
-}
-
-/*! \brief Append to SIP dialog history with arg list */
-static int append_history_full(struct sip_pvt *p, const char *fmt, ...)
-{
- va_list ap;
+/*! \brief append_history: Append to SIP dialog history */
+/* Always returns 0 */
+static int append_history(struct sip_pvt *p, const char *event, const char *data)
+{
+ struct sip_history *hist, *prev;
+ char *c;
if (!recordhistory || !p)
return 0;
- va_start(ap, fmt);
- append_history_va(p, fmt, ap);
- va_end(ap);
-
- return 0;
+ if(!(hist = malloc(sizeof(struct sip_history)))) {
+ ast_log(LOG_WARNING, "Can't allocate memory for history");
+ return 0;
+ }
+ memset(hist, 0, sizeof(struct sip_history));
+ snprintf(hist->event, sizeof(hist->event), "%-15s %s", event, data);
+ /* Trim up nicely */
+ c = hist->event;
+ while(*c) {
+ if ((*c == '\r') || (*c == '\n')) {
+ *c = '\0';
+ break;
+ }
+ c++;
+ }
+ /* Enqueue into history */
+ prev = p->history;
+ if (prev) {
+ while(prev->next)
+ prev = prev->next;
+ prev->next = hist;
+ } else {
+ p->history = hist;
+ }
+ return 0;
}
/*! \brief retrans_pkt: Retransmit SIP message if no answer ---*/
@@ -1184,6 +1164,8 @@
ast_mutex_lock(&pkt->owner->lock);
if (pkt->retrans < MAX_RETRANS) {
+ char buf[80];
+
pkt->retrans++;
if (!pkt->timer_t1) { /* Re-schedule using timer_a and timer_t1 */
if (sipdebug && option_debug > 3)
@@ -1215,19 +1197,22 @@
else
ast_verbose("Retransmitting #%d (no NAT) to %s:%d:\n%s\n---\n", pkt->retrans, ast_inet_ntoa(iabuf, sizeof(iabuf), pkt->owner->sa.sin_addr), ntohs(pkt->owner->sa.sin_port), pkt->data);
}
-
- append_history(pkt->owner, "ReTx", "%d %s", reschedule, pkt->data);
+ snprintf(buf, sizeof(buf), "ReTx %d", reschedule);
+
+ append_history(pkt->owner, buf, pkt->data);
__sip_xmit(pkt->owner, pkt->data, pkt->packetlen);
[... 5224 lines stripped ...]
More information about the svn-commits
mailing list