Use call numbers instead of pointers in IAX2

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@2186 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.0
Mark Spencer 22 years ago
parent e2ecedfa70
commit cc894e6100

@ -71,6 +71,8 @@
#define BRIDGE_OPTIMIZATION #define BRIDGE_OPTIMIZATION
#define PTR_TO_CALLNO(a) ((unsigned short)(unsigned long)(a))
#define CALLNO_TO_PTR(a) ((void *)(unsigned long)(a))
#define DEFAULT_RETRY_TIME 1000 #define DEFAULT_RETRY_TIME 1000
#define MEMORY_SIZE 100 #define MEMORY_SIZE 100
@ -480,7 +482,7 @@ static struct timeval lastused[IAX_MAX_CALLS];
static int send_command(struct chan_iax2_pvt *, char, int, unsigned int, char *, int, int); static int send_command(struct chan_iax2_pvt *, char, int, unsigned int, char *, int, int);
static int send_command_locked(struct chan_iax2_pvt *, char, int, unsigned int, char *, int, int); static int send_command_locked(unsigned short callno, char, int, unsigned int, char *, int, int);
static int send_command_immediate(struct chan_iax2_pvt *, char, int, unsigned int, char *, int, int); static int send_command_immediate(struct chan_iax2_pvt *, char, int, unsigned int, char *, int, int);
static int send_command_final(struct chan_iax2_pvt *, char, int, unsigned int, char *, int, int); static int send_command_final(struct chan_iax2_pvt *, char, int, unsigned int, char *, int, int);
static int send_command_transfer(struct chan_iax2_pvt *, char, int, unsigned int, char *, int); static int send_command_transfer(struct chan_iax2_pvt *, char, int, unsigned int, char *, int);
@ -1499,30 +1501,35 @@ static int iax2_transmit(struct iax_frame *fr)
static int iax2_digit(struct ast_channel *c, char digit) static int iax2_digit(struct ast_channel *c, char digit)
{ {
return send_command_locked(c->pvt->pvt, AST_FRAME_DTMF, digit, 0, NULL, 0, -1); return send_command_locked(PTR_TO_CALLNO(c->pvt->pvt), AST_FRAME_DTMF, digit, 0, NULL, 0, -1);
} }
static int iax2_sendtext(struct ast_channel *c, char *text) static int iax2_sendtext(struct ast_channel *c, char *text)
{ {
return send_command_locked(c->pvt->pvt, AST_FRAME_TEXT, return send_command_locked(PTR_TO_CALLNO(c->pvt->pvt), AST_FRAME_TEXT,
0, 0, text, strlen(text) + 1, -1); 0, 0, text, strlen(text) + 1, -1);
} }
static int iax2_sendimage(struct ast_channel *c, struct ast_frame *img) static int iax2_sendimage(struct ast_channel *c, struct ast_frame *img)
{ {
return send_command_locked(c->pvt->pvt, AST_FRAME_IMAGE, img->subclass, 0, img->data, img->datalen, -1); return send_command_locked(PTR_TO_CALLNO(c->pvt->pvt), AST_FRAME_IMAGE, img->subclass, 0, img->data, img->datalen, -1);
} }
static int iax2_sendhtml(struct ast_channel *c, int subclass, char *data, int datalen) static int iax2_sendhtml(struct ast_channel *c, int subclass, char *data, int datalen)
{ {
return send_command_locked(c->pvt->pvt, AST_FRAME_HTML, subclass, 0, data, datalen, -1); return send_command_locked(PTR_TO_CALLNO(c->pvt->pvt), AST_FRAME_HTML, subclass, 0, data, datalen, -1);
} }
static int iax2_fixup(struct ast_channel *oldchannel, struct ast_channel *newchan) static int iax2_fixup(struct ast_channel *oldchannel, struct ast_channel *newchan)
{ {
struct chan_iax2_pvt *pvt = newchan->pvt->pvt; unsigned short callno = PTR_TO_CALLNO(newchan->pvt->pvt);
pvt->owner = newchan; ast_mutex_lock(&iaxsl[callno]);
if (iaxs[callno])
iaxs[callno]->owner = newchan;
else
ast_log(LOG_WARNING, "Uh, this isn't a good sign...\n");
ast_mutex_unlock(&iaxsl[callno]);
return 0; return 0;
} }
@ -1747,7 +1754,7 @@ static int create_addr(struct sockaddr_in *sin, int *capability, int *sendani, i
static int auto_congest(void *nothing) static int auto_congest(void *nothing)
{ {
int callno = (int)(long)(nothing); int callno = PTR_TO_CALLNO(nothing);
struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_CONGESTION }; struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_CONGESTION };
ast_mutex_lock(&iaxsl[callno]); ast_mutex_lock(&iaxsl[callno]);
if (iaxs[callno]) { if (iaxs[callno]) {
@ -1791,7 +1798,7 @@ static int iax2_call(struct ast_channel *c, char *dest, int timeout)
char context[AST_MAX_EXTENSION] =""; char context[AST_MAX_EXTENSION] ="";
char *portno = NULL; char *portno = NULL;
char *opts = ""; char *opts = "";
struct chan_iax2_pvt *p = c->pvt->pvt; unsigned short callno = PTR_TO_CALLNO(c->pvt->pvt);
char *stringp=NULL; char *stringp=NULL;
char storedsecret[80]; char storedsecret[80];
if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) { if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) {
@ -1863,7 +1870,7 @@ static int iax2_call(struct ast_channel *c, char *dest, int timeout)
iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, l); iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, l);
if (n) if (n)
iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, n); iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, n);
if (p->sendani && c->ani) { if (iaxs[callno]->sendani && c->ani) {
l = n = NULL; l = n = NULL;
strncpy(cid, c->ani, sizeof(cid) - 1); strncpy(cid, c->ani, sizeof(cid) - 1);
ast_callerid_parse(cid, &n, &l); ast_callerid_parse(cid, &n, &l);
@ -1882,18 +1889,19 @@ static int iax2_call(struct ast_channel *c, char *dest, int timeout)
iax_ie_append_str(&ied, IAX_IE_USERNAME, username); iax_ie_append_str(&ied, IAX_IE_USERNAME, username);
if (!secret && strlen(storedsecret)) if (!secret && strlen(storedsecret))
secret = storedsecret; secret = storedsecret;
ast_mutex_lock(&iaxsl[callno]);
if (secret) { if (secret) {
if (secret[0] == '[') { if (secret[0] == '[') {
/* This is an RSA key, not a normal secret */ /* This is an RSA key, not a normal secret */
strncpy(p->outkey, secret + 1, sizeof(p->secret)-1); strncpy(iaxs[callno]->outkey, secret + 1, sizeof(iaxs[callno]->secret)-1);
if (strlen(p->outkey)) { if (strlen(iaxs[callno]->outkey)) {
p->outkey[strlen(p->outkey) - 1] = '\0'; iaxs[callno]->outkey[strlen(iaxs[callno]->outkey) - 1] = '\0';
} }
} else } else
strncpy(p->secret, secret, sizeof(p->secret)-1); strncpy(iaxs[callno]->secret, secret, sizeof(iaxs[callno]->secret)-1);
} }
iax_ie_append_int(&ied, IAX_IE_FORMAT, c->nativeformats); iax_ie_append_int(&ied, IAX_IE_FORMAT, c->nativeformats);
iax_ie_append_int(&ied, IAX_IE_CAPABILITY, p->capability); iax_ie_append_int(&ied, IAX_IE_CAPABILITY, iaxs[callno]->capability);
iax_ie_append_short(&ied, IAX_IE_ADSICPE, c->adsicpe); iax_ie_append_short(&ied, IAX_IE_ADSICPE, c->adsicpe);
iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime()); iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime());
/* Transmit the string in a "NEW" request */ /* Transmit the string in a "NEW" request */
@ -1902,13 +1910,14 @@ static int iax2_call(struct ast_channel *c, char *dest, int timeout)
if (option_verbose > 2) if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Calling using options '%s'\n", requeststr); ast_verbose(VERBOSE_PREFIX_3 "Calling using options '%s'\n", requeststr);
#endif #endif
if (p->maxtime) { if (iaxs[callno]->maxtime) {
/* Initialize pingtime and auto-congest time */ /* Initialize pingtime and auto-congest time */
p->pingtime = p->maxtime / 2; iaxs[callno]->pingtime = iaxs[callno]->maxtime / 2;
p->initid = ast_sched_add(sched, p->maxtime * 2, auto_congest, (void *)(long)p->callno); iaxs[callno]->initid = ast_sched_add(sched, iaxs[callno]->maxtime * 2, auto_congest, CALLNO_TO_PTR(callno));
} }
send_command_locked(p, AST_FRAME_IAX, send_command(iaxs[callno], AST_FRAME_IAX,
IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1); IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1);
ast_mutex_unlock(&iaxsl[callno]);
ast_setstate(c, AST_STATE_RINGING); ast_setstate(c, AST_STATE_RINGING);
return 0; return 0;
} }
@ -1916,16 +1925,15 @@ static int iax2_call(struct ast_channel *c, char *dest, int timeout)
static int iax2_hangup(struct ast_channel *c) static int iax2_hangup(struct ast_channel *c)
{ {
struct chan_iax2_pvt *pvt = c->pvt->pvt; struct chan_iax2_pvt *pvt = c->pvt->pvt;
unsigned short callno = PTR_TO_CALLNO(c->pvt->pvt);
int alreadygone; int alreadygone;
int callno;
if (pvt) {
callno = pvt->callno;
ast_mutex_lock(&iaxsl[callno]); ast_mutex_lock(&iaxsl[callno]);
if (callno && iaxs[callno]) {
ast_log(LOG_DEBUG, "We're hanging up %s now...\n", c->name); ast_log(LOG_DEBUG, "We're hanging up %s now...\n", c->name);
alreadygone = pvt->alreadygone; alreadygone = iaxs[callno]->alreadygone;
/* Send the hangup unless we have had a transmission error or are already gone */ /* Send the hangup unless we have had a transmission error or are already gone */
if (!pvt->error && !alreadygone) if (!pvt->error && !alreadygone)
send_command_final(pvt, AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, NULL, 0, -1); send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, NULL, 0, -1);
/* Explicitly predestroy it */ /* Explicitly predestroy it */
iax2_predestroy_nolock(callno); iax2_predestroy_nolock(callno);
/* If we were already gone to begin with, destroy us now */ /* If we were already gone to begin with, destroy us now */
@ -1933,8 +1941,8 @@ static int iax2_hangup(struct ast_channel *c)
ast_log(LOG_DEBUG, "Really destroying %s now...\n", c->name); ast_log(LOG_DEBUG, "Really destroying %s now...\n", c->name);
iax2_destroy_nolock(callno); iax2_destroy_nolock(callno);
} }
ast_mutex_unlock(&iaxsl[callno]);
} }
ast_mutex_unlock(&iaxsl[callno]);
if (option_verbose > 2) if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Hungup '%s'\n", c->name); ast_verbose(VERBOSE_PREFIX_3 "Hungup '%s'\n", c->name);
return 0; return 0;
@ -1949,7 +1957,7 @@ static int iax2_setoption(struct ast_channel *c, int option, void *data, int dat
h->flag = AST_OPTION_FLAG_REQUEST; h->flag = AST_OPTION_FLAG_REQUEST;
h->option = htons(option); h->option = htons(option);
memcpy(h->data, data, datalen); memcpy(h->data, data, datalen);
res = send_command_locked((struct chan_iax2_pvt *)c->pvt->pvt, AST_FRAME_CONTROL, res = send_command_locked(PTR_TO_CALLNO(c->pvt->pvt), AST_FRAME_CONTROL,
AST_CONTROL_OPTION, 0, (char *)h, datalen + sizeof(struct ast_option_header), -1); AST_CONTROL_OPTION, 0, (char *)h, datalen + sizeof(struct ast_option_header), -1);
free(h); free(h);
return res; return res;
@ -1957,6 +1965,7 @@ static int iax2_setoption(struct ast_channel *c, int option, void *data, int dat
ast_log(LOG_WARNING, "Out of memory\n"); ast_log(LOG_WARNING, "Out of memory\n");
return -1; return -1;
} }
static struct ast_frame *iax2_read(struct ast_channel *c) static struct ast_frame *iax2_read(struct ast_channel *c)
{ {
static struct ast_frame f = { AST_FRAME_NULL, }; static struct ast_frame f = { AST_FRAME_NULL, };
@ -1964,49 +1973,47 @@ static struct ast_frame *iax2_read(struct ast_channel *c)
return &f; return &f;
} }
static int iax2_start_transfer(struct ast_channel *c0, struct ast_channel *c1) static int iax2_start_transfer(unsigned short callno0, unsigned short callno1)
{ {
int res; int res;
struct iax_ie_data ied0; struct iax_ie_data ied0;
struct iax_ie_data ied1; struct iax_ie_data ied1;
struct chan_iax2_pvt *p0 = c0->pvt->pvt;
struct chan_iax2_pvt *p1 = c1->pvt->pvt;
unsigned int transferid = rand(); unsigned int transferid = rand();
memset(&ied0, 0, sizeof(ied0)); memset(&ied0, 0, sizeof(ied0));
iax_ie_append_addr(&ied0, IAX_IE_APPARENT_ADDR, &p1->addr); iax_ie_append_addr(&ied0, IAX_IE_APPARENT_ADDR, &iaxs[callno1]->addr);
iax_ie_append_short(&ied0, IAX_IE_CALLNO, p1->peercallno); iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[callno1]->peercallno);
iax_ie_append_int(&ied0, IAX_IE_TRANSFERID, transferid); iax_ie_append_int(&ied0, IAX_IE_TRANSFERID, transferid);
memset(&ied1, 0, sizeof(ied1)); memset(&ied1, 0, sizeof(ied1));
iax_ie_append_addr(&ied1, IAX_IE_APPARENT_ADDR, &p0->addr); iax_ie_append_addr(&ied1, IAX_IE_APPARENT_ADDR, &iaxs[callno0]->addr);
iax_ie_append_short(&ied1, IAX_IE_CALLNO, p0->peercallno); iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[callno0]->peercallno);
iax_ie_append_int(&ied1, IAX_IE_TRANSFERID, transferid); iax_ie_append_int(&ied1, IAX_IE_TRANSFERID, transferid);
res = send_command(p0, AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied0.buf, ied0.pos, -1); res = send_command(iaxs[callno0], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied0.buf, ied0.pos, -1);
if (res) if (res)
return -1; return -1;
res = send_command(p1, AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied1.buf, ied1.pos, -1); res = send_command(iaxs[callno1], AST_FRAME_IAX, IAX_COMMAND_TXREQ, 0, ied1.buf, ied1.pos, -1);
if (res) if (res)
return -1; return -1;
p0->transferring = TRANSFER_BEGIN; iaxs[callno0]->transferring = TRANSFER_BEGIN;
p1->transferring = TRANSFER_BEGIN; iaxs[callno1]->transferring = TRANSFER_BEGIN;
return 0; return 0;
} }
static void lock_both(struct chan_iax2_pvt *p0, struct chan_iax2_pvt *p1) static void lock_both(unsigned short callno0, unsigned short callno1)
{ {
ast_mutex_lock(&iaxsl[p0->callno]); ast_mutex_lock(&iaxsl[callno0]);
while (ast_mutex_trylock(&iaxsl[p1->callno])) { while (ast_mutex_trylock(&iaxsl[callno1])) {
ast_mutex_unlock(&iaxsl[p0->callno]); ast_mutex_unlock(&iaxsl[callno0]);
usleep(10); usleep(10);
ast_mutex_lock(&iaxsl[p0->callno]); ast_mutex_lock(&iaxsl[callno0]);
} }
} }
static void unlock_both(struct chan_iax2_pvt *p0, struct chan_iax2_pvt *p1) static void unlock_both(unsigned short callno0, unsigned short callno1)
{ {
ast_mutex_unlock(&iaxsl[p1->callno]); ast_mutex_unlock(&iaxsl[callno1]);
ast_mutex_unlock(&iaxsl[p0->callno]); ast_mutex_unlock(&iaxsl[callno0]);
} }
static int iax2_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc) static int iax2_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc)
@ -2017,15 +2024,15 @@ static int iax2_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
int res = -1; int res = -1;
int transferstarted=0; int transferstarted=0;
struct ast_frame *f; struct ast_frame *f;
struct chan_iax2_pvt *p0 = c0->pvt->pvt; unsigned short callno0 = PTR_TO_CALLNO(c0->pvt->pvt);
struct chan_iax2_pvt *p1 = c1->pvt->pvt; unsigned short callno1 = PTR_TO_CALLNO(c1->pvt->pvt);
struct timeval waittimer = {0, 0}, tv; struct timeval waittimer = {0, 0}, tv;
lock_both(p0, p1); lock_both(callno0, callno1);
/* Put them in native bridge mode */ /* Put them in native bridge mode */
p0->bridgecallno = p1->callno; iaxs[callno0]->bridgecallno = callno1;
p1->bridgecallno = p0->callno; iaxs[callno1]->bridgecallno = callno0;
unlock_both(p0, p1); unlock_both(callno0, callno1);
/* If not, try to bridge until we can execute a transfer, if we can */ /* If not, try to bridge until we can execute a transfer, if we can */
cs[0] = c0; cs[0] = c0;
@ -2037,34 +2044,34 @@ static int iax2_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
ast_verbose(VERBOSE_PREFIX_3 "Can't masquerade, we're different...\n"); ast_verbose(VERBOSE_PREFIX_3 "Can't masquerade, we're different...\n");
/* Remove from native mode */ /* Remove from native mode */
if (c0->type == type) { if (c0->type == type) {
ast_mutex_lock(&iaxsl[p0->callno]); ast_mutex_lock(&iaxsl[callno0]);
p0->bridgecallno = 0; iaxs[callno0]->bridgecallno = 0;
ast_mutex_unlock(&iaxsl[p0->callno]); ast_mutex_unlock(&iaxsl[callno0]);
} }
if (c1->type == type) { if (c1->type == type) {
ast_mutex_lock(&iaxsl[p1->callno]); ast_mutex_lock(&iaxsl[callno1]);
p1->bridgecallno = 0; iaxs[callno1]->bridgecallno = 0;
ast_mutex_unlock(&iaxsl[p1->callno]); ast_mutex_unlock(&iaxsl[callno1]);
} }
return -2; return -2;
} }
if (c0->nativeformats != c1->nativeformats) { if (c0->nativeformats != c1->nativeformats) {
ast_verbose(VERBOSE_PREFIX_3 "Operating with different codecs, can't native bridge...\n"); ast_verbose(VERBOSE_PREFIX_3 "Operating with different codecs, can't native bridge...\n");
/* Remove from native mode */ /* Remove from native mode */
lock_both(p0, p1); lock_both(callno0, callno1);
p0->bridgecallno = 0; iaxs[callno0]->bridgecallno = 0;
p1->bridgecallno = 0; iaxs[callno1]->bridgecallno = 0;
unlock_both(p0, p1); unlock_both(callno0, callno1);
return -2; return -2;
} }
/* check if transfered and if we really want native bridging */ /* check if transfered and if we really want native bridging */
if (!transferstarted && !p0->notransfer && !p1->notransfer) { if (!transferstarted && !iaxs[callno0]->notransfer && !iaxs[callno1]->notransfer) {
/* Try the transfer */ /* Try the transfer */
if (iax2_start_transfer(c0, c1)) if (iax2_start_transfer(callno0, callno1))
ast_log(LOG_WARNING, "Unable to start the transfer\n"); ast_log(LOG_WARNING, "Unable to start the transfer\n");
transferstarted = 1; transferstarted = 1;
} }
if ((p0->transferring == TRANSFER_RELEASED) && (p1->transferring == TRANSFER_RELEASED)) { if ((iaxs[callno0]->transferring == TRANSFER_RELEASED) && (iaxs[callno1]->transferring == TRANSFER_RELEASED)) {
/* Call has been transferred. We're no longer involved */ /* Call has been transferred. We're no longer involved */
gettimeofday(&tv, NULL); gettimeofday(&tv, NULL);
if (!waittimer.tv_sec && !waittimer.tv_usec) { if (!waittimer.tv_sec && !waittimer.tv_usec) {
@ -2150,32 +2157,32 @@ tackygoto:
cs[0] = cs[1]; cs[0] = cs[1];
cs[1] = cs[2]; cs[1] = cs[2];
} }
lock_both(p0, p1); lock_both(callno0, callno1);
p0->bridgecallno = 0; iaxs[callno0]->bridgecallno = 0;
p1->bridgecallno = 0; iaxs[callno1]->bridgecallno = 0;
unlock_both(p0, p1); unlock_both(callno0, callno1);
return res; return res;
} }
static int iax2_answer(struct ast_channel *c) static int iax2_answer(struct ast_channel *c)
{ {
struct chan_iax2_pvt *pvt = c->pvt->pvt; unsigned short callno = PTR_TO_CALLNO(c->pvt->pvt);
if (option_debug) if (option_debug)
ast_log(LOG_DEBUG, "Answering\n"); ast_log(LOG_DEBUG, "Answering\n");
return send_command(pvt, AST_FRAME_CONTROL, AST_CONTROL_ANSWER, 0, NULL, 0, -1); return send_command_locked(callno, AST_FRAME_CONTROL, AST_CONTROL_ANSWER, 0, NULL, 0, -1);
} }
static int iax2_indicate(struct ast_channel *c, int condition) static int iax2_indicate(struct ast_channel *c, int condition)
{ {
struct chan_iax2_pvt *pvt = c->pvt->pvt; unsigned short callno = PTR_TO_CALLNO(c->pvt->pvt);
if (option_debug) if (option_debug)
ast_log(LOG_DEBUG, "Indicating condition %d\n", condition); ast_log(LOG_DEBUG, "Indicating condition %d\n", condition);
return send_command(pvt, AST_FRAME_CONTROL, condition, 0, NULL, 0, -1); return send_command_locked(callno, AST_FRAME_CONTROL, condition, 0, NULL, 0, -1);
} }
static int iax2_transfer(struct ast_channel *c, char *dest) static int iax2_transfer(struct ast_channel *c, char *dest)
{ {
struct chan_iax2_pvt *pvt = c->pvt->pvt; unsigned short callno = PTR_TO_CALLNO(c->pvt->pvt);
struct iax_ie_data ied; struct iax_ie_data ied;
char tmp[256] = "", *context; char tmp[256] = "", *context;
strncpy(tmp, dest, sizeof(tmp) - 1); strncpy(tmp, dest, sizeof(tmp) - 1);
@ -2190,7 +2197,7 @@ static int iax2_transfer(struct ast_channel *c, char *dest)
iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context); iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context);
if (option_debug) if (option_debug)
ast_log(LOG_DEBUG, "Transferring '%s' to '%s'\n", c->name, dest); ast_log(LOG_DEBUG, "Transferring '%s' to '%s'\n", c->name, dest);
return send_command(pvt, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1); return send_command_locked(callno, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1);
} }
@ -2769,27 +2776,31 @@ static struct ast_cli_entry cli_no_debug =
static int iax2_write(struct ast_channel *c, struct ast_frame *f) static int iax2_write(struct ast_channel *c, struct ast_frame *f)
{ {
struct chan_iax2_pvt *i = c->pvt->pvt; unsigned short callno = PTR_TO_CALLNO(c->pvt->pvt);
if (!i) int res = -1;
return -1; ast_mutex_lock(&iaxsl[callno]);
if (iaxs[callno]) {
/* If there's an outstanding error, return failure now */ /* If there's an outstanding error, return failure now */
if (i->error) { if (!iaxs[callno]->error) {
if (iaxs[callno]->alreadygone)
res = 0;
/* Don't waste bandwidth sending null frames */
else if (f->frametype == AST_FRAME_NULL)
res = 0;
else if ((f->frametype == AST_FRAME_VOICE) && iaxs[callno]->quelch)
res = 0;
else if (!(iaxs[callno]->state & IAX_STATE_STARTED))
res = 0;
else
/* Simple, just queue for transmission */
res = iax2_send(iaxs[callno], f, 0, -1, 0, 0, 0);
} else {
ast_log(LOG_DEBUG, "Write error: %s\n", strerror(errno)); ast_log(LOG_DEBUG, "Write error: %s\n", strerror(errno));
return -1; }
} }
/* If it's already gone, just return */ /* If it's already gone, just return */
if (i->alreadygone) ast_mutex_unlock(&iaxsl[callno]);
return 0; return res;
/* Don't waste bandwidth sending null frames */
if (f->frametype == AST_FRAME_NULL)
return 0;
/* If we're quelching voice, don't bother sending it */
if ((f->frametype == AST_FRAME_VOICE) && i->quelch)
return 0;
if (!(i->state & IAX_STATE_STARTED))
return 0;
/* Simple, just queue for transmission */
return iax2_send(i, f, 0, -1, 0, 0, 0);
} }
static int __send_command(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, char *data, int datalen, int seqno, static int __send_command(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, char *data, int datalen, int seqno,
@ -2812,12 +2823,12 @@ static int send_command(struct chan_iax2_pvt *i, char type, int command, unsigne
return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0); return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0);
} }
static int send_command_locked(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, char *data, int datalen, int seqno) static int send_command_locked(unsigned short callno, char type, int command, unsigned int ts, char *data, int datalen, int seqno)
{ {
int res; int res;
ast_mutex_lock(&iaxsl[i->callno]); ast_mutex_lock(&iaxsl[callno]);
res = send_command(i, type, command, ts, data, datalen, seqno); res = send_command(iaxs[callno], type, command, ts, data, datalen, seqno);
ast_mutex_unlock(&iaxsl[i->callno]); ast_mutex_unlock(&iaxsl[callno]);
return res; return res;
} }

Loading…
Cancel
Save