Merging the invitestate-1.4 branch after successful testing.

Will check if I can solve this with less changes in 1.2.


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@48270 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.4
Olle Johansson 19 years ago
parent 7945d4ca35
commit 694205de93

@ -244,6 +244,21 @@ enum sip_result {
AST_FAILURE = -1, AST_FAILURE = -1,
}; };
/*! \brief States for the INVITE transaction, not the dialog
\note this is for the INVITE that sets up the dialog
*/
enum invitestates {
INV_NONE = 0, /*!< No state at all, maybe not an INVITE dialog */
INV_CALLING = 1, /*!< Invite sent, no answer */
INV_PROCEEDING = 2, /*!< We got/sent 1xx message */
INV_EARLY_MEDIA = 3, /*!< We got 18x message with to-tag back */
INV_COMPLETED = 4, /*!< Got final response with error. Wait for ACK, then CONFIRMED */
INV_CONFIRMED = 5, /*!< Confirmed response - we've got an ack (Incoming calls only) */
INV_TERMINATED = 6, /*!< Transaction done - either successful (AST_STATE_UP) or failed, but done
The only way out of this is a BYE from one side */
INV_CANCELLED = 7, /*!< Transaction cancelled by client or server in non-terminated state */
};
/* Do _NOT_ make any changes to this enum, or the array following it; /* Do _NOT_ make any changes to this enum, or the array following it;
if you think you are doing the right thing, you are probably if you think you are doing the right thing, you are probably
not doing the right thing. If you think there are changes not doing the right thing. If you think there are changes
@ -703,7 +718,7 @@ struct sip_auth {
#define SIP_REALTIME (1 << 11) /*!< Flag for realtime users */ #define SIP_REALTIME (1 << 11) /*!< Flag for realtime users */
#define SIP_USECLIENTCODE (1 << 12) /*!< Trust X-ClientCode info message */ #define SIP_USECLIENTCODE (1 << 12) /*!< Trust X-ClientCode info message */
#define SIP_OUTGOING (1 << 13) /*!< Direction of the last transaction in this dialog */ #define SIP_OUTGOING (1 << 13) /*!< Direction of the last transaction in this dialog */
#define SIP_CAN_BYE (1 << 14) /*!< Can we send BYE on this dialog? */ #define SIP_FREE_BIT (1 << 14) /*!< ---- */
#define SIP_DEFER_BYE_ON_TRANSFER (1 << 15) /*!< Do not hangup at first ast_hangup */ #define SIP_DEFER_BYE_ON_TRANSFER (1 << 15) /*!< Do not hangup at first ast_hangup */
#define SIP_DTMF (3 << 16) /*!< DTMF Support: four settings, uses two bits */ #define SIP_DTMF (3 << 16) /*!< DTMF Support: four settings, uses two bits */
#define SIP_DTMF_RFC2833 (0 << 16) /*!< DTMF Support: RTP DTMF - "rfc2833" */ #define SIP_DTMF_RFC2833 (0 << 16) /*!< DTMF Support: RTP DTMF - "rfc2833" */
@ -877,6 +892,7 @@ struct sip_refer {
static struct sip_pvt { static struct sip_pvt {
ast_mutex_t lock; /*!< Dialog private lock */ ast_mutex_t lock; /*!< Dialog private lock */
int method; /*!< SIP method that opened this dialog */ int method; /*!< SIP method that opened this dialog */
enum invitestates invitestate; /*!< The state of the INVITE transaction only */
AST_DECLARE_STRING_FIELDS( AST_DECLARE_STRING_FIELDS(
AST_STRING_FIELD(callid); /*!< Global CallID */ AST_STRING_FIELD(callid); /*!< Global CallID */
AST_STRING_FIELD(randdata); /*!< Random data */ AST_STRING_FIELD(randdata); /*!< Random data */
@ -1593,6 +1609,13 @@ static void initialize_initreq(struct sip_pvt *p, struct sip_request *req)
ast_verbose("%d headers, %d lines\n", p->initreq.headers, p->initreq.lines); ast_verbose("%d headers, %d lines\n", p->initreq.headers, p->initreq.lines);
} }
static void sip_alreadygone(struct sip_pvt *dialog)
{
if (option_debug > 2)
ast_log(LOG_DEBUG, "Setting SIP_ALREADYGONE on dialog %s\n", dialog->callid);
ast_set_flag(&dialog->flags[0], SIP_ALREADYGONE);
}
/*! \brief returns true if 'name' (with optional trailing whitespace) /*! \brief returns true if 'name' (with optional trailing whitespace)
* matches the sip method 'id'. * matches the sip method 'id'.
@ -1871,7 +1894,7 @@ static int retrans_pkt(void *data)
ast_mutex_lock(&pkt->owner->lock); ast_mutex_lock(&pkt->owner->lock);
} }
if (pkt->owner->owner) { if (pkt->owner->owner) {
ast_set_flag(&pkt->owner->flags[0], SIP_ALREADYGONE); sip_alreadygone(pkt->owner);
ast_log(LOG_WARNING, "Hanging up call %s - no reply to our critical packet.\n", pkt->owner->callid); ast_log(LOG_WARNING, "Hanging up call %s - no reply to our critical packet.\n", pkt->owner->callid);
ast_queue_hangup(pkt->owner->owner); ast_queue_hangup(pkt->owner->owner);
ast_channel_unlock(pkt->owner->owner); ast_channel_unlock(pkt->owner->owner);
@ -2802,6 +2825,7 @@ static int sip_call(struct ast_channel *ast, char *dest, int timeout)
if (option_debug > 1) if (option_debug > 1)
ast_log(LOG_DEBUG,"Our T38 capability (%d), joint T38 capability (%d)\n", p->t38.capability, p->t38.jointcapability); ast_log(LOG_DEBUG,"Our T38 capability (%d), joint T38 capability (%d)\n", p->t38.capability, p->t38.jointcapability);
transmit_invite(p, SIP_INVITE, 1, 2); transmit_invite(p, SIP_INVITE, 1, 2);
p->invitestate = INV_CALLING;
/* Initialize auto-congest time */ /* Initialize auto-congest time */
p->initid = ast_sched_add(sched, p->maxtime ? (p->maxtime * 4) : SIP_TRANS_TIMEOUT, auto_congest, p); p->initid = ast_sched_add(sched, p->maxtime ? (p->maxtime * 4) : SIP_TRANS_TIMEOUT, auto_congest, p);
@ -3269,7 +3293,7 @@ static int sip_hangup(struct ast_channel *ast)
return 0; return 0;
} }
/* If the call is not UP, we need to send CANCEL instead of BYE */ /* If the call is not UP, we need to send CANCEL instead of BYE */
if (ast->_state == AST_STATE_RING || ast->_state == AST_STATE_RINGING) { if (ast->_state == AST_STATE_RING || ast->_state == AST_STATE_RINGING || p->invitestate < INV_COMPLETED) {
needcancel = TRUE; needcancel = TRUE;
if (option_debug > 3) if (option_debug > 3)
ast_log(LOG_DEBUG, "Hanging up channel in state %s (not UP)\n", ast_state2str(ast->_state)); ast_log(LOG_DEBUG, "Hanging up channel in state %s (not UP)\n", ast_state2str(ast->_state));
@ -3293,7 +3317,7 @@ static int sip_hangup(struct ast_channel *ast)
*/ */
if (ast_test_flag(&p->flags[0], SIP_ALREADYGONE)) if (ast_test_flag(&p->flags[0], SIP_ALREADYGONE))
needdestroy = 1; /* Set destroy flag at end of this function */ needdestroy = 1; /* Set destroy flag at end of this function */
else else if (p->invitestate != INV_CALLING)
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
/* Start the process if it's not already started */ /* Start the process if it's not already started */
@ -3304,7 +3328,8 @@ static int sip_hangup(struct ast_channel *ast)
__sip_pretend_ack(p); __sip_pretend_ack(p);
/* if we can't send right now, mark it pending */ /* if we can't send right now, mark it pending */
if (!ast_test_flag(&p->flags[0], SIP_CAN_BYE)) { if (p->invitestate == INV_CALLING) {
/* We can't send anything in CALLING state */
ast_set_flag(&p->flags[0], SIP_PENDINGBYE); ast_set_flag(&p->flags[0], SIP_PENDINGBYE);
/* Do we need a timer here if we don't hear from them at all? */ /* Do we need a timer here if we don't hear from them at all? */
} else { } else {
@ -3354,6 +3379,7 @@ static int sip_hangup(struct ast_channel *ast)
but we can't send one while we have "INVITE" outstanding. */ but we can't send one while we have "INVITE" outstanding. */
ast_set_flag(&p->flags[0], SIP_PENDINGBYE); ast_set_flag(&p->flags[0], SIP_PENDINGBYE);
ast_clear_flag(&p->flags[0], SIP_NEEDREINVITE); ast_clear_flag(&p->flags[0], SIP_NEEDREINVITE);
sip_cancel_destroy(p);
} }
} }
} }
@ -3608,6 +3634,7 @@ static int sip_indicate(struct ast_channel *ast, int condition, const void *data
switch(condition) { switch(condition) {
case AST_CONTROL_RINGING: case AST_CONTROL_RINGING:
if (ast->_state == AST_STATE_RING) { if (ast->_state == AST_STATE_RING) {
p->invitestate = INV_EARLY_MEDIA;
if (!ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) || if (!ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) ||
(ast_test_flag(&p->flags[0], SIP_PROG_INBAND) == SIP_PROG_INBAND_NEVER)) { (ast_test_flag(&p->flags[0], SIP_PROG_INBAND) == SIP_PROG_INBAND_NEVER)) {
/* Send 180 ringing if out-of-band seems reasonable */ /* Send 180 ringing if out-of-band seems reasonable */
@ -3624,7 +3651,8 @@ static int sip_indicate(struct ast_channel *ast, int condition, const void *data
case AST_CONTROL_BUSY: case AST_CONTROL_BUSY:
if (ast->_state != AST_STATE_UP) { if (ast->_state != AST_STATE_UP) {
transmit_response(p, "486 Busy Here", &p->initreq); transmit_response(p, "486 Busy Here", &p->initreq);
ast_set_flag(&p->flags[0], SIP_ALREADYGONE); p->invitestate = INV_TERMINATED;
sip_alreadygone(p);
ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV); ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
break; break;
} }
@ -3633,7 +3661,8 @@ static int sip_indicate(struct ast_channel *ast, int condition, const void *data
case AST_CONTROL_CONGESTION: case AST_CONTROL_CONGESTION:
if (ast->_state != AST_STATE_UP) { if (ast->_state != AST_STATE_UP) {
transmit_response(p, "503 Service Unavailable", &p->initreq); transmit_response(p, "503 Service Unavailable", &p->initreq);
ast_set_flag(&p->flags[0], SIP_ALREADYGONE); p->invitestate = INV_TERMINATED;
sip_alreadygone(p);
ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV); ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
break; break;
} }
@ -3644,6 +3673,7 @@ static int sip_indicate(struct ast_channel *ast, int condition, const void *data
!ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) && !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) &&
!ast_test_flag(&p->flags[0], SIP_OUTGOING)) { !ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
transmit_response(p, "100 Trying", &p->initreq); transmit_response(p, "100 Trying", &p->initreq);
p->invitestate = INV_PROCEEDING;
break; break;
} }
res = -1; res = -1;
@ -3652,6 +3682,7 @@ static int sip_indicate(struct ast_channel *ast, int condition, const void *data
if ((ast->_state != AST_STATE_UP) && if ((ast->_state != AST_STATE_UP) &&
!ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) && !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) &&
!ast_test_flag(&p->flags[0], SIP_OUTGOING)) { !ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
p->invitestate = INV_EARLY_MEDIA;
transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE); transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE);
ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT); ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
break; break;
@ -7374,6 +7405,9 @@ static int transmit_request(struct sip_pvt *p, int sipmethod, int seqno, enum xm
{ {
struct sip_request resp; struct sip_request resp;
if (sipmethod == SIP_ACK)
p->invitestate = INV_CONFIRMED;
reqprep(&resp, p, sipmethod, seqno, newbranch); reqprep(&resp, p, sipmethod, seqno, newbranch);
add_header_contentLength(&resp, 0); add_header_contentLength(&resp, 0);
return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq); return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq);
@ -11462,7 +11496,7 @@ static void check_pendings(struct sip_pvt *p)
{ {
if (ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) { if (ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
/* if we can't BYE, then this is really a pending CANCEL */ /* if we can't BYE, then this is really a pending CANCEL */
if (!ast_test_flag(&p->flags[0], SIP_CAN_BYE)) if (p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA)
transmit_request(p, SIP_CANCEL, p->ocseq, XMIT_RELIABLE, FALSE); transmit_request(p, SIP_CANCEL, p->ocseq, XMIT_RELIABLE, FALSE);
/* Actually don't destroy us yet, wait for the 487 on our original /* Actually don't destroy us yet, wait for the 487 on our original
INVITE, but do set an autodestruct just in case we never get it. */ INVITE, but do set an autodestruct just in case we never get it. */
@ -11513,6 +11547,15 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
if (resp > 100 && resp < 200 && resp!=101 && resp != 180 && resp != 183) if (resp > 100 && resp < 200 && resp!=101 && resp != 180 && resp != 183)
resp = 183; resp = 183;
/* Any response between 100 and 199 is PROCEEDING */
if (resp >= 100 && resp < 200 && p->invitestate == INV_CALLING)
p->invitestate = INV_PROCEEDING;
/* Final response, not 200 ? */
if (resp >= 300 && (p->invitestate == INV_CALLING || p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA ))
p->invitestate = INV_COMPLETED;
switch (resp) { switch (resp) {
case 100: /* Trying */ case 100: /* Trying */
case 101: /* Dialog establishment */ case 101: /* Dialog establishment */
@ -11531,13 +11574,13 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
} }
} }
if (find_sdp(req)) { if (find_sdp(req)) {
p->invitestate = INV_EARLY_MEDIA;
res = process_sdp(p, req); res = process_sdp(p, req);
if (!ast_test_flag(req, SIP_PKT_IGNORE) && p->owner) { if (!ast_test_flag(req, SIP_PKT_IGNORE) && p->owner) {
/* Queue a progress frame only if we have SDP in 180 */ /* Queue a progress frame only if we have SDP in 180 */
ast_queue_control(p->owner, AST_CONTROL_PROGRESS); ast_queue_control(p->owner, AST_CONTROL_PROGRESS);
} }
} }
ast_set_flag(&p->flags[0], SIP_CAN_BYE);
check_pendings(p); check_pendings(p);
break; break;
@ -11546,13 +11589,13 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
sip_cancel_destroy(p); sip_cancel_destroy(p);
/* Ignore 183 Session progress without SDP */ /* Ignore 183 Session progress without SDP */
if (find_sdp(req)) { if (find_sdp(req)) {
p->invitestate = INV_EARLY_MEDIA;
res = process_sdp(p, req); res = process_sdp(p, req);
if (!ast_test_flag(req, SIP_PKT_IGNORE) && p->owner) { if (!ast_test_flag(req, SIP_PKT_IGNORE) && p->owner) {
/* Queue a progress frame */ /* Queue a progress frame */
ast_queue_control(p->owner, AST_CONTROL_PROGRESS); ast_queue_control(p->owner, AST_CONTROL_PROGRESS);
} }
} }
ast_set_flag(&p->flags[0], SIP_CAN_BYE);
check_pendings(p); check_pendings(p);
break; break;
@ -11653,8 +11696,8 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
ast_set_flag(&p->flags[0], SIP_PENDINGBYE); ast_set_flag(&p->flags[0], SIP_PENDINGBYE);
} }
/* If I understand this right, the branch is different for a non-200 ACK only */ /* If I understand this right, the branch is different for a non-200 ACK only */
p->invitestate = INV_TERMINATED;
transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, TRUE); transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, TRUE);
ast_set_flag(&p->flags[0], SIP_CAN_BYE);
check_pendings(p); check_pendings(p);
break; break;
case 407: /* Proxy authentication */ case 407: /* Proxy authentication */
@ -11672,7 +11715,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
if ((p->authtries == MAX_AUTHTRIES) || do_proxy_auth(p, req, authenticate, authorization, SIP_INVITE, 1)) { if ((p->authtries == MAX_AUTHTRIES) || do_proxy_auth(p, req, authenticate, authorization, SIP_INVITE, 1)) {
ast_log(LOG_NOTICE, "Failed to authenticate on INVITE to '%s'\n", get_header(&p->initreq, "From")); ast_log(LOG_NOTICE, "Failed to authenticate on INVITE to '%s'\n", get_header(&p->initreq, "From"));
ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
ast_set_flag(&p->flags[0], SIP_ALREADYGONE); sip_alreadygone(p);
if (p->owner) if (p->owner)
ast_queue_control(p->owner, AST_CONTROL_CONGESTION); ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
} }
@ -11686,14 +11729,14 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
if (!ast_test_flag(req, SIP_PKT_IGNORE) && p->owner) if (!ast_test_flag(req, SIP_PKT_IGNORE) && p->owner)
ast_queue_control(p->owner, AST_CONTROL_CONGESTION); ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
ast_set_flag(&p->flags[0], SIP_ALREADYGONE); sip_alreadygone(p);
break; break;
case 404: /* Not found */ case 404: /* Not found */
transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE);
if (p->owner && !ast_test_flag(req, SIP_PKT_IGNORE)) if (p->owner && !ast_test_flag(req, SIP_PKT_IGNORE))
ast_queue_control(p->owner, AST_CONTROL_CONGESTION); ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
ast_set_flag(&p->flags[0], SIP_ALREADYGONE); sip_alreadygone(p);
break; break;
case 481: /* Call leg does not exist */ case 481: /* Call leg does not exist */
@ -12150,7 +12193,6 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_
/* Fatal response */ /* Fatal response */
if ((option_verbose > 2) && (resp != 487)) if ((option_verbose > 2) && (resp != 487))
ast_verbose(VERBOSE_PREFIX_3 "Got SIP response %d \"%s\" back from %s\n", resp, rest, ast_inet_ntoa(p->sa.sin_addr)); ast_verbose(VERBOSE_PREFIX_3 "Got SIP response %d \"%s\" back from %s\n", resp, rest, ast_inet_ntoa(p->sa.sin_addr));
ast_set_flag(&p->flags[0], SIP_ALREADYGONE);
stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */ stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */
@ -12209,7 +12251,7 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_
/* ACK on invite */ /* ACK on invite */
if (sipmethod == SIP_INVITE) if (sipmethod == SIP_INVITE)
transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE);
ast_set_flag(&p->flags[0], SIP_ALREADYGONE); sip_alreadygone(p);
if (!p->owner) if (!p->owner)
ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
} else if ((resp >= 100) && (resp < 200)) { } else if ((resp >= 100) && (resp < 200)) {
@ -13254,6 +13296,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
if (option_debug > 1) if (option_debug > 1)
ast_log(LOG_DEBUG, "%s: New call is still down.... Trying... \n", c->name); ast_log(LOG_DEBUG, "%s: New call is still down.... Trying... \n", c->name);
transmit_response(p, "100 Trying", req); transmit_response(p, "100 Trying", req);
p->invitestate = INV_PROCEEDING;
ast_setstate(c, AST_STATE_RING); ast_setstate(c, AST_STATE_RING);
if (strcmp(p->exten, ast_pickup_ext())) { /* Call to extension -start pbx on this call */ if (strcmp(p->exten, ast_pickup_ext())) { /* Call to extension -start pbx on this call */
enum ast_pbx_result res; enum ast_pbx_result res;
@ -13263,6 +13306,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
switch(res) { switch(res) {
case AST_PBX_FAILED: case AST_PBX_FAILED:
ast_log(LOG_WARNING, "Failed to start PBX :(\n"); ast_log(LOG_WARNING, "Failed to start PBX :(\n");
p->invitestate = INV_COMPLETED;
if (ast_test_flag(req, SIP_PKT_IGNORE)) if (ast_test_flag(req, SIP_PKT_IGNORE))
transmit_response(p, "503 Unavailable", req); transmit_response(p, "503 Unavailable", req);
else else
@ -13270,6 +13314,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
break; break;
case AST_PBX_CALL_LIMIT: case AST_PBX_CALL_LIMIT:
ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n"); ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n");
p->invitestate = INV_COMPLETED;
if (ast_test_flag(req, SIP_PKT_IGNORE)) if (ast_test_flag(req, SIP_PKT_IGNORE))
transmit_response(p, "480 Temporarily Unavailable", req); transmit_response(p, "480 Temporarily Unavailable", req);
else else
@ -13297,7 +13342,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
transmit_response(p, "503 Unavailable", req); /* OEJ - Right answer? */ transmit_response(p, "503 Unavailable", req); /* OEJ - Right answer? */
else else
transmit_response_reliable(p, "503 Unavailable", req); transmit_response_reliable(p, "503 Unavailable", req);
ast_set_flag(&p->flags[0], SIP_ALREADYGONE); sip_alreadygone(p);
/* Unlock locks so ast_hangup can do its magic */ /* Unlock locks so ast_hangup can do its magic */
ast_mutex_unlock(&p->lock); ast_mutex_unlock(&p->lock);
c->hangupcause = AST_CAUSE_CALL_REJECTED; c->hangupcause = AST_CAUSE_CALL_REJECTED;
@ -13306,6 +13351,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
ast_setstate(c, AST_STATE_DOWN); ast_setstate(c, AST_STATE_DOWN);
c->hangupcause = AST_CAUSE_NORMAL_CLEARING; c->hangupcause = AST_CAUSE_NORMAL_CLEARING;
} }
p->invitestate = INV_COMPLETED;
ast_hangup(c); ast_hangup(c);
ast_mutex_lock(&p->lock); ast_mutex_lock(&p->lock);
c = NULL; c = NULL;
@ -13313,9 +13359,11 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
break; break;
case AST_STATE_RING: case AST_STATE_RING:
transmit_response(p, "100 Trying", req); transmit_response(p, "100 Trying", req);
p->invitestate = INV_PROCEEDING;
break; break;
case AST_STATE_RINGING: case AST_STATE_RINGING:
transmit_response(p, "180 Ringing", req); transmit_response(p, "180 Ringing", req);
p->invitestate = INV_PROCEEDING;
break; break;
case AST_STATE_UP: case AST_STATE_UP:
if (option_debug > 1) if (option_debug > 1)
@ -13401,6 +13449,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
transmit_response_with_sdp(p, "200 OK", req, XMIT_CRITICAL); transmit_response_with_sdp(p, "200 OK", req, XMIT_CRITICAL);
} }
p->invitestate = INV_TERMINATED;
break; break;
default: default:
ast_log(LOG_WARNING, "Don't know how to handle INVITE in state %d\n", c->_state); ast_log(LOG_WARNING, "Don't know how to handle INVITE in state %d\n", c->_state);
@ -13421,6 +13470,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
transmit_response(p, msg, req); transmit_response(p, msg, req);
else else
transmit_response_reliable(p, msg, req); transmit_response_reliable(p, msg, req);
p->invitestate = INV_COMPLETED;
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
} }
} }
@ -13616,7 +13666,7 @@ static int handle_request_refer(struct sip_pvt *p, struct sip_request *req, int
transmit_response(p, "603 Declined (No dialog)", req); transmit_response(p, "603 Declined (No dialog)", req);
if (!ast_test_flag(req, SIP_PKT_IGNORE)) { if (!ast_test_flag(req, SIP_PKT_IGNORE)) {
append_history(p, "Xfer", "Refer failed. Outside of dialog."); append_history(p, "Xfer", "Refer failed. Outside of dialog.");
ast_set_flag(&p->flags[0], SIP_ALREADYGONE); sip_alreadygone(p);
ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
} }
return 0; return 0;
@ -13875,7 +13925,8 @@ static int handle_request_cancel(struct sip_pvt *p, struct sip_request *req)
{ {
check_via(p, req); check_via(p, req);
ast_set_flag(&p->flags[0], SIP_ALREADYGONE); sip_alreadygone(p);
p->invitestate = INV_CANCELLED;
if (p->owner && p->owner->_state == AST_STATE_UP) { if (p->owner && p->owner->_state == AST_STATE_UP) {
/* This call is up, cancel is ignored, we need a bye */ /* This call is up, cancel is ignored, we need a bye */
@ -13908,12 +13959,14 @@ static int handle_request_bye(struct sip_pvt *p, struct sip_request *req)
struct ast_channel *bridged_to; struct ast_channel *bridged_to;
/* If we have an INCOMING invite that we haven't answered, terminate that transaction */ /* If we have an INCOMING invite that we haven't answered, terminate that transaction */
if (p->pendinginvite && !ast_test_flag(&p->flags[0], SIP_OUTGOING) && !ast_test_flag(req, SIP_PKT_IGNORE) && !p->owner) if (p->pendinginvite && !ast_test_flag(&p->flags[0], SIP_OUTGOING) && !ast_test_flag(req, SIP_PKT_IGNORE) && !p->owner)
transmit_response_reliable(p, "487 Request Terminated", &p->initreq); transmit_response_reliable(p, "487 Request Terminated", &p->initreq);
p->invitestate = INV_TERMINATED;
copy_request(&p->initreq, req); copy_request(&p->initreq, req);
check_via(p, req); check_via(p, req);
ast_set_flag(&p->flags[0], SIP_ALREADYGONE); sip_alreadygone(p);
/* Get RTCP quality before end of call */ /* Get RTCP quality before end of call */
if (!ast_test_flag(&p->flags[0], SIP_NO_HISTORY) || p->owner) { if (!ast_test_flag(&p->flags[0], SIP_NO_HISTORY) || p->owner) {
@ -14479,6 +14532,7 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
case SIP_ACK: case SIP_ACK:
/* Make sure we don't ignore this */ /* Make sure we don't ignore this */
if (seqno == p->pendinginvite) { if (seqno == p->pendinginvite) {
p->invitestate = INV_CONFIRMED;
p->pendinginvite = 0; p->pendinginvite = 0;
__sip_ack(p, seqno, FLAG_RESPONSE, 0); __sip_ack(p, seqno, FLAG_RESPONSE, 0);
if (find_sdp(req)) { if (find_sdp(req)) {

Loading…
Cancel
Save