mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-02 11:58:40 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
38cf8c772c | ||
|
|
a0c8d474ca | ||
|
|
2bc528c2ce | ||
|
|
f8b2d69f5c | ||
|
|
ef4320cbf1 | ||
|
|
bee3a35b21 | ||
|
|
f4968a052a | ||
|
|
6ee2842b38 | ||
|
|
0936993140 | ||
|
|
c0c96428b1 | ||
|
|
a53f20eea7 | ||
|
|
a5bfe89dae | ||
|
|
194641486e | ||
|
|
c8714a6c76 | ||
|
|
aecdd19a5e |
1
.lastclean
Normal file
1
.lastclean
Normal file
@@ -0,0 +1 @@
|
||||
32
|
||||
@@ -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, ®->addr, NEW_FORCE, defaultsockfd);
|
||||
reg->callno = find_callno(0, 0, ®->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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user