mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-30 02:26:23 +00:00
Cleanup SIP locking
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@746 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -1297,6 +1297,7 @@ static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *si
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
ast_pthread_mutex_lock(&p->lock);
|
||||||
ast_pthread_mutex_unlock(&iflock);
|
ast_pthread_mutex_unlock(&iflock);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@@ -1848,13 +1849,27 @@ static int reqprep(struct sip_request *req, struct sip_pvt *p, char *msg, int in
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int transmit_response(struct sip_pvt *p, char *msg, struct sip_request *req)
|
static int __transmit_response(struct sip_pvt *p, char *msg, struct sip_request *req, int reliable)
|
||||||
{
|
{
|
||||||
struct sip_request resp;
|
struct sip_request resp;
|
||||||
|
int seqno = 0;
|
||||||
|
if (reliable && (sscanf(get_header(req, "CSeq"), "%i ", &seqno) != 1)) {
|
||||||
|
ast_log(LOG_WARNING, "Unable to determine sequence number from '%s'\n", get_header(req, "CSeq"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
respprep(&resp, p, msg, req);
|
respprep(&resp, p, msg, req);
|
||||||
add_header(&resp, "Content-Length", "0");
|
add_header(&resp, "Content-Length", "0");
|
||||||
add_blank_header(&resp);
|
add_blank_header(&resp);
|
||||||
return send_response(p, &resp, 0, 0);
|
return send_response(p, &resp, reliable, seqno);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int transmit_response(struct sip_pvt *p, char *msg, struct sip_request *req)
|
||||||
|
{
|
||||||
|
return __transmit_response(p, msg, req, 0);
|
||||||
|
}
|
||||||
|
static int transmit_response_reliable(struct sip_pvt *p, char *msg, struct sip_request *req)
|
||||||
|
{
|
||||||
|
return __transmit_response(p, msg, req, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int transmit_response_with_allow(struct sip_pvt *p, char *msg, struct sip_request *req)
|
static int transmit_response_with_allow(struct sip_pvt *p, char *msg, struct sip_request *req)
|
||||||
@@ -2853,7 +2868,7 @@ static void receive_message(struct sip_pvt *p, struct sip_request *req)
|
|||||||
f.offset = 0;
|
f.offset = 0;
|
||||||
f.data = buf;
|
f.data = buf;
|
||||||
f.datalen = strlen(buf);
|
f.datalen = strlen(buf);
|
||||||
ast_queue_frame(p->owner, &f, 1);
|
ast_queue_frame(p->owner, &f, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3068,7 +3083,7 @@ static void receive_info(struct sip_pvt *p, struct sip_request *req)
|
|||||||
f.offset = 0;
|
f.offset = 0;
|
||||||
f.data = NULL;
|
f.data = NULL;
|
||||||
f.datalen = 0;
|
f.datalen = 0;
|
||||||
ast_queue_frame(p->owner, &f, 1);
|
ast_queue_frame(p->owner, &f, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3261,16 +3276,6 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_
|
|||||||
}
|
}
|
||||||
msg = strchr(c, ' ');
|
msg = strchr(c, ' ');
|
||||||
if (!msg) msg = ""; else msg++;
|
if (!msg) msg = ""; else msg++;
|
||||||
retrylock:
|
|
||||||
ast_pthread_mutex_lock(&p->lock);
|
|
||||||
/* Go ahead and lock the owner if it has one -- we may need it */
|
|
||||||
if (p->owner && pthread_mutex_trylock(&p->owner->lock)) {
|
|
||||||
ast_log(LOG_DEBUG, "Failed to grab lock, trying again...\n");
|
|
||||||
ast_pthread_mutex_unlock(&p->lock);
|
|
||||||
/* Sleep infintismly short amount of time */
|
|
||||||
usleep(1);
|
|
||||||
goto retrylock;
|
|
||||||
}
|
|
||||||
owner = p->owner;
|
owner = p->owner;
|
||||||
if (p->peerpoke) {
|
if (p->peerpoke) {
|
||||||
/* We don't really care what the response is, just that it replied back.
|
/* We don't really care what the response is, just that it replied back.
|
||||||
@@ -3296,8 +3301,7 @@ retrylock:
|
|||||||
ast_sched_del(sched, peer->pokeexpire);
|
ast_sched_del(sched, peer->pokeexpire);
|
||||||
if (!strcasecmp(msg, "INVITE"))
|
if (!strcasecmp(msg, "INVITE"))
|
||||||
transmit_request(p, "ACK", 0, 0);
|
transmit_request(p, "ACK", 0, 0);
|
||||||
sip_destroy(p);
|
p->needdestroy = 1;
|
||||||
p = NULL;
|
|
||||||
/* Try again eventually */
|
/* Try again eventually */
|
||||||
if ((peer->lastms < 0) || (peer->lastms > peer->maxms))
|
if ((peer->lastms < 0) || (peer->lastms > peer->maxms))
|
||||||
peer->pokeexpire = ast_sched_add(sched, DEFAULT_FREQ_NOTOK, sip_poke_peer_s, peer);
|
peer->pokeexpire = ast_sched_add(sched, DEFAULT_FREQ_NOTOK, sip_poke_peer_s, peer);
|
||||||
@@ -3555,6 +3559,8 @@ static int attempt_transfer(struct sip_pvt *p1, struct sip_pvt *p2)
|
|||||||
|
|
||||||
static int handle_request(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin)
|
static int handle_request(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin)
|
||||||
{
|
{
|
||||||
|
/* Called with p->lock held, as well as p->owner->lock if appropriate, keeping things
|
||||||
|
relatively static */
|
||||||
struct sip_request resp;
|
struct sip_request resp;
|
||||||
char *cmd;
|
char *cmd;
|
||||||
char *cseq;
|
char *cseq;
|
||||||
@@ -3613,7 +3619,7 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
|
|||||||
/* Response to our request -- Do some sanity checks */
|
/* Response to our request -- Do some sanity checks */
|
||||||
if (!p->initreq.headers) {
|
if (!p->initreq.headers) {
|
||||||
ast_log(LOG_DEBUG, "That's odd... Got a response on a call we dont know about.\n");
|
ast_log(LOG_DEBUG, "That's odd... Got a response on a call we dont know about.\n");
|
||||||
sip_destroy(p);
|
p->needdestroy = 1;
|
||||||
return 0;
|
return 0;
|
||||||
} else if (p->ocseq && (p->ocseq < seqno)) {
|
} else if (p->ocseq && (p->ocseq < seqno)) {
|
||||||
ast_log(LOG_DEBUG, "Ignoring out of order response %d (expecting %d)\n", seqno, p->ocseq);
|
ast_log(LOG_DEBUG, "Ignoring out of order response %d (expecting %d)\n", seqno, p->ocseq);
|
||||||
@@ -3673,7 +3679,7 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
|
|||||||
if (res) {
|
if (res) {
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
ast_log(LOG_NOTICE, "Failed to authenticate user %s\n", get_header(req, "From"));
|
ast_log(LOG_NOTICE, "Failed to authenticate user %s\n", get_header(req, "From"));
|
||||||
sip_destroy(p);
|
p->needdestroy = 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -3685,9 +3691,7 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
|
|||||||
transmit_response(p, "404 Not Found", req);
|
transmit_response(p, "404 Not Found", req);
|
||||||
else
|
else
|
||||||
transmit_response(p, "484 Address Incomplete", req);
|
transmit_response(p, "484 Address Incomplete", req);
|
||||||
sip_destroy(p);
|
p->needdestroy = 1;
|
||||||
p = NULL;
|
|
||||||
c = NULL;
|
|
||||||
} else {
|
} else {
|
||||||
/* If no extension was specified, use the s one */
|
/* If no extension was specified, use the s one */
|
||||||
if (!strlen(p->exten))
|
if (!strlen(p->exten))
|
||||||
@@ -3696,6 +3700,10 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
|
|||||||
p->tag = rand();
|
p->tag = rand();
|
||||||
/* First invitation */
|
/* First invitation */
|
||||||
c = sip_new(p, AST_STATE_DOWN, strlen(p->username) ? p->username : NULL);
|
c = sip_new(p, AST_STATE_DOWN, strlen(p->username) ? p->username : NULL);
|
||||||
|
if (c) {
|
||||||
|
/* Pre-lock the call */
|
||||||
|
ast_pthread_mutex_lock(&c->lock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else
|
} else
|
||||||
@@ -3709,9 +3717,9 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
|
|||||||
ast_setstate(c, AST_STATE_RING);
|
ast_setstate(c, AST_STATE_RING);
|
||||||
if (ast_pbx_start(c)) {
|
if (ast_pbx_start(c)) {
|
||||||
ast_log(LOG_WARNING, "Failed to start PBX :(\n");
|
ast_log(LOG_WARNING, "Failed to start PBX :(\n");
|
||||||
ast_hangup(c);
|
sip_hangup(c);
|
||||||
transmit_response(p, "503 Unavailable", req);
|
transmit_response_reliable(p, "503 Unavailable", req);
|
||||||
sip_destroy(p);
|
c = NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AST_STATE_RING:
|
case AST_STATE_RING:
|
||||||
@@ -3730,8 +3738,8 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
|
|||||||
} else {
|
} else {
|
||||||
if (p) {
|
if (p) {
|
||||||
ast_log(LOG_NOTICE, "Unable to create/find channel\n");
|
ast_log(LOG_NOTICE, "Unable to create/find channel\n");
|
||||||
transmit_response(p, "503 Unavailable", req);
|
transmit_response_reliable(p, "503 Unavailable", req);
|
||||||
sip_destroy(p);
|
p->needdestroy = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!strcasecmp(cmd, "REFER")) {
|
} else if (!strcasecmp(cmd, "REFER")) {
|
||||||
@@ -3772,7 +3780,7 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
|
|||||||
ast_rtp_stop(p->rtp);
|
ast_rtp_stop(p->rtp);
|
||||||
}
|
}
|
||||||
if (p->owner)
|
if (p->owner)
|
||||||
ast_queue_hangup(p->owner, 1);
|
ast_queue_hangup(p->owner, 0);
|
||||||
transmit_response(p, "200 OK", req);
|
transmit_response(p, "200 OK", req);
|
||||||
} else if (!strcasecmp(cmd, "MESSAGE")) {
|
} else if (!strcasecmp(cmd, "MESSAGE")) {
|
||||||
if (sipdebug)
|
if (sipdebug)
|
||||||
@@ -3793,7 +3801,7 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
|
|||||||
if ((res = register_verify(p, sin, req, e)) < 0)
|
if ((res = register_verify(p, sin, req, e)) < 0)
|
||||||
ast_log(LOG_NOTICE, "Registration from '%s' failed for '%s'\n", get_header(req, "To"), inet_ntoa(sin->sin_addr));
|
ast_log(LOG_NOTICE, "Registration from '%s' failed for '%s'\n", get_header(req, "To"), inet_ntoa(sin->sin_addr));
|
||||||
if (res < 1) {
|
if (res < 1) {
|
||||||
sip_destroy(p);
|
p->needdestroy = 1;
|
||||||
}
|
}
|
||||||
} else if (!strcasecmp(cmd, "ACK")) {
|
} else if (!strcasecmp(cmd, "ACK")) {
|
||||||
/* Uhm, I haven't figured out the point of the ACK yet. Are we
|
/* Uhm, I haven't figured out the point of the ACK yet. Are we
|
||||||
@@ -3849,8 +3857,20 @@ static int sipsock_read(int *id, int fd, short events, void *ignore)
|
|||||||
ast_pthread_mutex_lock(&netlock);
|
ast_pthread_mutex_lock(&netlock);
|
||||||
p = find_call(&req, &sin);
|
p = find_call(&req, &sin);
|
||||||
if (p) {
|
if (p) {
|
||||||
|
retrylock:
|
||||||
|
/* Go ahead and lock the owner if it has one -- we may need it */
|
||||||
|
if (p->owner && pthread_mutex_trylock(&p->owner->lock)) {
|
||||||
|
ast_log(LOG_DEBUG, "Failed to grab lock, trying again...\n");
|
||||||
|
ast_pthread_mutex_unlock(&p->lock);
|
||||||
|
/* Sleep infintismly short amount of time */
|
||||||
|
usleep(1);
|
||||||
|
goto retrylock;
|
||||||
|
}
|
||||||
memcpy(&p->recv, &sin, sizeof(p->recv));
|
memcpy(&p->recv, &sin, sizeof(p->recv));
|
||||||
handle_request(p, &req, &sin);
|
handle_request(p, &req, &sin);
|
||||||
|
if (p->owner)
|
||||||
|
ast_pthread_mutex_unlock(&p->owner->lock);
|
||||||
|
ast_pthread_mutex_unlock(&p->lock);
|
||||||
}
|
}
|
||||||
ast_pthread_mutex_unlock(&netlock);
|
ast_pthread_mutex_unlock(&netlock);
|
||||||
return 1;
|
return 1;
|
||||||
|
Reference in New Issue
Block a user