diff options
author | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2004-01-11 15:57:42 +0000 |
---|---|---|
committer | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2004-01-11 15:57:42 +0000 |
commit | e2fda4b720e00418c83b3bdddb783f18e878f162 (patch) | |
tree | 6dbebd7ac7fceb586fd1bf10f0029b52e070e86e /channels | |
parent | d32fb2bb893f22e0f354336bc14c8071248cecf5 (diff) |
Locking changes for IAX2
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@1943 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rwxr-xr-x | channels/chan_iax2.c | 47 |
1 files changed, 39 insertions, 8 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 02e46adef..1f4e10205 100755 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -477,6 +477,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_locked(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_transfer(struct chan_iax2_pvt *, char, int, unsigned int, char *, int); @@ -1493,24 +1494,24 @@ static int iax2_transmit(struct iax_frame *fr) static int iax2_digit(struct ast_channel *c, char digit) { - return send_command(c->pvt->pvt, AST_FRAME_DTMF, digit, 0, NULL, 0, -1); + return send_command_locked(c->pvt->pvt, AST_FRAME_DTMF, digit, 0, NULL, 0, -1); } static int iax2_sendtext(struct ast_channel *c, char *text) { - return send_command(c->pvt->pvt, AST_FRAME_TEXT, + return send_command_locked(c->pvt->pvt, AST_FRAME_TEXT, 0, 0, text, strlen(text) + 1, -1); } static int iax2_sendimage(struct ast_channel *c, struct ast_frame *img) { - return send_command(c->pvt->pvt, AST_FRAME_IMAGE, img->subclass, 0, img->data, img->datalen, -1); + return send_command_locked(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) { - return send_command(c->pvt->pvt, AST_FRAME_HTML, subclass, 0, data, datalen, -1); + return send_command_locked(c->pvt->pvt, AST_FRAME_HTML, subclass, 0, data, datalen, -1); } static int iax2_fixup(struct ast_channel *oldchannel, struct ast_channel *newchan) @@ -1897,7 +1898,7 @@ static int iax2_call(struct ast_channel *c, char *dest, int timeout) p->pingtime = p->maxtime / 2; p->initid = ast_sched_add(sched, p->maxtime * 2, auto_congest, (void *)(long)p->callno); } - send_command(p, AST_FRAME_IAX, + send_command_locked(p, AST_FRAME_IAX, IAX_COMMAND_NEW, 0, ied.buf, ied.pos, -1); ast_setstate(c, AST_STATE_RINGING); return 0; @@ -1939,7 +1940,7 @@ static int iax2_setoption(struct ast_channel *c, int option, void *data, int dat h->flag = AST_OPTION_FLAG_REQUEST; h->option = htons(option); memcpy(h->data, data, datalen); - res = send_command((struct chan_iax2_pvt *)c->pvt->pvt, AST_FRAME_CONTROL, + res = send_command_locked((struct chan_iax2_pvt *)c->pvt->pvt, AST_FRAME_CONTROL, AST_CONTROL_OPTION, 0, (char *)h, datalen + sizeof(struct ast_option_header), -1); free(h); return res; @@ -1983,6 +1984,22 @@ static int iax2_start_transfer(struct ast_channel *c0, struct ast_channel *c1) return 0; } +static void lock_both(struct chan_iax2_pvt *p0, struct chan_iax2_pvt *p1) +{ + ast_mutex_lock(&iaxsl[p0->callno]); + while (ast_mutex_trylock(&iaxsl[p1->callno])) { + ast_mutex_unlock(&iaxsl[p0->callno]); + usleep(10); + ast_mutex_lock(&iaxsl[p0->callno]); + } +} + +static void unlock_both(struct chan_iax2_pvt *p0, struct chan_iax2_pvt *p1) +{ + ast_mutex_unlock(&iaxsl[p1->callno]); + ast_mutex_unlock(&iaxsl[p0->callno]); +} + static int iax2_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc) { struct ast_channel *cs[3]; @@ -1995,9 +2012,11 @@ static int iax2_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags struct chan_iax2_pvt *p1 = c1->pvt->pvt; struct timeval waittimer = {0, 0}, tv; + lock_both(p0, p1); /* Put them in native bridge mode */ p0->bridgecallno = p1->callno; p1->bridgecallno = p0->callno; + unlock_both(p0, p1); /* If not, try to bridge until we can execute a transfer, if we can */ cs[0] = c0; @@ -2008,15 +2027,25 @@ static int iax2_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "Can't masquerade, we're different...\n"); /* Remove from native mode */ - p0->bridgecallno = 0; - p1->bridgecallno = 0; + if (c0->type == type) { + ast_mutex_lock(&iaxsl[p0->callno]); + p0->bridgecallno = 0; + ast_mutex_unlock(&iaxsl[p0->callno]); + } + if (c1->type == type) { + ast_mutex_lock(&iaxsl[p1->callno]); + p1->bridgecallno = 0; + ast_mutex_unlock(&iaxsl[p1->callno]); + } return -2; } if (c0->nativeformats != c1->nativeformats) { ast_verbose(VERBOSE_PREFIX_3 "Operating with different codecs, can't native bridge...\n"); /* Remove from native mode */ + lock_both(p0, p1); p0->bridgecallno = 0; p1->bridgecallno = 0; + unlock_both(p0, p1); return -2; } /* check if transfered and if we really want native bridging */ @@ -2112,8 +2141,10 @@ tackygoto: cs[0] = cs[1]; cs[1] = cs[2]; } + lock_both(p0, p1); p0->bridgecallno = 0; p1->bridgecallno = 0; + unlock_both(p0, p1); return res; } |