Compare commits

...

15 Commits

Author SHA1 Message Date
Russell Bryant
38cf8c772c Fix a minor problem with the backport to 1.4.19
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/1.4.19.2@115888 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-05-13 18:50:13 +00:00
Russell Bryant
a0c8d474ca Merge rev 115565 from 1.4
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/1.4.19.2@115647 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-05-12 15:08:41 +00:00
Russell Bryant
2bc528c2ce Merge rev 114891 from 1.4
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/1.4.19.2@115643 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-05-12 15:07:30 +00:00
Russell Bryant
f8b2d69f5c Merge rev 114880 from 1.4
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/1.4.19.2@115640 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-05-12 15:06:33 +00:00
Russell Bryant
ef4320cbf1 update .version and ChangeLog
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/1.4.19.2@115632 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-05-12 15:03:35 +00:00
Russell Bryant
bee3a35b21 cp 1.4.19.1 1.4.19.2
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/1.4.19.2@115620 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-05-12 14:58:33 +00:00
Russell Bryant
f4968a052a Importing files for 1.4.19.1 release
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/1.4.19.1@114564 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-04-22 22:26:57 +00:00
Russell Bryant
6ee2842b38 When we receive a full frame that is supposed to contain our call number,
ensure that it has the correct one.
(closes issue #10078)
(AST-2008-006)


git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/1.4.19.1@114557 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-04-22 22:14:04 +00:00
Russell Bryant
0936993140 remove version files
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/1.4.19.1@114555 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-04-22 22:04:25 +00:00
Russell Bryant
c0c96428b1 create a tag for 1.4.19.1
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/1.4.19.1@114554 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-04-22 22:03:18 +00:00
Russell Bryant
a53f20eea7 update .version and ChangeLog
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/1.4.19@112286 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-04-01 19:27:36 +00:00
Russell Bryant
a5bfe89dae Create 1.4.19 tag from 1.4.19-rc4
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/1.4.19@112285 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-04-01 19:26:14 +00:00
Russell Bryant
194641486e Use autotagged externals
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/1.4.19-rc4@111666 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-03-28 16:44:15 +00:00
Russell Bryant
c8714a6c76 Importing files for 1.4.19-rc4 release
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/1.4.19-rc4@111665 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-03-28 16:43:52 +00:00
Russell Bryant
aecdd19a5e Creating tag for the release of asterisk-1.4.19-rc4
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/1.4.19-rc4@111664 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-03-28 16:43:07 +00:00
5 changed files with 17412 additions and 154 deletions

1
.lastclean Normal file
View File

@@ -0,0 +1 @@
32

1
.version Normal file
View File

@@ -0,0 +1 @@
1.4.19.2

17089
ChangeLog Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -127,9 +127,6 @@ static int nochecksums = 0;
#define DEFAULT_RETRY_TIME 1000
#define MEMORY_SIZE 100
#define DEFAULT_DROP 3
/* Flag to use with trunk calls, keeping these calls high up. It halves our effective use
but keeps the division between trunked and non-trunked better. */
#define TRUNK_CALL_START 0x4000
#define DEBUG_SUPPORT
@@ -151,8 +148,6 @@ static int maxauthreq = 3;
static int max_retries = 4;
static int ping_time = 21;
static int lagrq_time = 10;
static int maxtrunkcall = TRUNK_CALL_START;
static int maxnontrunkcall = 1;
static int maxjitterbuffer=1000;
static int resyncthreshold=1000;
static int maxjitterinterps=10;
@@ -811,8 +806,26 @@ static void jb_debug_output(const char *fmt, ...)
/* XXX We probably should use a mutex when working with this XXX */
static struct chan_iax2_pvt *iaxs[IAX_MAX_CALLS];
static ast_mutex_t iaxsl[IAX_MAX_CALLS];
static struct timeval lastused[IAX_MAX_CALLS];
static ast_mutex_t iaxsl[ARRAY_LEN(iaxs)];
static struct timeval lastused[ARRAY_LEN(iaxs)];
/*!
* \brief Another container of iax2_pvt structures
*
* Active IAX2 pvt structs are also stored in this container, if they are a part
* of an active call where we know the remote side's call number. The reason
* for this is that incoming media frames do not contain our call number. So,
* instead of having to iterate the entire iaxs array, we use this container to
* look up calls where the remote side is using a given call number.
*/
static struct ao2_container *iax_peercallno_pvts;
/* Flag to use with trunk calls, keeping these calls high up. It halves our effective use
but keeps the division between trunked and non-trunked better. */
#define TRUNK_CALL_START ARRAY_LEN(iaxs) / 2
static int maxtrunkcall = TRUNK_CALL_START;
static int maxnontrunkcall = 1;
static enum ast_bridge_result iax2_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
static int expire_registry(const void *data);
@@ -1181,16 +1194,179 @@ static int iax2_getpeername(struct sockaddr_in sin, char *host, int len)
return res;
}
static void iax2_destroy_helper(struct chan_iax2_pvt *pvt)
{
/* Decrement AUTHREQ count if needed */
if (ast_test_flag(pvt, IAX_MAXAUTHREQ)) {
struct iax2_user *user;
struct iax2_user tmp_user = {
.name = pvt->username,
};
user = ao2_find(users, &tmp_user, OBJ_POINTER);
if (user) {
ast_atomic_fetchadd_int(&user->curauthreq, -1);
user = user_unref(user);
}
ast_clear_flag(pvt, IAX_MAXAUTHREQ);
}
/* No more pings or lagrq's */
AST_SCHED_DEL(sched, pvt->pingid);
AST_SCHED_DEL(sched, pvt->lagid);
AST_SCHED_DEL(sched, pvt->autoid);
AST_SCHED_DEL(sched, pvt->authid);
AST_SCHED_DEL(sched, pvt->initid);
AST_SCHED_DEL(sched, pvt->jbid);
}
static void store_by_peercallno(struct chan_iax2_pvt *pvt)
{
if (!pvt->peercallno) {
ast_log(LOG_ERROR, "This should not be called without a peer call number.\n");
return;
}
ao2_link(iax_peercallno_pvts, pvt);
}
static void remove_by_peercallno(struct chan_iax2_pvt *pvt)
{
if (!pvt->peercallno) {
ast_log(LOG_ERROR, "This should not be called without a peer call number.\n");
return;
}
ao2_unlink(iax_peercallno_pvts, pvt);
}
static void update_max_trunk(void)
{
int max = TRUNK_CALL_START;
int x;
/* XXX Prolly don't need locks here XXX */
for (x = TRUNK_CALL_START; x < ARRAY_LEN(iaxs) - 1; x++) {
if (iaxs[x]) {
max = x + 1;
}
}
maxtrunkcall = max;
if (option_debug && iaxdebug)
ast_log(LOG_DEBUG, "New max trunk callno is %d\n", max);
}
static void iax2_frame_free(struct iax_frame *fr)
{
AST_SCHED_DEL(sched, fr->retrans);
iax_frame_free(fr);
}
static void iax2_destroy(int callno)
{
struct chan_iax2_pvt *pvt;
struct ast_channel *owner;
retry:
pvt = iaxs[callno];
gettimeofday(&lastused[callno], NULL);
owner = pvt ? pvt->owner : NULL;
if (owner) {
if (ast_mutex_trylock(&owner->lock)) {
ast_log(LOG_NOTICE, "Avoiding IAX destroy deadlock\n");
ast_mutex_unlock(&iaxsl[callno]);
usleep(1);
ast_mutex_lock(&iaxsl[callno]);
goto retry;
}
}
if (!owner) {
iaxs[callno] = NULL;
}
if (pvt) {
if (!owner) {
pvt->owner = NULL;
} else {
/* If there's an owner, prod it to give up */
/* It is ok to use ast_queue_hangup() here instead of iax2_queue_hangup()
* because we already hold the owner channel lock. */
ast_queue_hangup(owner);
}
if (pvt->peercallno) {
remove_by_peercallno(pvt);
}
if (!owner) {
ao2_ref(pvt, -1);
pvt = NULL;
}
}
if (owner) {
ast_mutex_unlock(&owner->lock);
}
if (callno & 0x4000) {
update_max_trunk();
}
}
static void pvt_destructor(void *obj)
{
struct chan_iax2_pvt *pvt = obj;
struct iax_frame *cur = NULL;
iax2_destroy_helper(pvt);
/* Already gone */
ast_set_flag(pvt, IAX_ALREADYGONE);
AST_LIST_LOCK(&iaxq.queue);
AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
/* Cancel any pending transmissions */
if (cur->callno == pvt->callno) {
cur->retries = -1;
}
}
AST_LIST_UNLOCK(&iaxq.queue);
if (pvt->reg) {
pvt->reg->callno = 0;
}
if (!pvt->owner) {
jb_frame frame;
if (pvt->vars) {
ast_variables_destroy(pvt->vars);
pvt->vars = NULL;
}
while (jb_getall(pvt->jb, &frame) == JB_OK) {
iax2_frame_free(frame.data);
}
jb_destroy(pvt->jb);
ast_string_field_free_memory(pvt);
}
}
static struct chan_iax2_pvt *new_iax(struct sockaddr_in *sin, const char *host)
{
struct chan_iax2_pvt *tmp;
jb_conf jbconf;
if (!(tmp = ast_calloc(1, sizeof(*tmp))))
if (!(tmp = ao2_alloc(sizeof(*tmp), pvt_destructor))) {
return NULL;
}
if (ast_string_field_init(tmp, 32)) {
free(tmp);
ao2_ref(tmp, -1);
tmp = NULL;
return NULL;
}
@@ -1239,13 +1415,13 @@ static struct iax_frame *iaxfrdup2(struct iax_frame *fr)
#define NEW_ALLOW 1
#define NEW_FORCE 2
static int match(struct sockaddr_in *sin, unsigned short callno, unsigned short dcallno, struct chan_iax2_pvt *cur)
static int match(struct sockaddr_in *sin, unsigned short callno, unsigned short dcallno, struct chan_iax2_pvt *cur, int full_frame)
{
if ((cur->addr.sin_addr.s_addr == sin->sin_addr.s_addr) &&
(cur->addr.sin_port == sin->sin_port)) {
/* This is the main host */
if ((cur->peercallno == callno) ||
((dcallno == cur->callno) && !cur->peercallno)) {
if ( (cur->peercallno == 0 || cur->peercallno == callno) &&
(full_frame ? dcallno == cur->callno : 1) ) {
/* That's us. Be sure we keep track of the peer call number */
return 1;
}
@@ -1259,20 +1435,6 @@ static int match(struct sockaddr_in *sin, unsigned short callno, unsigned short
return 0;
}
static void update_max_trunk(void)
{
int max = TRUNK_CALL_START;
int x;
/* XXX Prolly don't need locks here XXX */
for (x=TRUNK_CALL_START;x<IAX_MAX_CALLS - 1; x++) {
if (iaxs[x])
max = x + 1;
}
maxtrunkcall = max;
if (option_debug && iaxdebug)
ast_log(LOG_DEBUG, "New max trunk callno is %d\n", max);
}
static void update_max_nontrunk(void)
{
int max = 1;
@@ -1301,7 +1463,7 @@ static int make_trunk(unsigned short callno, int locked)
return -1;
}
gettimeofday(&now, NULL);
for (x=TRUNK_CALL_START;x<IAX_MAX_CALLS - 1; x++) {
for (x = TRUNK_CALL_START; x < ARRAY_LEN(iaxs) - 1; x++) {
ast_mutex_lock(&iaxsl[x]);
if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) {
iaxs[x] = iaxs[callno];
@@ -1321,7 +1483,7 @@ static int make_trunk(unsigned short callno, int locked)
}
ast_mutex_unlock(&iaxsl[x]);
}
if (x >= IAX_MAX_CALLS - 1) {
if (x >= ARRAY_LEN(iaxs) - 1) {
ast_log(LOG_WARNING, "Unable to trunk call: Insufficient space\n");
return -1;
}
@@ -1336,7 +1498,7 @@ static int make_trunk(unsigned short callno, int locked)
/*!
* \note Calling this function while holding another pvt lock can cause a deadlock.
*/
static int find_callno(unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int new, int sockfd)
static int find_callno(unsigned short callno, unsigned short dcallno, struct sockaddr_in *sin, int new, int sockfd, int full_frame)
{
int res = 0;
int x;
@@ -1344,12 +1506,31 @@ static int find_callno(unsigned short callno, unsigned short dcallno, struct soc
char host[80];
if (new <= NEW_ALLOW) {
if (callno) {
struct chan_iax2_pvt *pvt;
struct chan_iax2_pvt tmp_pvt = {
.callno = dcallno,
.peercallno = callno,
/* hack!! */
.frames_received = full_frame,
};
memcpy(&tmp_pvt.addr, sin, sizeof(tmp_pvt.addr));
if ((pvt = ao2_find(iax_peercallno_pvts, &tmp_pvt, OBJ_POINTER))) {
res = pvt->callno;
ao2_ref(pvt, -1);
pvt = NULL;
return res;
}
}
/* Look for an existing connection first */
for (x=1;(res < 1) && (x<maxnontrunkcall);x++) {
ast_mutex_lock(&iaxsl[x]);
if (iaxs[x]) {
/* Look for an exact match */
if (match(sin, callno, dcallno, iaxs[x])) {
if (match(sin, callno, dcallno, iaxs[x], full_frame)) {
res = x;
}
}
@@ -1359,7 +1540,7 @@ static int find_callno(unsigned short callno, unsigned short dcallno, struct soc
ast_mutex_lock(&iaxsl[x]);
if (iaxs[x]) {
/* Look for an exact match */
if (match(sin, callno, dcallno, iaxs[x])) {
if (match(sin, callno, dcallno, iaxs[x], full_frame)) {
res = x;
}
}
@@ -1367,6 +1548,8 @@ static int find_callno(unsigned short callno, unsigned short dcallno, struct soc
}
}
if ((res < 1) && (new >= NEW_ALLOW)) {
int start, found = 0;
/* It may seem odd that we look through the peer list for a name for
* this *incoming* call. Well, it is weird. However, users don't
* have an IP address/port number that we can match against. So,
@@ -1375,15 +1558,29 @@ static int find_callno(unsigned short callno, unsigned short dcallno, struct soc
* correct, but it will be changed if needed after authentication. */
if (!iax2_getpeername(*sin, host, sizeof(host)))
snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
gettimeofday(&now, NULL);
for (x=1;x<TRUNK_CALL_START;x++) {
now = ast_tvnow();
start = 1 + (ast_random() % (TRUNK_CALL_START - 1));
for (x = start; 1; x++) {
if (x == TRUNK_CALL_START) {
x = 0;
continue;
}
/* Find first unused call number that hasn't been used in a while */
ast_mutex_lock(&iaxsl[x]);
if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) break;
if (!iaxs[x] && ((now.tv_sec - lastused[x].tv_sec) > MIN_REUSE_TIME)) {
found = 1;
break;
}
ast_mutex_unlock(&iaxsl[x]);
if (x == start - 1) {
break;
}
}
/* We've still got lock held if we found a spot */
if (x >= TRUNK_CALL_START) {
if (x == start - 1 && !found) {
ast_log(LOG_WARNING, "No more space\n");
return 0;
}
@@ -1408,6 +1605,10 @@ static int find_callno(unsigned short callno, unsigned short dcallno, struct soc
ast_string_field_set(iaxs[x], accountcode, accountcode);
ast_string_field_set(iaxs[x], mohinterpret, mohinterpret);
ast_string_field_set(iaxs[x], mohsuggest, mohsuggest);
if (iaxs[x]->peercallno) {
store_by_peercallno(iaxs[x]);
}
} else {
ast_log(LOG_WARNING, "Out of resources\n");
ast_mutex_unlock(&iaxsl[x]);
@@ -1419,12 +1620,6 @@ static int find_callno(unsigned short callno, unsigned short dcallno, struct soc
return res;
}
static void iax2_frame_free(struct iax_frame *fr)
{
AST_SCHED_DEL(sched, fr->retrans);
iax_frame_free(fr);
}
/*!
* \brief Queue a frame to a call's owning asterisk channel
*
@@ -1889,32 +2084,6 @@ static int send_packet(struct iax_frame *f)
return res;
}
static void iax2_destroy_helper(struct chan_iax2_pvt *pvt)
{
/* Decrement AUTHREQ count if needed */
if (ast_test_flag(pvt, IAX_MAXAUTHREQ)) {
struct iax2_user *user;
struct iax2_user tmp_user = {
.name = pvt->username,
};
user = ao2_find(users, &tmp_user, OBJ_POINTER);
if (user) {
ast_atomic_fetchadd_int(&user->curauthreq, -1);
user_unref(user);
}
ast_clear_flag(pvt, IAX_MAXAUTHREQ);
}
/* No more pings or lagrq's */
AST_SCHED_DEL(sched, pvt->pingid);
AST_SCHED_DEL(sched, pvt->lagid);
AST_SCHED_DEL(sched, pvt->autoid);
AST_SCHED_DEL(sched, pvt->authid);
AST_SCHED_DEL(sched, pvt->initid);
AST_SCHED_DEL(sched, pvt->jbid);
}
/*!
* \note Since this function calls iax2_queue_hangup(), the pvt struct
* for the given call number may disappear during its execution.
@@ -1940,76 +2109,6 @@ static int iax2_predestroy(int callno)
return 0;
}
static void iax2_destroy(int callno)
{
struct chan_iax2_pvt *pvt;
struct iax_frame *cur;
struct ast_channel *owner;
retry:
pvt = iaxs[callno];
gettimeofday(&lastused[callno], NULL);
owner = pvt ? pvt->owner : NULL;
if (owner) {
if (ast_mutex_trylock(&owner->lock)) {
ast_log(LOG_NOTICE, "Avoiding IAX destroy deadlock\n");
ast_mutex_unlock(&iaxsl[callno]);
usleep(1);
ast_mutex_lock(&iaxsl[callno]);
goto retry;
}
}
if (!owner)
iaxs[callno] = NULL;
if (pvt) {
if (!owner)
pvt->owner = NULL;
iax2_destroy_helper(pvt);
/* Already gone */
ast_set_flag(pvt, IAX_ALREADYGONE);
if (owner) {
/* If there's an owner, prod it to give up */
/* It is ok to use ast_queue_hangup() here instead of iax2_queue_hangup()
* because we already hold the owner channel lock. */
ast_queue_hangup(owner);
}
AST_LIST_LOCK(&iaxq.queue);
AST_LIST_TRAVERSE(&iaxq.queue, cur, list) {
/* Cancel any pending transmissions */
if (cur->callno == pvt->callno)
cur->retries = -1;
}
AST_LIST_UNLOCK(&iaxq.queue);
if (pvt->reg)
pvt->reg->callno = 0;
if (!owner) {
jb_frame frame;
if (pvt->vars) {
ast_variables_destroy(pvt->vars);
pvt->vars = NULL;
}
while (jb_getall(pvt->jb, &frame) == JB_OK)
iax2_frame_free(frame.data);
jb_destroy(pvt->jb);
/* gotta free up the stringfields */
ast_string_field_free_memory(pvt);
free(pvt);
}
}
if (owner) {
ast_mutex_unlock(&owner->lock);
}
if (callno & 0x4000)
update_max_trunk();
}
static int update_packet(struct iax_frame *f)
{
/* Called with iaxsl lock held, and iaxs[callno] non-NULL */
@@ -3514,6 +3613,24 @@ static int iax2_indicate(struct ast_channel *c, int condition, const void *data,
ast_mutex_lock(&iaxsl[callno]);
pvt = iaxs[callno];
if (!pvt->peercallno) {
/* We don't know the remote side's call number, yet. :( */
int count = 10;
while (count-- && pvt && !pvt->peercallno) {
ast_mutex_unlock(&iaxsl[callno]);
usleep(1);
ast_mutex_lock(&iaxsl[callno]);
pvt = iaxs[callno];
}
if (pvt->peercallno) {
ast_log(LOG_NOTICE, "Yay, we didn't know the peercallno, but we were patient and got it.\n");
} else {
ast_log(LOG_NOTICE, "Damnit! We waited around and never got the peercallno ...\n");
res = -1;
goto done;
}
}
switch (condition) {
case AST_CONTROL_HOLD:
if (strcasecmp(pvt->mohinterpret, "passthrough")) {
@@ -4655,7 +4772,7 @@ static int iax2_show_channels(int fd, int argc, char *argv[])
if (argc != 3)
return RESULT_SHOWUSAGE;
ast_cli(fd, FORMAT2, "Channel", "Peer", "Username", "ID (Lo/Rem)", "Seq (Tx/Rx)", "Lag", "Jitter", "JitBuf", "Format");
for (x=0;x<IAX_MAX_CALLS;x++) {
for (x = 0; x < ARRAY_LEN(iaxs); x++) {
ast_mutex_lock(&iaxsl[x]);
if (iaxs[x]) {
int lag, jitter, localdelay;
@@ -4695,7 +4812,7 @@ static int ast_cli_netstats(struct mansession *s, int fd, int limit_fmt)
{
int x;
int numchans = 0;
for (x=0;x<IAX_MAX_CALLS;x++) {
for (x = 0; x < ARRAY_LEN(iaxs); x++) {
ast_mutex_lock(&iaxsl[x]);
if (iaxs[x]) {
int localjitter, localdelay, locallost, locallosspct, localdropped, localooo;
@@ -5695,7 +5812,13 @@ static int complete_transfer(int callno, struct iax_ies *ies)
pvt->rseqno = 0;
pvt->iseqno = 0;
pvt->aseqno = 0;
if (pvt->peercallno) {
remove_by_peercallno(pvt);
}
pvt->peercallno = peercallno;
store_by_peercallno(pvt);
pvt->transferring = TRANSFER_NONE;
pvt->svoiceformat = -1;
pvt->voiceformat = 0;
@@ -6848,7 +6971,7 @@ static int socket_process(struct iax2_thread *thread)
}
/* This is a video frame, get call number */
fr->callno = find_callno(ntohs(vh->callno) & ~0x8000, dcallno, &sin, new, fd);
fr->callno = find_callno(ntohs(vh->callno) & ~0x8000, dcallno, &sin, new, fd, 0);
minivid = 1;
} else if ((meta->zeros == 0) && !(ntohs(meta->metacmd) & 0x8000)) {
unsigned char metatype;
@@ -6906,7 +7029,7 @@ static int socket_process(struct iax2_thread *thread)
/* Stop if we don't have enough data */
if (len > res)
break;
fr->callno = find_callno(callno & ~IAX_FLAG_FULL, 0, &sin, NEW_PREVENT, fd);
fr->callno = find_callno(callno & ~IAX_FLAG_FULL, 0, &sin, NEW_PREVENT, fd, 0);
if (fr->callno) {
ast_mutex_lock(&iaxsl[fr->callno]);
/* If it's a valid call, deliver the contents. If not, we
@@ -6993,7 +7116,7 @@ static int socket_process(struct iax2_thread *thread)
}
if (!fr->callno)
fr->callno = find_callno(ntohs(mh->callno) & ~IAX_FLAG_FULL, dcallno, &sin, new, fd);
fr->callno = find_callno(ntohs(mh->callno) & ~IAX_FLAG_FULL, dcallno, &sin, new, fd, ntohs(mh->callno) & IAX_FLAG_FULL);
if (fr->callno > 0)
ast_mutex_lock(&iaxsl[fr->callno]);
@@ -7032,8 +7155,18 @@ static int socket_process(struct iax2_thread *thread)
if (!inaddrcmp(&sin, &iaxs[fr->callno]->addr) && !minivid &&
f.subclass != IAX_COMMAND_TXCNT && /* for attended transfer */
f.subclass != IAX_COMMAND_TXACC) /* for attended transfer */
iaxs[fr->callno]->peercallno = (unsigned short)(ntohs(mh->callno) & ~IAX_FLAG_FULL);
f.subclass != IAX_COMMAND_TXACC) { /* for attended transfer */
unsigned short new_peercallno;
new_peercallno = (unsigned short) (ntohs(mh->callno) & ~IAX_FLAG_FULL);
if (new_peercallno && new_peercallno != iaxs[fr->callno]->peercallno) {
if (iaxs[fr->callno]->peercallno) {
remove_by_peercallno(iaxs[fr->callno]);
}
iaxs[fr->callno]->peercallno = new_peercallno;
store_by_peercallno(iaxs[fr->callno]);
}
}
if (ntohs(mh->callno) & IAX_FLAG_FULL) {
if (option_debug && iaxdebug)
ast_log(LOG_DEBUG, "Received packet %d, (%d, %d)\n", fh->oseqno, f.frametype, f.subclass);
@@ -8481,7 +8614,7 @@ static int iax2_do_register(struct iax2_registry *reg)
if (!reg->callno) {
if (option_debug)
ast_log(LOG_DEBUG, "Allocate call number\n");
reg->callno = find_callno(0, 0, &reg->addr, NEW_FORCE, defaultsockfd);
reg->callno = find_callno(0, 0, &reg->addr, NEW_FORCE, defaultsockfd, 0);
if (reg->callno < 1) {
ast_log(LOG_WARNING, "Unable to create call for registration\n");
return -1;
@@ -8541,7 +8674,7 @@ static int iax2_provision(struct sockaddr_in *end, int sockfd, char *dest, const
memset(&ied, 0, sizeof(ied));
iax_ie_append_raw(&ied, IAX_IE_PROVISIONING, provdata.buf, provdata.pos);
callno = find_callno(0, 0, &sin, NEW_FORCE, cai.sockfd);
callno = find_callno(0, 0, &sin, NEW_FORCE, cai.sockfd, 0);
if (!callno)
return -1;
@@ -8683,7 +8816,7 @@ static int iax2_poke_peer(struct iax2_peer *peer, int heldcall)
}
if (heldcall)
ast_mutex_unlock(&iaxsl[heldcall]);
peer->callno = find_callno(0, 0, &peer->addr, NEW_FORCE, peer->sockfd);
peer->callno = find_callno(0, 0, &peer->addr, NEW_FORCE, peer->sockfd, 0);
if (heldcall)
ast_mutex_lock(&iaxsl[heldcall]);
if (peer->callno < 1) {
@@ -8763,7 +8896,7 @@ static struct ast_channel *iax2_request(const char *type, int format, void *data
if (pds.port)
sin.sin_port = htons(atoi(pds.port));
callno = find_callno(0, 0, &sin, NEW_FORCE, cai.sockfd);
callno = find_callno(0, 0, &sin, NEW_FORCE, cai.sockfd, 0);
if (callno < 1) {
ast_log(LOG_WARNING, "Unable to create call\n");
*cause = AST_CAUSE_CONGESTION;
@@ -10047,7 +10180,7 @@ static int cache_get_callno_locked(const char *data)
struct parsed_dial_string pds;
char *tmpstr;
for (x=0; x<IAX_MAX_CALLS; x++) {
for (x = 0; x < ARRAY_LEN(iaxs); x++) {
/* Look for an *exact match* call. Once a call is negotiated, it can only
look up entries for a single context */
if (!ast_mutex_trylock(&iaxsl[x])) {
@@ -10079,7 +10212,7 @@ static int cache_get_callno_locked(const char *data)
ast_log(LOG_DEBUG, "peer: %s, username: %s, password: %s, context: %s\n",
pds.peer, pds.username, pds.password, pds.context);
callno = find_callno(0, 0, &sin, NEW_FORCE, cai.sockfd);
callno = find_callno(0, 0, &sin, NEW_FORCE, cai.sockfd, 0);
if (callno < 1) {
ast_log(LOG_WARNING, "Unable to create call\n");
return -1;
@@ -10800,9 +10933,11 @@ static int __unload_module(void)
ast_netsock_release(netsock);
ast_netsock_release(outsock);
for (x=0;x<IAX_MAX_CALLS;x++)
if (iaxs[x])
for (x = 0; x < ARRAY_LEN(iaxs); x++) {
if (iaxs[x]) {
iax2_destroy(x);
}
}
ast_manager_unregister( "IAXpeers" );
ast_manager_unregister( "IAXnetstats" );
ast_unregister_application(papp);
@@ -10816,11 +10951,13 @@ static int __unload_module(void)
ast_mutex_destroy(&waresl.lock);
for (x = 0; x < IAX_MAX_CALLS; x++)
for (x = 0; x < ARRAY_LEN(iaxsl); x++) {
ast_mutex_destroy(&iaxsl[x]);
}
ao2_ref(peers, -1);
ao2_ref(users, -1);
ao2_ref(iax_peercallno_pvts, -1);
return 0;
}
@@ -10841,6 +10978,24 @@ static int peer_set_sock_cb(void *obj, void *arg, int flags)
return 0;
}
static int pvt_hash_cb(const void *obj, const int flags)
{
const struct chan_iax2_pvt *pvt = obj;
return pvt->peercallno;
}
static int pvt_cmp_cb(void *obj, void *arg, int flags)
{
struct chan_iax2_pvt *pvt = obj, *pvt2 = arg;
/* The frames_received field is used to hold whether we're matching
* against a full frame or not ... */
return match(&pvt2->addr, pvt2->peercallno, pvt2->callno, pvt,
pvt2->frames_received) ? CMP_MATCH : 0;
}
/*! \brief Load IAX2 module, load configuraiton ---*/
static int load_module(void)
{
@@ -10857,6 +11012,12 @@ static int load_module(void)
ao2_ref(peers, -1);
return AST_MODULE_LOAD_FAILURE;
}
iax_peercallno_pvts = ao2_container_alloc(IAX_MAX_CALLS, pvt_hash_cb, pvt_cmp_cb);
if (!iax_peercallno_pvts) {
ao2_ref(peers, -1);
ao2_ref(users, -1);
return AST_MODULE_LOAD_FAILURE;
}
ast_custom_function_register(&iaxpeer_function);
@@ -10876,8 +11037,9 @@ static int load_module(void)
memset(iaxs, 0, sizeof(iaxs));
for (x=0;x<IAX_MAX_CALLS;x++)
for (x = 0; x < ARRAY_LEN(iaxsl); x++) {
ast_mutex_init(&iaxsl[x]);
}
ast_cond_init(&sched_cond, NULL);

View File

@@ -17,7 +17,12 @@
/* Max version of IAX protocol we support */
#define IAX_PROTO_VERSION 2
/* NOTE: IT IS CRITICAL THAT IAX_MAX_CALLS BE A POWER OF 2. */
#if defined(LOW_MEMORY)
#define IAX_MAX_CALLS 2048
#else
#define IAX_MAX_CALLS 32768
#endif
#define IAX_FLAG_FULL 0x8000