[asterisk-commits] oej: branch oej/codename-pineapple r47482 - in
/team/oej/codename-pineapple/c...
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Fri Nov 10 15:46:26 MST 2006
Author: oej
Date: Fri Nov 10 16:46:26 2006
New Revision: 47482
URL: http://svn.digium.com/view/asterisk?view=rev&rev=47482
Log:
Updates, just updates
Modified:
team/oej/codename-pineapple/channels/chan_sip.c
team/oej/codename-pineapple/channels/chan_sip3.c
team/oej/codename-pineapple/channels/sip3/sip3_dialog.c
team/oej/codename-pineapple/channels/sip3/sip3_sdprtp.c
team/oej/codename-pineapple/channels/sip3/sip3funcs.h
Modified: team/oej/codename-pineapple/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/chan_sip.c?view=diff&rev=47482&r1=47481&r2=47482
==============================================================================
--- team/oej/codename-pineapple/channels/chan_sip.c (original)
+++ team/oej/codename-pineapple/channels/chan_sip.c Fri Nov 10 16:46:26 2006
@@ -13105,6 +13105,7 @@
in fact a forked call through a SIP proxy somewhere. */
transmit_response(p, "482 Loop Detected", req);
/* We do NOT destroy p here, so that our response will be accepted */
+ sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
return 0;
}
Modified: team/oej/codename-pineapple/channels/chan_sip3.c
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/chan_sip3.c?view=diff&rev=47482&r1=47481&r2=47482
==============================================================================
--- team/oej/codename-pineapple/channels/chan_sip3.c (original)
+++ team/oej/codename-pineapple/channels/chan_sip3.c Fri Nov 10 16:46:26 2006
@@ -457,12 +457,12 @@
/*--- Transmitting responses and requests */
static int transmit_sip_request(struct sip_dialog *p, struct sip_request *req);
+static int transmit_request(struct sip_dialog *p, int sipmethod, int inc, enum xmittype reliable, int newbranch);
static int transmit_response_reliable(struct sip_dialog *p, const char *msg, const struct sip_request *req);
static int transmit_response_with_attachment(enum responseattach attach, struct sip_dialog *p, const char *msg,
const struct sip_request *req, enum xmittype reliable);
static int transmit_response_with_unsupported(struct sip_dialog *p, const char *msg, const struct sip_request *req, const char *unsupported);
static void transmit_fake_auth_response(struct sip_dialog *p, struct sip_request *req, int reliable);
-static int transmit_request(struct sip_dialog *p, int sipmethod, int inc, enum xmittype reliable, int newbranch);
static int transmit_info_with_digit(struct sip_dialog *p, const char digit);
static int transmit_info_with_vidupdate(struct sip_dialog *p);
static int transmit_message_with_text(struct sip_dialog *p, const char *text);
@@ -1313,28 +1313,27 @@
ast_log(LOG_DEBUG, "SIP Transfer: Not hanging up right now... Rescheduling hangup for %s.\n", p->callid);
if (p->autokillid > -1)
sip_cancel_destroy(p);
- sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+ dialogstatechange(p, DIALOG_STATE_TERMINATED);
+ sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); /* This does not issue BYE - fix needed */
ast_clear_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER); /* Really hang up next time */
ast_clear_flag(&p->flags[0], SIP_NEEDDESTROY);
p->owner->tech_pvt = NULL;
p->owner = NULL; /* Owner will be gone after we return, so take it away */
return 0;
}
- if (option_debug) {
+ if (option_debug > 1) {
if (ast_test_flag(ast, AST_FLAG_ZOMBIE) && p->refer && option_debug)
ast_log(LOG_DEBUG, "SIP Transfer: Hanging up Zombie channel %s after transfer ... Call-ID: %s\n", ast->name, p->callid);
- else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Hangup call %s, SIP callid %s)\n", ast->name, p->callid);
- }
- }
- if (option_debug && ast_test_flag(ast, AST_FLAG_ZOMBIE))
+ else
+ ast_log(LOG_DEBUG, "Hangup call %s, SIP callid %s)\n", ast->name, p->callid);
+ }
+ if (option_debug > 1 && ast_test_flag(ast, AST_FLAG_ZOMBIE))
ast_log(LOG_DEBUG, "Hanging up zombie call. Be scared.\n");
dialog_lock(p, TRUE);
if (option_debug && sipdebug)
ast_log(LOG_DEBUG, "update_call_counter(%s) - decrement call limit counter on hangup\n", p->peername);
- update_call_counter(p, DEC_CALL_LIMIT);
+ update_call_counter(p, DEC_CALL_LIMIT); /* Fix call limit counter */
/* Determine how to disconnect */
if (p->owner != ast) {
@@ -1353,6 +1352,7 @@
if (p->vad)
ast_dsp_free(p->vad);
+ /* Disconnect us from the owner */
p->owner = NULL;
ast->tech_pvt = NULL;
@@ -1408,8 +1408,6 @@
audioqos = ast_rtp_get_quality(p->rtp);
if (p->vrtp)
videoqos = ast_rtp_get_quality(p->vrtp);
- /* Send a hangup */
- transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1);
/* Get RTCP quality before end of call */
if (!ast_test_flag(&p->flags[0], SIP_NO_HISTORY)) {
@@ -1423,6 +1421,9 @@
if (p->vrtp && oldowner)
pbx_builtin_setvar_helper(oldowner, "RTPVIDEOQOS", videoqos);
dialogstatechange(p, DIALOG_STATE_TERMINATED);
+
+ /* Send a hangup */
+ transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1);
} else {
/* Note we will need a BYE when this all settles out
but we can't send one while we have "INVITE" outstanding. */
@@ -1433,6 +1434,9 @@
}
if (needdestroy)
ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
+
+ if(!ast_test_flag(&p->flags[0], SIP_PENDINGBYE))
+ sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); /* If we don't get answer in 32 secs, destroy */
dialog_lock(p, FALSE);
return 0;
}
@@ -2343,7 +2347,7 @@
/* Bump branch even on initial requests */
build_via(p, TRUE);
- if (init = 2) /* open a new dialog */
+ if (init == 2) /* open a new dialog */
initreqprep(&req, p, sipmethod);
else
reqprep(&req, p, sipmethod, 0, TRUE);
@@ -4147,25 +4151,26 @@
if (!strcasecmp(c, "application/dtmf-relay") ||
!strcasecmp(c, "application/vnd.nortelnetworks.digits")) {
+ if (p->state == DIALOG_STATE_TRYING) { /* INFO outside of a dialog */
+ transmit_final_response(p, "481 Call leg/transaction does not exist", req, XMIT_UNRELIABLE); /* Should return error */
+ return;
+ }
+
/* Try getting the "signal=" part */
if (ast_strlen_zero(c = get_body(req, "Signal")) && ast_strlen_zero(c = get_body(req, "d"))) {
ast_log(LOG_WARNING, "Unable to retrieve DTMF signal from INFO message from %s\n", p->callid);
transmit_response(p, "200 OK", req); /* Should return error */
return;
- } else {
+ } else
ast_copy_string(buf, c, sizeof(buf));
- }
- if (!p->owner) { /* not a PBX call */
- transmit_response(p, "481 Call leg/transaction does not exist", req);
- sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
- return;
- }
if (ast_strlen_zero(buf)) {
+ /* Nothing there folks, move on. */
transmit_response(p, "200 OK", req);
return;
}
+ /* We have a DTMF code in the attachment */
if (buf[0] == '*')
event = 10;
@@ -4214,7 +4219,7 @@
ast_cdr_setuserfield(ast_bridged_channel(p->owner), c);
transmit_response(p, "200 OK", req);
} else {
- transmit_response(p, "403 Unauthorized", req);
+ transmit_response(p, "415 Unsupported media type", req);
}
return;
}
@@ -4276,7 +4281,7 @@
build_callid_pvt(p);
ast_cli(fd, "Sending NOTIFY of type '%s' to '%s'\n", argv[2], argv[i]);
transmit_sip_request(p, &req);
- sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+ sip_scheddestroy(p, -1);
}
return RESULT_SUCCESS;
@@ -4926,347 +4931,233 @@
Well, as long as it's not a 100 response... since we might
need to hang around for something more "definitive" */
- handle_response_peerpoke(p, resp, req);
- } else if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
- switch(resp) {
- case 100: /* 100 Trying */
- if (sipmethod == SIP_INVITE)
- handle_response_invite(p, resp, rest, req);
- break;
- case 183: /* 183 Session Progress */
- if (sipmethod == SIP_INVITE)
- handle_response_invite(p, resp, rest, req);
- break;
- case 180: /* 180 Ringing */
- if (sipmethod == SIP_INVITE)
- handle_response_invite(p, resp, rest, req);
- break;
- case 200: /* 200 OK */
- p->authtries = 0; /* Reset authentication counter */
- if (sipmethod == SIP_MESSAGE) {
- /* We successfully transmitted a message */
- ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
- } else if (sipmethod == SIP_INVITE) {
- handle_response_invite(p, resp, rest, req);
- } else if (sipmethod == SIP_NOTIFY) {
- /* They got the notify, this is the end */
- if (p->owner) {
- if (!p->refer) {
- ast_log(LOG_WARNING, "Notify answer on an owned channel? - %s\n", p->owner->name);
- ast_queue_hangup(p->owner);
- } else if (option_debug > 3)
- ast_log(LOG_DEBUG, "Got OK on REFER Notify message\n");
- } else {
- if (p->subscribed == NONE)
- ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
- }
- dialogstatechange(p, DIALOG_STATE_TERMINATED);
- } else if (sipmethod == SIP_REGISTER)
- res = handle_response_register(p, resp, rest, req, req->seqno);
- else if (sipmethod == SIP_BYE) /* Ok, we're ready to go */
- ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
- break;
- case 202: /* Transfer accepted */
- if (sipmethod == SIP_REFER)
- handle_response_refer(p, resp, rest, req);
- break;
- case 401: /* Not www-authorized on SIP method */
- if (sipmethod == SIP_INVITE)
- handle_response_invite(p, resp, rest, req);
- else if (sipmethod == SIP_REFER)
- handle_response_refer(p, resp, rest, req);
- else if (p->registry && sipmethod == SIP_REGISTER)
- res = handle_response_register(p, resp, rest, req, req->seqno);
- else {
- ast_log(LOG_WARNING, "Got authentication request (401) on unknown %s to '%s'\n", sip_method2txt(sipmethod), get_header(req, "To"));
+ return handle_response_peerpoke(p, resp, req);
+ }
+
+ switch(resp) {
+ case 100: /* 100 Trying */
+ if (sipmethod == SIP_INVITE)
+ handle_response_invite(p, resp, rest, req);
+ break;
+ case 183: /* 183 Session Progress */
+ if (sipmethod == SIP_INVITE)
+ handle_response_invite(p, resp, rest, req);
+ break;
+ case 180: /* 180 Ringing */
+ if (sipmethod == SIP_INVITE)
+ handle_response_invite(p, resp, rest, req);
+ break;
+ case 200: /* 200 OK */
+ p->authtries = 0; /* Reset authentication counter */
+ if (sipmethod == SIP_MESSAGE) {
+ /* We successfully transmitted a message */
+ ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
+ } else if (sipmethod == SIP_CANCEL) {
+ if (option_debug)
+ ast_log(LOG_DEBUG, "Got 200 OK on CANCEL\n");
+
+ /* Wait for 487, then destroy */
+ } else if (sipmethod == SIP_INVITE) {
+ handle_response_invite(p, resp, rest, req);
+ } else if (sipmethod == SIP_NOTIFY) {
+ /* They got the notify, this is the end */
+ if (p->owner) {
+ if (!p->refer) {
+ ast_log(LOG_WARNING, "Notify answer on an owned channel? - %s\n", p->owner->name);
+ ast_queue_hangup(p->owner);
+ } else if (option_debug > 3)
+ ast_log(LOG_DEBUG, "Got OK on REFER Notify message\n");
+ } else {
+ if (p->subscribed == NONE)
+ ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
+ }
+ dialogstatechange(p, DIALOG_STATE_TERMINATED);
+ } else if (sipmethod == SIP_REGISTER)
+ res = handle_response_register(p, resp, rest, req, req->seqno);
+ else if (sipmethod == SIP_BYE) /* Ok, we're ready to go */
+ ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
+ break;
+ case 202: /* Transfer accepted */
+ if (sipmethod == SIP_REFER)
+ handle_response_refer(p, resp, rest, req);
+ break;
+ case 401: /* Not www-authorized on SIP method */
+ case 407: /* Proxy auth required */
+ if (sipmethod == SIP_INVITE)
+ handle_response_invite(p, resp, rest, req);
+ else if (sipmethod == SIP_REFER)
+ handle_response_refer(p, resp, rest, req);
+ else if (p->registry && sipmethod == SIP_REGISTER)
+ res = handle_response_register(p, resp, rest, req, req->seqno);
+ else if (sipmethod == SIP_BYE) {
+ if (ast_strlen_zero(p->authname))
+ ast_log(LOG_WARNING, "Asked to authenticate %s, to %s:%d but we have no matching peer!\n",
+ msg, ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port));
+ if (p->authtries == MAX_AUTHTRIES || do_proxy_auth(p, req, resp, sipmethod, 0)) {
+ ast_log(LOG_NOTICE, "Failed to authenticate on %s to '%s'\n", msg, get_header(&p->initreq, "From"));
ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
}
+ } else {
+ ast_log(LOG_WARNING, "Got authentication request (401) on unknown %s to '%s'\n", sip_method2txt(sipmethod), get_header(req, "To"));
+ ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
+ }
+ break;
+ case 403: /* Forbidden - we failed authentication */
+ if (sipmethod == SIP_INVITE)
+ handle_response_invite(p, resp, rest, req);
+ else if (p->registry && sipmethod == SIP_REGISTER)
+ res = handle_response_register(p, resp, rest, req, req->seqno);
+ else {
+ ast_log(LOG_WARNING, "Forbidden - maybe wrong password on authentication for %s\n", msg);
+ ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
+ }
+ break;
+ case 404: /* Not found */
+ if (p->registry && sipmethod == SIP_REGISTER)
+ res = handle_response_register(p, resp, rest, req, req->seqno);
+ else if (sipmethod == SIP_INVITE)
+ handle_response_invite(p, resp, rest, req);
+ else if (owner)
+ ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
+ break;
+ case 423: /* Interval too brief */
+ if (sipmethod == SIP_REGISTER)
+ res = handle_response_register(p, resp, rest, req, req->seqno);
+ break;
+ case 481: /* Call leg does not exist */
+ if (sipmethod == SIP_INVITE) {
+ /* First we ACK */
+ transmit_request(p, SIP_ACK, req->seqno, XMIT_UNRELIABLE, FALSE);
+ ast_log(LOG_WARNING, "INVITE with REPLACEs failed to '%s'\n", get_header(&p->initreq, "From"));
+ if (owner)
+ ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
+ dialogstatechange(p, DIALOG_STATE_TERMINATED);
+ sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+ } else if (sipmethod == SIP_REFER) {
+ /* A transfer with Replaces did not work */
+ /* OEJ: We should Set flag, cancel the REFER, go back
+ to original call - but right now we can't */
+ ast_log(LOG_WARNING, "Remote host can't match request %s to call '%s'. Giving up.\n", sip_method2txt(sipmethod), p->callid);
+ if (owner)
+ ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
+ ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
+ } else if (sipmethod == SIP_BYE) {
+ /* The other side has no transaction to bye,
+ just assume it's all right then */
+ ast_log(LOG_WARNING, "Remote host can't match request %s to call '%s'. Giving up.\n", sip_method2txt(sipmethod), p->callid);
+ } else if (sipmethod == SIP_CANCEL) {
+ /* The other side has no transaction to cancel,
+ just assume it's all right then */
+ ast_log(LOG_WARNING, "Remote host can't match request %s to call '%s'. Giving up.\n", sip_method2txt(sipmethod), p->callid);
+ } else {
+ ast_log(LOG_WARNING, "Remote host can't match request %s to call '%s'. Giving up.\n", sip_method2txt(sipmethod), p->callid);
+ /* Guessing that this is not an important request */
+ }
+ break;
+ case 491: /* Pending */
+ if (sipmethod == SIP_INVITE)
+ handle_response_invite(p, resp, rest, req);
+ else {
+ if (option_debug)
+ ast_log(LOG_DEBUG, "Got 491 on %s, unspported. Call ID %s\n", sip_method2txt(sipmethod), p->callid);
+ ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
+ }
+ break;
+ case 501: /* Not Implemented */
+ if (sipmethod == SIP_INVITE)
+ handle_response_invite(p, resp, rest, req);
+ else if (sipmethod == SIP_REFER)
+ handle_response_refer(p, resp, rest, req);
+ else {
+ ast_log(LOG_WARNING, "Host '%s' does not implement '%s'\n", ast_inet_ntoa(p->sa.sin_addr), msg);
+ }
+ break;
+ case 603: /* Declined transfer */
+ if (sipmethod == SIP_REFER) {
+ handle_response_refer(p, resp, rest, req);
break;
- case 403: /* Forbidden - we failed authentication */
- if (sipmethod == SIP_INVITE)
- handle_response_invite(p, resp, rest, req);
- else if (p->registry && sipmethod == SIP_REGISTER)
- res = handle_response_register(p, resp, rest, req, req->seqno);
- else {
- ast_log(LOG_WARNING, "Forbidden - maybe wrong password on authentication for %s\n", msg);
- ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
- }
+ } else if (sipmethod == SIP_INVITE) {
+ handle_response_invite(p, resp, rest, req);
break;
- case 404: /* Not found */
- if (p->registry && sipmethod == SIP_REGISTER)
- res = handle_response_register(p, resp, rest, req, req->seqno);
- else if (sipmethod == SIP_INVITE)
- handle_response_invite(p, resp, rest, req);
- else if (owner)
- ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
- break;
- case 407: /* Proxy auth required */
- if (sipmethod == SIP_INVITE)
- handle_response_invite(p, resp, rest, req);
- else if (sipmethod == SIP_REFER)
- handle_response_refer(p, resp, rest, req);
- else if (p->registry && sipmethod == SIP_REGISTER)
- res = handle_response_register(p, resp, rest, req, req->seqno);
- else if (sipmethod == SIP_BYE) {
- if (ast_strlen_zero(p->authname))
- ast_log(LOG_WARNING, "Asked to authenticate %s, to %s:%d but we have no matching peer!\n",
- msg, ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port));
- ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
- if (p->authtries == MAX_AUTHTRIES || do_proxy_auth(p, req, 407, sipmethod, 0)) {
- ast_log(LOG_NOTICE, "Failed to authenticate on %s to '%s'\n", msg, get_header(&p->initreq, "From"));
- ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
+ }
+ /* Fallthrough */
+ default:
+ if ((resp >= 300) && (resp < 700)) {
+ /* Fatal response */
+ 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_set_flag(&p->flags[0], SIP_ALREADYGONE);
+ stop_media_flows(p); /* Stop RTP, VRTP and UDPTL */
+ /* XXX Locking issues?? XXX */
+ switch(resp) {
+ case 300: /* Multiple Choices */
+ case 301: /* Moved permenantly */
+ case 302: /* Moved temporarily */
+ case 305: /* Use Proxy */
+ case 486: /* Busy here */
+ case 600: /* Busy everywhere */
+ if (sipmethod == SIP_INVITE)
+ handle_response_invite(p, resp, rest, req);
+ break;
+ case 487: /* Response on INVITE that has been CANCELled */
+ /* channel now destroyed - dec the inUse counter */
+ if (owner)
+ ast_queue_hangup(p->owner);
+ update_call_counter(p, DEC_CALL_LIMIT);
+ break;
+ case 488: /* Not acceptable here - codec error */
+ if (sipmethod == SIP_INVITE) {
+ handle_response_invite(p, resp, rest, req);
+ break;
}
- } else /* We can't handle this, giving up in a bad way */
- ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
-
- break;
- case 423: /* Interval too brief */
- if (sipmethod == SIP_REGISTER)
- res = handle_response_register(p, resp, rest, req, req->seqno);
- break;
- case 481: /* Call leg does not exist */
- if (sipmethod == SIP_INVITE) {
- /* First we ACK */
- transmit_request(p, SIP_ACK, req->seqno, XMIT_UNRELIABLE, FALSE);
- ast_log(LOG_WARNING, "INVITE with REPLACEs failed to '%s'\n", get_header(&p->initreq, "From"));
+ case 482:
+ /* So we treat this as a call
+ forward and hope we end up at the right place... */
+ if (option_debug)
+ ast_log(LOG_DEBUG, "Hairpin detected, setting up call forward for what it's worth\n");
+ if (p->owner)
+ ast_string_field_build(p->owner, call_forward,
+ "Local/%s@%s", p->peername, p->context);
+ /* Fall through */
+ case 480: /* Temporarily Unavailable */
+ case 404: /* Not Found */
+ case 410: /* Gone */
+ case 400: /* Bad Request */
+ case 500: /* Server error */
+ if (sipmethod == SIP_REFER) {
+ handle_response_refer(p, resp, rest, req);
+ break;
+ }
+ /* Fall through */
+ case 503: /* Service Unavailable */
if (owner)
ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
- dialogstatechange(p, DIALOG_STATE_TERMINATED);
- sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
- } else if (sipmethod == SIP_REFER) {
- /* A transfer with Replaces did not work */
- /* OEJ: We should Set flag, cancel the REFER, go back
- to original call - but right now we can't */
- ast_log(LOG_WARNING, "Remote host can't match request %s to call '%s'. Giving up.\n", sip_method2txt(sipmethod), p->callid);
+ break;
+ default:
+ /* Send hangup */
if (owner)
- ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
- ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
- } else if (sipmethod == SIP_BYE) {
- /* The other side has no transaction to bye,
- just assume it's all right then */
- ast_log(LOG_WARNING, "Remote host can't match request %s to call '%s'. Giving up.\n", sip_method2txt(sipmethod), p->callid);
- } else if (sipmethod == SIP_CANCEL) {
- /* The other side has no transaction to cancel,
- just assume it's all right then */
- ast_log(LOG_WARNING, "Remote host can't match request %s to call '%s'. Giving up.\n", sip_method2txt(sipmethod), p->callid);
- } else {
- ast_log(LOG_WARNING, "Remote host can't match request %s to call '%s'. Giving up.\n", sip_method2txt(sipmethod), p->callid);
- /* Guessing that this is not an important request */
- }
- break;
- case 491: /* Pending */
- if (sipmethod == SIP_INVITE)
- handle_response_invite(p, resp, rest, req);
- else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Got 491 on %s, unspported. Call ID %s\n", sip_method2txt(sipmethod), p->callid);
- ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
- }
- break;
- case 501: /* Not Implemented */
- if (sipmethod == SIP_INVITE)
- handle_response_invite(p, resp, rest, req);
- else if (sipmethod == SIP_REFER)
- handle_response_refer(p, resp, rest, req);
- else {
- ast_log(LOG_WARNING, "Host '%s' does not implement '%s'\n", ast_inet_ntoa(p->sa.sin_addr), msg);
- }
- break;
- case 603: /* Declined transfer */
- if (sipmethod == SIP_REFER) {
- handle_response_refer(p, resp, rest, req);
- break;
- } else if (sipmethod == SIP_INVITE) {
- handle_response_invite(p, resp, rest, req);
+ ast_queue_hangup(p->owner);
break;
}
- /* Fallthrough */
- default:
- if ((resp >= 300) && (resp < 700)) {
- /* Fatal response */
- 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_set_flag(&p->flags[0], SIP_ALREADYGONE);
- stop_media_flows(p); /* Stop RTP, VRTP and UDPTL */
- /* XXX Locking issues?? XXX */
- switch(resp) {
- case 300: /* Multiple Choices */
- case 301: /* Moved permenantly */
- case 302: /* Moved temporarily */
- case 305: /* Use Proxy */
- case 486: /* Busy here */
- case 600: /* Busy everywhere */
- if (sipmethod == SIP_INVITE)
- handle_response_invite(p, resp, rest, req);
- break;
- case 487: /* Response on INVITE that has been CANCELled */
- /* channel now destroyed - dec the inUse counter */
- if (owner)
- ast_queue_hangup(p->owner);
- update_call_counter(p, DEC_CALL_LIMIT);
- break;
- case 488: /* Not acceptable here - codec error */
- if (sipmethod == SIP_INVITE) {
- handle_response_invite(p, resp, rest, req);
- break;
- }
- case 482: /*
- \note SIP is incapable of performing a hairpin call, which
- is yet another failure of not having a layer 2 (again, YAY
- IETF for thinking ahead). So we treat this as a call
- forward and hope we end up at the right place... */
- if (option_debug)
- ast_log(LOG_DEBUG, "Hairpin detected, setting up call forward for what it's worth\n");
- if (p->owner)
- ast_string_field_build(p->owner, call_forward,
- "Local/%s@%s", p->peername, p->context);
- /* Fall through */
- case 480: /* Temporarily Unavailable */
- case 404: /* Not Found */
- case 410: /* Gone */
- case 400: /* Bad Request */
- case 500: /* Server error */
- if (sipmethod == SIP_REFER) {
- handle_response_refer(p, resp, rest, req);
- break;
- }
- /* Fall through */
- case 503: /* Service Unavailable */
- if (owner)
- ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
- break;
- default:
- /* Send hangup */
- if (owner)
- ast_queue_hangup(p->owner);
- break;
- }
- /* ACK on invite */
- if (sipmethod == SIP_INVITE)
- transmit_request(p, SIP_ACK, req->seqno, XMIT_UNRELIABLE, FALSE);
- ast_set_flag(&p->flags[0], SIP_ALREADYGONE);
- if (!p->owner)
- ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
- } else if ((resp >= 100) && (resp < 200)) {
- if (sipmethod == SIP_INVITE) {
- if (!ast_test_flag(req, SIP_PKT_IGNORE))
- sip_cancel_destroy(p);
- if (find_sdp(req))
- process_sdp(p, req);
- if (p->owner) {
- /* Queue a progress frame */
- ast_queue_control(p->owner, AST_CONTROL_PROGRESS);
- }
- }
- } else
- ast_log(LOG_NOTICE, "Dont know how to handle a %d %s response from %s\n", resp, rest, p->owner ? p->owner->name : ast_inet_ntoa(p->sa.sin_addr));
- }
- } else {
- /* Responses to OUTGOING SIP requests on INCOMING calls
- get handled here. As well as out-of-call message responses */
- if (ast_test_flag(req, SIP_PKT_DEBUG))
- ast_verbose("SIP Response message for INCOMING dialog %s arrived\n", msg);
-
- if (sipmethod == SIP_INVITE && resp == 200) {
- /* Tags in early session is replaced by the tag in 200 OK, which is
- the final reply to our INVITE */
- char tag[128];
-
- gettag(req->to, tag, sizeof(tag));
- ast_string_field_set(p, theirtag, tag);
- }
-
- switch(resp) {
- case 200:
+ /* ACK on invite */
+ if (sipmethod == SIP_INVITE)
+ transmit_request(p, SIP_ACK, req->seqno, XMIT_UNRELIABLE, FALSE);
+ ast_set_flag(&p->flags[0], SIP_ALREADYGONE);
+ if (!p->owner)
+ ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
+ } else if ((resp >= 100) && (resp < 200)) {
if (sipmethod == SIP_INVITE) {
- handle_response_invite(p, resp, rest, req);
- } else if (sipmethod == SIP_CANCEL) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Got 200 OK on CANCEL\n");
-
- /* Wait for 487, then destroy */
- } else if (sipmethod == SIP_NOTIFY) {
- /* They got the notify, this is the end */
+ if (!ast_test_flag(req, SIP_PKT_IGNORE))
+ sip_cancel_destroy(p);
+ if (find_sdp(req))
+ process_sdp(p, req);
if (p->owner) {
- ast_log(LOG_WARNING, "Notify answer on an owned channel?\n");
- /* ast_queue_hangup(p->owner); Disabled */
- } else {
- if (!p->subscribed && !p->refer)
- ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
- }
- } else if (sipmethod == SIP_BYE)
- ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
- else if (sipmethod == SIP_MESSAGE)
- /* We successfully transmitted a message */
- /* XXX Why destroy this pvt after message transfer? Bad */
- ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
- else if (sipmethod == SIP_BYE)
- /* Ok, we're ready to go */
- ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
- break;
- case 202: /* Transfer accepted */
- if (sipmethod == SIP_REFER)
- handle_response_refer(p, resp, rest, req);
- break;
- case 401: /* www-auth */
- case 407:
- if (sipmethod == SIP_REFER)
- handle_response_refer(p, resp, rest, req);
- else if (sipmethod == SIP_INVITE)
- handle_response_invite(p, resp, rest, req);
- else if (sipmethod == SIP_BYE) {
- if (p->authtries == MAX_AUTHTRIES || do_proxy_auth(p, req, resp, sipmethod, 0)) {
- ast_log(LOG_NOTICE, "Failed to authenticate on %s to '%s'\n", msg, get_header(&p->initreq, "From"));
- ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
+ /* Queue a progress frame */
+ ast_queue_control(p->owner, AST_CONTROL_PROGRESS);
}
}
- break;
- case 481: /* Call leg does not exist */
- if (sipmethod == SIP_INVITE) {
- /* Re-invite failed */
- handle_response_invite(p, resp, rest, req);
- } else if (sipmethod == SIP_BYE) {
- ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
- } else if (sipdebug) {
- ast_log (LOG_DEBUG, "Remote host can't match request %s to call '%s'. Giving up\n", sip_method2txt(sipmethod), p->callid);
- }
- break;
- case 501: /* Not Implemented */
- if (sipmethod == SIP_INVITE)
- handle_response_invite(p, resp, rest, req);
- else if (sipmethod == SIP_REFER)
- handle_response_refer(p, resp, rest, req);
- break;
- case 603: /* Declined transfer */
- if (sipmethod == SIP_REFER) {
- handle_response_refer(p, resp, rest, req);
- break;
- }
- /* Fallthrough */
- default: /* Errors without handlers */
- if ((resp >= 100) && (resp < 200)) {
- if (sipmethod == SIP_INVITE) { /* re-invite */
- if (!ast_test_flag(req, SIP_PKT_IGNORE))
- sip_cancel_destroy(p);
- }
- }
- if ((resp >= 300) && (resp < 700)) {
- if ((option_verbose > 2) && (resp != 487))
- ast_verbose(VERBOSE_PREFIX_3 "Incoming call: Got SIP response %d \"%s\" back from %s\n", resp, rest, ast_inet_ntoa(p->sa.sin_addr));
- switch(resp) {
- case 488: /* Not acceptable here - codec error */
- case 603: /* Decline */
- case 500: /* Server error */
- case 503: /* Service Unavailable */
-
- if (sipmethod == SIP_INVITE) { /* re-invite failed */
- sip_cancel_destroy(p);
- }
- break;
- }
- }
- break;
- }
+ } else
+ ast_log(LOG_NOTICE, "Dont know how to handle a %d %s response from %s\n", resp, rest, p->owner ? p->owner->name : ast_inet_ntoa(p->sa.sin_addr));
}
}
@@ -5635,18 +5526,19 @@
/* This is a call to ourself. Send ourselves an error code and stop
processing immediately, as SIP really has no good mechanism for
being able to call yourself */
- /* we need to check the tags. If they're different, this is
+ /* we need to check the tags and the branch. If they're different, this is
in fact a forked call through a SIP proxy somewhere. */
- transmit_response(p, "482 Loop Detected", req);
- /* We do NOT destroy p here, so that our response will be accepted */
+ transmit_final_response(p, "482 Loop Detected", req, XMIT_RELIABLE);
return 0;
}
+ /* Check if we already have a pending invite. If so, then deny this one */
if (!ast_test_flag(req, SIP_PKT_IGNORE) && p->pendinginvite) {
/* We already have a pending invite. Sorry. You are on hold. */
transmit_response(p, "491 Request Pending", req);
if (option_debug)
ast_log(LOG_DEBUG, "Got INVITE on call where we already have pending INVITE, deferring that - %s\n", p->callid);
+ /* No destruction here, we have a current dialog */
return 0;
}
@@ -5674,9 +5566,8 @@
ast_uri_decode(replace_id);
if (!p->refer && !sip_refer_allocate(p)) {
- transmit_response(p, "500 Server Internal Error", req);
append_history(p, "Xfer", "INVITE/Replace Failed. Out of memory.");
- sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+ transmit_final_response(p, "500 Server Internal Error", req, XMIT_RELIABLE);
return -1;
}
@@ -5711,7 +5602,7 @@
*/
if ((p->refer->refer_call = get_sip_dialog_byid_locked(replace_id, totag, fromtag)) == NULL) {
ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-existent call id (%s)!\n", replace_id);
- transmit_response(p, "481 Call Leg Does Not Exist (Replaces)", req);
+ transmit_final_response(p, "481 Call leg Does not exit (Replaces)", req, XMIT_RELIABLE);
error = 1;
}
@@ -5724,7 +5615,7 @@
if (p->refer->refer_call == p) {
ast_log(LOG_NOTICE, "INVITE with replaces into it's own call id (%s == %s)!\n", replace_id, p->callid);
p->refer->refer_call = NULL;
- transmit_response(p, "400 Bad request", req); /* The best way to not not accept the transfer */
+ transmit_final_response(p, "400 Bad request", req, XMIT_RELIABLE);
error = 1;
}
@@ -5732,19 +5623,18 @@
/* Oops, someting wrong anyway, no owner, no call */
ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-existing call id (%s)!\n", replace_id);
/* Check for better return code */
- transmit_response(p, "481 Call Leg Does Not Exist (Replace)", req);
+ transmit_final_response(p, "481 Call leg Does not exit (Replaces)", req, XMIT_RELIABLE);
error = 1;
}
if (!error && p->refer->refer_call->owner->_state != AST_STATE_RING && p->refer->refer_call->owner->_state != AST_STATE_UP ) {
ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-ringing or active call id (%s)!\n", replace_id);
- transmit_response(p, "603 Declined (Replaces)", req);
+ transmit_final_response(p, "603 Declined (Replaces)", req, XMIT_RELIABLE);
error = 1;
}
if (error) { /* Give up this dialog */
append_history(p, "Xfer", "INVITE/Replace Failed.");
- sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
dialog_lock(p, FALSE);
if (p->refer->refer_call) {
dialog_lock(p->refer->refer_call, FALSE);
@@ -5815,8 +5705,7 @@
if (find_sdp(req)) {
if (process_sdp(p, req)) {
/* Unacceptable codecs */
- transmit_response_reliable(p, "488 Not acceptable here", req);
- sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+ transmit_final_response(p, "488 Not acceptable here", req, XMIT_RELIABLE);
if (option_debug)
ast_log(LOG_DEBUG, "No compatible codecs for this SIP call.\n");
return -1;
@@ -5827,12 +5716,6 @@
ast_log(LOG_DEBUG, "No SDP in Invite, third party call control\n");
}
- /* Queue NULL frame to prod ast_rtp_bridge if appropriate */
- /* This seems redundant ... see !p-owner above */
- if (p->owner)
- ast_queue_frame(p->owner, &ast_null_frame);
-
-
/* Initialize the context if it hasn't been already */
if (ast_strlen_zero(p->context))
ast_string_field_set(p, context, global.default_context);
@@ -5844,8 +5727,7 @@
if ((res = update_call_counter(p, INC_CALL_LIMIT))) {
if (res < 0) {
ast_log(LOG_NOTICE, "Failed to place call for user %s, too many calls\n", p->peername);
- transmit_response_reliable(p, "480 Temporarily Unavailable (Call limit) ", req);
- sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+ transmit_final_response(p, "480 Temporarily Unavailable", req, XMIT_RELIABLE);
}
return 0;
}
@@ -5859,14 +5741,13 @@
}
if (!replace_id && gotdest) { /* No matching extension found */
- if (gotdest == 1 && ast_test_flag(&p->flags[1], SIP_PAGE2_ALLOWOVERLAP)) {
- transmit_response_reliable(p, "484 Address Incomplete", req);
- update_call_counter(p, DEC_CALL_LIMIT);
- } else {
- transmit_response_reliable(p, "404 Not Found", req);
- update_call_counter(p, DEC_CALL_LIMIT);
- }
- sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+ char *response;
+ if (gotdest == 1 && ast_test_flag(&p->flags[1], SIP_PAGE2_ALLOWOVERLAP))
+ response = "484 Address Incomplete";
+ else
+ response = "404 Not Found";
+ transmit_final_response(p, response, req, XMIT_RELIABLE);
+ update_call_counter(p, DEC_CALL_LIMIT);
} else {
/* If no extension was specified, use the s one */
/* Basically for calling to IP/Host name only */
@@ -5918,31 +5799,27 @@
ast_setstate(c, AST_STATE_RING);
if (strcmp(p->exten, ast_pickup_ext())) { /* Call to extension -start pbx on this call */
enum ast_pbx_result res;
+ const char *response = NULL;
res = ast_pbx_start(c);
switch(res) {
case AST_PBX_FAILED:
ast_log(LOG_WARNING, "Failed to start PBX :(\n");
- if (ast_test_flag(req, SIP_PKT_IGNORE))
- transmit_response(p, "503 Unavailable", req);
- else
- transmit_response_reliable(p, "503 Unavailable", req);
+ response = "503 Unavailable";
break;
case AST_PBX_CALL_LIMIT:
ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n");
- if (ast_test_flag(req, SIP_PKT_IGNORE))
- transmit_response(p, "480 Temporarily Unavailable", req);
- else
- transmit_response_reliable(p, "480 Temporarily Unavailable", req);
+ response = "480 Temporarily Unavailable";
break;
case AST_PBX_SUCCESS:
/* nothing to do */
break;
}
+ if (response)
+ transmit_final_response(p, response, req, ast_test_flag(req, SIP_PKT_IGNORE) ? XMIT_UNRELIABLE : XMIT_RELIABLE);
if (res) {
-
/* Unlock locks so ast_hangup can do its magic */
ast_channel_unlock(c);
dialog_lock(p, FALSE);
@@ -5954,10 +5831,7 @@
ast_channel_unlock(c);
if (ast_pickup_call(c)) {
ast_log(LOG_NOTICE, "Nothing to pick up for %s\n", p->callid);
- if (ast_test_flag(req, SIP_PKT_IGNORE))
- transmit_response(p, "503 Unavailable", req); /* OEJ - Right answer? */
- else
- transmit_response_reliable(p, "503 Unavailable", req);
+ transmit_final_response(p, "503 Unavailable", req, ast_test_flag(req, SIP_PKT_IGNORE) ? XMIT_UNRELIABLE : XMIT_RELIABLE);
ast_set_flag(&p->flags[0], SIP_ALREADYGONE);
/* Unlock locks so ast_hangup can do its magic */
dialog_lock(p, FALSE);
@@ -5974,9 +5848,13 @@
break;
case AST_STATE_RING:
transmit_response(p, "100 Trying", req);
+ if (!p->owner)
+ dialogstatechange(p, DIALOG_STATE_PROCEEDING);
break;
case AST_STATE_RINGING:
transmit_response(p, "180 Ringing", req);
+ if (!p->owner)
+ dialogstatechange(p, DIALOG_STATE_EARLY);
break;
case AST_STATE_UP:
if (option_debug > 1)
@@ -6002,33 +5880,27 @@
dialog_lock(bridgepvt, FALSE);
if (option_debug > 1)
ast_log(LOG_DEBUG,"T38 state changed to %d on channel %s\n", bridgepvt->t38.state, bridgepeer->name);
- if (ast_test_flag(req, SIP_PKT_IGNORE))
- transmit_response(p, "488 Not acceptable here", req);
- else
- transmit_response_reliable(p, "488 Not acceptable here", req);
- sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+ transmit_final_response(p, "488 Not Acceptable here", req, ast_test_flag(req, SIP_PKT_IGNORE) ? XMIT_UNRELIABLE : XMIT_RELIABLE);
}
} else {
/* The other side is already setup for T.38 most likely so we need to acknowledge this too */
transmit_response_with_attachment(WITH_T38_SDP, p, "200 OK", req, XMIT_CRITICAL);
+ dialogstatechange(p, DIALOG_STATE_CONFIRMED);
p->t38.state = T38_ENABLED;
if (option_debug)
ast_log(LOG_DEBUG, "T38 state changed to %d on channel %s\n", p->t38.state, p->owner ? p->owner->name : "<none>");
}
} else {
/* Other side is not a SIP channel */
- if (ast_test_flag(req, SIP_PKT_IGNORE))
- transmit_response(p, "488 Not acceptable here", req);
- else
- transmit_response_reliable(p, "488 Not acceptable here", req);
+ transmit_final_response(p, "488 Not Acceptable here", req, ast_test_flag(req, SIP_PKT_IGNORE) ? XMIT_UNRELIABLE : XMIT_RELIABLE);
p->t38.state = T38_DISABLED;
if (option_debug > 1)
ast_log(LOG_DEBUG,"T38 state changed to %d on channel %s\n", p->t38.state, p->owner ? p->owner->name : "<none>");
- sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
}
} else {
/* we are not bridged in a call */
transmit_response_with_attachment(WITH_T38_SDP, p, "200 OK", req, XMIT_CRITICAL);
+ dialogstatechange(p, DIALOG_STATE_CONFIRMED);
p->t38.state = T38_ENABLED;
if (option_debug)
ast_log(LOG_DEBUG,"T38 state changed to %d on channel %s\n", p->t38.state, p->owner ? p->owner->name : "<none>");
@@ -6047,18 +5919,17 @@
if (bridgepvt->t38.state == T38_ENABLED) {
ast_log(LOG_WARNING, "RTP re-invite after T38 session not handled yet !\n");
/* Insted of this we should somehow re-invite the other side of the bridge to RTP */
- if (ast_test_flag(req, SIP_PKT_IGNORE))
[... 350 lines stripped ...]
More information about the asterisk-commits
mailing list