[svn-commits] mmichelson: branch group/v14_colp r146401 - /team/group/v14_colp/channels/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Sat Oct 4 13:23:03 CDT 2008


Author: mmichelson
Date: Sat Oct  4 13:23:03 2008
New Revision: 146401

URL: http://svn.digium.com/view/asterisk?view=rev&rev=146401
Log:
Backport of most of chan_sip from the issue8824 branch.
The check_user_full function is quite a bit different
between 1.4, trunk, and the issue8824 branch, so I'm going
to have to get that fixed up for the next commit.

Note: This code does not compile right now and I know this.
This will be fixed in the next commit, which should come
shortly hereafter.


Modified:
    team/group/v14_colp/channels/chan_sip.c

Modified: team/group/v14_colp/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/group/v14_colp/channels/chan_sip.c?view=diff&rev=146401&r1=146400&r2=146401
==============================================================================
--- team/group/v14_colp/channels/chan_sip.c (original)
+++ team/group/v14_colp/channels/chan_sip.c Sat Oct  4 13:23:03 2008
@@ -197,8 +197,6 @@
 #define MAX(a,b) ((a) > (b) ? (a) : (b))
 #endif
 
-#define CALLERID_UNKNOWN        "Unknown"
-
 #define DEFAULT_MAXMS                2000             /*!< Qualification: Must be faster than 2 seconds by default */
 #define DEFAULT_FREQ_OK              60 * 1000        /*!< Qualification: How often to check for the host to be up */
 #define DEFAULT_FREQ_NOTOK           10 * 1000        /*!< Qualification: How often to check, if the host is down... */
@@ -471,6 +469,54 @@
 	{ SIP_OPT_RESPRIORITY,	NOT_SUPPORTED,	"resource-priority" },
 };
 
+/*! \brief Diversion header reasons
+ *
+ * The core defines a bunch of constants used to define
+ * redirecting reasons. This provides a translation table
+ * between those and the strings which may be present in 
+ * a SIP Diversion header
+ */
+static const struct sip_reasons {
+	enum AST_REDIRECTING_REASON code;
+	char * const text;
+} sip_reason_table[] = {
+	{ AST_REDIRECTING_REASON_UNKNOWN, "unknown" },
+	{ AST_REDIRECTING_REASON_USER_BUSY, "user-busy" },
+	{ AST_REDIRECTING_REASON_NO_ANSWER, "no-answer" },
+	{ AST_REDIRECTING_REASON_UNAVAILABLE, "unavailable" },
+	{ AST_REDIRECTING_REASON_UNCONDITIONAL, "unconditional" },
+	{ AST_REDIRECTING_REASON_TIME_OF_DAY, "time-of-day" },
+	{ AST_REDIRECTING_REASON_DO_NOT_DISTURB, "do-not-disturb" },
+	{ AST_REDIRECTING_REASON_DEFLECTION, "deflection" },
+	{ AST_REDIRECTING_REASON_FOLLOW_ME, "follow-me" },
+	{ AST_REDIRECTING_REASON_OUT_OF_ORDER, "out-of-service" },
+	{ AST_REDIRECTING_REASON_AWAY, "away" },
+	{ AST_REDIRECTING_REASON_CALL_FWD_DTE, "unknown"}
+};
+
+static enum AST_REDIRECTING_REASON sip_reason_str_to_code(const char *text) 
+{
+	enum AST_REDIRECTING_REASON ast = AST_REDIRECTING_REASON_UNKNOWN;
+	int i;
+
+	for (i = 0; i < ARRAY_LEN(sip_reason_table); ++i) {
+		if (!strcasecmp(text, sip_reason_table[i].text)) {
+			ast = sip_reason_table[i].code;
+			break;
+		}
+	}
+
+	return ast;
+}
+
+static const char *sip_reason_code_to_str(enum AST_REDIRECTING_REASON code)
+{
+	if (code >= 0 && code < ARRAY_LEN(sip_reason_table)) {
+		return sip_reason_table[code].text;
+	}
+
+	return "unknown";
+}
 
 /*! \brief SIP Methods we support */
 #define ALLOWED_METHODS "INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY"
@@ -759,12 +805,11 @@
 #define SIP_PROG_INBAND_YES	(2 << 25)
 #define SIP_NO_HISTORY		(1 << 27)	/*!< Suppress recording request/response history */
 #define SIP_CALL_LIMIT		(1 << 28)	/*!< Call limit enforced for this call */
-#define SIP_SENDRPID		(1 << 29)	/*!< Remote Party-ID Support */
 #define SIP_INC_COUNT		(1 << 30)	/*!< Did this connection increment the counter of in-use calls? */
 #define SIP_G726_NONSTANDARD	(1 << 31)	/*!< Use non-standard packing for G726-32 data */
 
 #define SIP_FLAGS_TO_COPY \
-	(SIP_PROMISCREDIR | SIP_TRUSTRPID | SIP_SENDRPID | SIP_DTMF | SIP_REINVITE | \
+	(SIP_PROMISCREDIR | SIP_TRUSTRPID | SIP_PAGE2_SENDRPID | SIP_DTMF | SIP_REINVITE | \
 	 SIP_PROG_INBAND | SIP_USECLIENTCODE | SIP_NAT | SIP_G726_NONSTANDARD | \
 	 SIP_USEREQPHONE | SIP_INSECURE_PORT | SIP_INSECURE_INVITE)
 
@@ -801,6 +846,9 @@
 #define SIP_PAGE2_OUTGOING_CALL         (1 << 27)       /*!< 27: Is this an outgoing call? */
 #define SIP_PAGE2_UDPTL_DESTINATION     (1 << 28)       /*!< 28: Use source IP of RTP as destination if NAT is enabled */
 #define SIP_PAGE2_DIALOG_ESTABLISHED    (1 << 29)       /*!< 29: Has a dialog been established? */
+#define SIP_PAGE2_SENDRPID		(3 << 30)	/*!< Remote Party-ID Support */
+#define SIP_PAGE2_SENDRPID_RPID   (1 << 30)   /*!< Use "Remote-Party-ID" header */
+#define SIP_PAGE2_SENDRPID_PAI    (2 << 30)   /*!< Use "P-Asserted-Identity" header */
 
 #define SIP_PAGE2_FLAGS_TO_COPY \
 	(SIP_PAGE2_ALLOWSUBSCRIBE | SIP_PAGE2_ALLOWOVERLAP | SIP_PAGE2_VIDEOSUPPORT | \
@@ -936,6 +984,7 @@
 		AST_STRING_FIELD(mohinterpret);	/*!< MOH class to use when put on hold */
 		AST_STRING_FIELD(mohsuggest);	/*!< MOH class to suggest when putting a peer on hold */
 		AST_STRING_FIELD(rdnis);	/*!< Referring DNIS */
+		AST_STRING_FIELD(redircause);	/*!< Referring cause */
 		AST_STRING_FIELD(theirtag);	/*!< Their tag */
 		AST_STRING_FIELD(username);	/*!< [user] name */
 		AST_STRING_FIELD(peername);	/*!< [peer] name, not set if [user] */
@@ -949,8 +998,6 @@
 		AST_STRING_FIELD(via);		/*!< Via: header */
 		AST_STRING_FIELD(fullcontact);	/*!< The Contact: that the UA registers with us */
 		AST_STRING_FIELD(our_contact);	/*!< Our contact header */
-		AST_STRING_FIELD(rpid);		/*!< Our RPID header */
-		AST_STRING_FIELD(rpid_from);	/*!< Our RPID From header */
 	);
 	unsigned int ocseq;			/*!< Current outgoing seqno */
 	unsigned int icseq;			/*!< Current incoming seqno */
@@ -1277,7 +1324,7 @@
 static int send_request(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, int seqno);
 static void copy_request(struct sip_request *dst, const struct sip_request *src);
 static void receive_message(struct sip_pvt *p, struct sip_request *req);
-static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req);
+static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req, char **name, char **number);
 static int sip_send_mwi_to_peer(struct sip_peer *peer);
 static int does_peer_need_mwi(struct sip_peer *peer);
 
@@ -1491,12 +1538,15 @@
 static int set_address_from_contact(struct sip_pvt *pvt);
 static void check_via(struct sip_pvt *p, const struct sip_request *req);
 static char *get_calleridname(const char *input, char *output, size_t outputsize);
-static int get_rpid_num(const char *input, char *output, int maxlen);
-static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq);
+static int get_rpid(struct sip_pvt *p, struct sip_request *oreq);
+static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq, char **name, char **number, int *reason);
 static int get_destination(struct sip_pvt *p, struct sip_request *oreq);
 static int get_msg_text(char *buf, int len, struct sip_request *req);
 static void free_old_route(struct sip_route *route);
 static int transmit_state_notify(struct sip_pvt *p, int state, int full, int timeout);
+static void update_connectedline(struct sip_pvt *p, const void *data, size_t datalen);
+static void update_redirecting(struct sip_pvt *p, const void *data, size_t datalen);
+static void change_redirecting_information(struct sip_pvt *p, struct sip_request *req);
 
 /*--- Constructing requests and responses */
 static void initialize_initreq(struct sip_pvt *p, struct sip_request *req);
@@ -1518,6 +1568,7 @@
 static int add_line(struct sip_request *req, const char *line);
 static int add_text(struct sip_request *req, const char *text);
 static int add_digit(struct sip_request *req, char digit, unsigned int duration);
+static int add_rpid(struct sip_request *req, struct sip_pvt *p);
 static int add_vidupdate(struct sip_request *req);
 static void add_route(struct sip_request *req, struct sip_route *route);
 static int copy_header(struct sip_request *req, const struct sip_request *orig, const char *field);
@@ -1526,7 +1577,6 @@
 static void set_destination(struct sip_pvt *p, char *uri);
 static void append_date(struct sip_request *req);
 static void build_contact(struct sip_pvt *p);
-static void build_rpid(struct sip_pvt *p);
 
 /*------Request handling functions */
 static int handle_request(struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int *recount, int *nounlock);
@@ -2855,6 +2905,8 @@
 	ast_string_field_set(dialog, mohinterpret, peer->mohinterpret);
 	ast_string_field_set(dialog, tohost, peer->tohost);
 	ast_string_field_set(dialog, fullcontact, peer->fullcontact);
+	ast_string_field_set(dialog, cid_num, peer->cid_num);
+	ast_string_field_set(dialog, cid_name, peer->cid_name);
 	if (!dialog->initreq.headers && !ast_strlen_zero(peer->fromdomain)) {
 		char *tmpcall;
 		char *c;
@@ -4000,6 +4052,12 @@
 		break;
 	case AST_CONTROL_SRCUPDATE:
 		ast_rtp_new_source(p->rtp);
+		break;
+	case AST_CONTROL_CONNECTED_LINE:
+		update_connectedline(p, data, datalen);
+		break;
+	case AST_CONTROL_REDIRECTING:
+		update_redirecting(p, data, datalen);
 		break;
 	case -1:
 		res = -1;
@@ -6074,9 +6132,6 @@
 		add_header(req, "User-Agent", global_useragent);
 	add_header(req, "Max-Forwards", DEFAULT_MAX_FORWARDS);
 
-	if (!ast_strlen_zero(p->rpid))
-		add_header(req, "Remote-Party-ID", p->rpid);
-
 	return 0;
 }
 
@@ -6262,6 +6317,73 @@
 	add_header(req, "Content-Type", "application/dtmf-relay");
 	add_header_contentLength(req, strlen(tmp));
 	add_line(req, tmp);
+	return 0;
+}
+
+/*! \brief Add Remote-Party-ID header to SIP message */
+static int add_rpid(struct sip_request *req, struct sip_pvt *p) {
+	char tmp[256];
+	char *lid_num = NULL;
+	char *lid_name = NULL;
+	int lid_pres;
+	const char *fromdomain;
+	const char *privacy = NULL;
+	const char *screen = NULL;
+
+	if (p->owner && p->owner->connected.id.number)
+		lid_num = p->owner->connected.id.number;
+	if (p->owner && p->owner->connected.id.name)
+		lid_name = p->owner->connected.id.name;
+	lid_pres = (p->owner) ? p->owner->connected.id.number_presentation : AST_PRES_NUMBER_NOT_AVAILABLE;
+
+	if (ast_strlen_zero(lid_num))
+		return 0;
+	if (ast_strlen_zero(lid_name))
+		lid_name = lid_num;
+	fromdomain = S_OR(p->fromdomain, ast_inet_ntoa(p->ourip));
+
+	snprintf(tmp, sizeof(tmp), "\"%s\" <sip:%s@%s>;party=%s", lid_name, lid_num, fromdomain, ast_test_flag(&p->flags[0], SIP_OUTGOING) ? "calling" : "called");
+
+	switch (lid_pres) {
+	case AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
+	case AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
+		privacy = "off";
+		screen = "no";
+		break;
+	case AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
+	case AST_PRES_ALLOWED_NETWORK_NUMBER:
+		privacy = "off";
+		screen = "yes";
+		break;
+	case AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
+	case AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
+		privacy = "full";
+		screen = "no";
+		break;
+	case AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
+	case AST_PRES_PROHIB_NETWORK_NUMBER:
+		privacy = "full";
+		screen = "yes";
+		break;
+	case AST_PRES_NUMBER_NOT_AVAILABLE:
+		break;
+	default:
+		if ((lid_pres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED)
+			privacy = "full";
+		else
+			privacy = "off";
+		screen = "no";
+		break;
+	}
+
+	if (!ast_strlen_zero(privacy) && !ast_strlen_zero(screen))
+		snprintf(tmp + strlen(tmp), sizeof(tmp) - strlen(tmp), ";privacy=%s;screen=%s", privacy, screen);
+
+	if (ast_test_flag(&p->flags[0], SIP_PAGE2_SENDRPID_RPID)) {
+		add_header(req, "Remote-Party-ID", tmp);
+	} else {
+		add_header(req, "P-Asserted-Identity", tmp);
+	}
 	return 0;
 }
 
@@ -6922,85 +7044,6 @@
 		ast_string_field_build(p, our_contact, "<sip:%s%s%s>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip));
 }
 
-/*! \brief Build the Remote Party-ID & From using callingpres options */
-static void build_rpid(struct sip_pvt *p)
-{
-	int send_pres_tags = TRUE;
-	const char *privacy=NULL;
-	const char *screen=NULL;
-	char buf[256];
-	const char *clid = default_callerid;
-	const char *clin = NULL;
-	const char *fromdomain;
-
-	if (!ast_strlen_zero(p->rpid) || !ast_strlen_zero(p->rpid_from))  
-		return;
-
-	if (p->owner && p->owner->cid.cid_num)
-		clid = p->owner->cid.cid_num;
-	if (p->owner && p->owner->cid.cid_name)
-		clin = p->owner->cid.cid_name;
-	if (ast_strlen_zero(clin))
-		clin = clid;
-
-	switch (p->callingpres) {
-	case AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
-		privacy = "off";
-		screen = "no";
-		break;
-	case AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
-		privacy = "off";
-		screen = "yes";
-		break;
-	case AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
-		privacy = "off";
-		screen = "no";
-		break;
-	case AST_PRES_ALLOWED_NETWORK_NUMBER:
-		privacy = "off";
-		screen = "yes";
-		break;
-	case AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
-		privacy = "full";
-		screen = "no";
-		break;
-	case AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
-		privacy = "full";
-		screen = "yes";
-		break;
-	case AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
-		privacy = "full";
-		screen = "no";
-		break;
-	case AST_PRES_PROHIB_NETWORK_NUMBER:
-		privacy = "full";
-		screen = "yes";
-		break;
-	case AST_PRES_NUMBER_NOT_AVAILABLE:
-		send_pres_tags = FALSE;
-		break;
-	default:
-		ast_log(LOG_WARNING, "Unsupported callingpres (%d)\n", p->callingpres);
-		if ((p->callingpres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED)
-			privacy = "full";
-		else
-			privacy = "off";
-		screen = "no";
-		break;
-	}
-	
-	fromdomain = S_OR(p->fromdomain, ast_inet_ntoa(p->ourip));
-
-	snprintf(buf, sizeof(buf), "\"%s\" <sip:%s@%s>", clin, clid, fromdomain);
-	if (send_pres_tags)
-		snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ";privacy=%s;screen=%s", privacy, screen);
-	ast_string_field_set(p, rpid, buf);
-
-	ast_string_field_build(p, rpid_from, "\"%s\" <sip:%s@%s>;tag=%s", clin,
-			       S_OR(p->fromuser, clid),
-			       fromdomain, p->tag);
-}
-
 /*! \brief Initiate new SIP request to peer/user */
 static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmethod)
 {
@@ -7036,15 +7079,9 @@
 
 	snprintf(p->lastmsg, sizeof(p->lastmsg), "Init: %s", sip_methods[sipmethod].text);
 
-	if (p->owner) {
-		l = p->owner->cid.cid_num;
-		n = p->owner->cid.cid_name;
-	}
-	/* if we are not sending RPID and user wants his callerid restricted */
-	if (!ast_test_flag(&p->flags[0], SIP_SENDRPID) &&
-	    ((p->callingpres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED)) {
-		l = CALLERID_UNKNOWN;
-		n = l;
+	if (p->owner && (p->owner->connected.id.number_presentation & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED) {
+		l = p->owner->connected.id.number; 
+		n = p->owner->connected.id.name; 
 	}
 	if (ast_strlen_zero(l))
 		l = default_callerid;
@@ -7117,11 +7154,7 @@
 	/* SLD: FIXME?: do Route: here too?  I think not cos this is the first request.
 	 * OTOH, then we won't have anything in p->route anyway */
 	/* Build Remote Party-ID and From */
-	if (ast_test_flag(&p->flags[0], SIP_SENDRPID) && (sipmethod == SIP_INVITE)) {
-		build_rpid(p);
-		add_header(req, "From", p->rpid_from);
-	} else 
-		add_header(req, "From", from);
+	add_header(req, "From", from);
 	add_header(req, "To", to);
 	ast_string_field_set(p, exten, l);
 	build_contact(p);
@@ -7131,8 +7164,45 @@
 	if (!ast_strlen_zero(global_useragent))
 		add_header(req, "User-Agent", global_useragent);
 	add_header(req, "Max-Forwards", DEFAULT_MAX_FORWARDS);
-	if (!ast_strlen_zero(p->rpid))
-		add_header(req, "Remote-Party-ID", p->rpid);
+}
+
+/*! \brief Add "Diversion" header to outgoing message
+ *
+ * We need to add a Diversion header if the owner channel of
+ * this dialog has redirecting information associated with it.
+ * XXX Add locking if necessary later.
+ *
+ * \param req The request/response to which we will add the header
+ * \param pvt The sip_pvt which represents the call-leg
+ * \param apr Redirecting data used to make the diversion header
+ */
+static void add_diversion_header(struct sip_request *req, struct sip_pvt *pvt)
+{
+	const char *diverting_number;
+	const char *diverting_name;
+	const char *reason;
+	char header_text[256];
+
+	if (!pvt->owner) {
+		return;
+	}
+
+	diverting_number = pvt->owner->cid.cid_rdnis;
+	diverting_name = pvt->owner->redirecting.from.name;
+	reason = sip_reason_code_to_str(pvt->owner->redirecting.reason);
+
+	if (ast_strlen_zero(diverting_number)) {
+		return;
+	}
+
+	/* We at least have a number to place in the Diversion header, which is enough */
+	if (ast_strlen_zero(diverting_name)) {
+		snprintf(header_text, sizeof(header_text), "<sip:%s@%s>;reason=\"%s\"", diverting_number, ast_inet_ntoa(pvt->ourip), reason);
+	} else {
+		snprintf(header_text, sizeof(header_text), "\"%s\" <sip:%s@%s>;reason=\"%s\"", diverting_name, diverting_number, ast_inet_ntoa(pvt->ourip), reason);
+	}
+
+	add_header(req, "Diversion", header_text);
 }
 
 /*! \brief Build REFER/INVITE/OPTIONS message and transmit it */
@@ -7215,6 +7285,11 @@
 		}
 
 		ast_channel_unlock(chan);
+	}
+	if ((sipmethod == SIP_INVITE || sipmethod == SIP_UPDATE) && ast_test_flag(&p->flags[0], SIP_PAGE2_SENDRPID))
+		add_rpid(&req, p);
+	if (sipmethod == SIP_INVITE) {
+		add_diversion_header(&req, p);
 	}
 	if (sdp) {
 		if (p->udptl && (p->t38.state == T38_LOCAL_DIRECT || p->t38.state == T38_LOCAL_REINVITE)) {
@@ -7492,6 +7567,72 @@
 	p->lastnoninvite = p->ocseq;
 
 	return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
+}
+
+/*! \brief Send a provisional response indicating that a call was redirected
+ */
+static void update_redirecting(struct sip_pvt *p, const void *data, size_t datalen)
+{
+	struct sip_request resp;
+
+	if (p->owner->_state == AST_STATE_UP || ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
+		return;
+	}
+
+	respprep(&resp, p, "181 Call is being forwarded", &p->initreq);
+	add_diversion_header(&resp, p);
+	send_response(p, &resp, XMIT_UNRELIABLE, 0);
+}
+
+/*! \brief Notify peer that the connected line has changed */
+static void update_connectedline(struct sip_pvt *p, const void *data, size_t datalen)
+{
+	
+	if (!ast_test_flag(&p->flags[0], SIP_PAGE2_SENDRPID))
+		return;
+	if (ast_strlen_zero(p->owner->connected.id.number))
+		return;
+
+	append_history(p, "ConnectedLine", "%s party is now %s <%s>", ast_test_flag(&p->flags[0], SIP_OUTGOING) ? "Calling" : "Called", p->owner->connected.id.name, p->owner->connected.id.number);
+
+	if (p->owner->_state == AST_STATE_UP || ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
+		struct sip_request req;
+
+		if (p->invitestate == INV_CONFIRMED || p->invitestate == INV_TERMINATED) {
+			reqprep(&req, p, ast_test_flag(&p->flags[0], SIP_REINVITE_UPDATE) ? SIP_UPDATE : SIP_INVITE, 0, 1);
+
+			add_header(&req, "Allow", ALLOWED_METHODS);
+			add_header(&req, "Supported", SUPPORTED_EXTENSIONS);
+			add_rpid(&req, p);
+			add_sdp(&req, p);
+
+			initialize_initreq(p, &req);
+			p->lastinvite = p->ocseq;
+			ast_set_flag(&p->flags[0], SIP_OUTGOING);
+			send_request(p, &req, XMIT_CRITICAL, p->ocseq);
+		} else {
+			reqprep(&req, p, SIP_UPDATE, 0, 1);
+			add_rpid(&req, p);
+			add_header_contentLength(&req, 0);
+			send_request(p, &req, XMIT_CRITICAL, p->ocseq);
+		}
+	} else {
+		struct sip_request resp;
+
+		if ((p->owner->_state == AST_STATE_RING) && !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT)) {
+			respprep(&resp, p, "180 Ringing", &p->initreq);
+			add_rpid(&resp, p);
+			send_response(p, &resp, XMIT_UNRELIABLE, 0);
+			ast_set_flag(&p->flags[0], SIP_RINGING);
+		} else if (p->owner->_state == AST_STATE_RINGING) {
+			respprep(&resp, p, "183 Session Progress", &p->initreq);
+			add_rpid(&resp, p);
+			send_response(p, &resp, XMIT_UNRELIABLE, 0);
+			ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
+		} else {
+			ast_log(LOG_DEBUG, "Unable able to send update to '%s' in state '%s'\n", p->owner->name, ast_state2str(p->owner->_state));
+		}
+	}
 }
 
 /*! \brief Convert registration state status to string */
@@ -8893,30 +9034,211 @@
 
 	return res;
 }
-
-/*! \brief Get referring dnis */
-static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq)
-{
-	char tmp[256], *c, *a;
+/*! \brief Get name, number and presentation from remote party id header, 
+ *  returns true if a valid header was found and it was different from the
+ *  current caller id.
+ */
+static int get_rpid(struct sip_pvt *p, struct sip_request *oreq)
+{
+	char tmp[256];
 	struct sip_request *req;
-	
+	char *cid_num = "";
+	char *cid_name = "";
+	int callingpres = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
+	char *privacy = "";
+	char *screen = "";
+	char *start, *end;
+
+	if (!ast_test_flag(&p->flags[0], SIP_TRUSTRPID))
+		return 0;
 	req = oreq;
 	if (!req)
 		req = &p->initreq;
+	ast_copy_string(tmp, get_header(req, "Remote-Party-ID"), sizeof(tmp));
+	if (ast_strlen_zero(tmp))
+		return 0;
+
+	start = tmp;
+	if (*start == '"') {
+		*start++ = '\0';
+		end = strchr(start, '"');
+		if (!end)
+			return 0;
+		*end++ = '\0';
+		cid_name = start;
+		start = ast_skip_blanks(end);
+	}
+
+	if (*start != '<')
+		return 0;
+	*start++ = '\0';
+	end = strchr(start, '@');
+	if (!end)
+		return 0;
+	*end++ = '\0';
+	if (strncasecmp(start, "sip:", 4))
+		return 0;
+	cid_num = start + 4;
+	if (ast_is_shrinkable_phonenumber(cid_num))
+		ast_shrink_phone_number(cid_num);
+	start = end;
+
+	end = strchr(start, '>');
+	if (!end)
+		return 0;
+	*end++ = '\0';
+	if (*end) {
+		start = end;
+		if (*start != ';')
+			return 0;
+		*start++ = '\0';
+		while (!ast_strlen_zero(start)) {
+			end = strchr(start, ';');
+			if (end)
+				*end++ = '\0';
+			if (!strncasecmp(start, "privacy=", 8))
+				privacy = start + 8;
+			else if (!strncasecmp(start, "screen=", 7))
+				screen = start + 7;
+			start = end;
+		}
+
+		if (!strcasecmp(privacy, "full")) {
+			if (!strcasecmp(screen, "yes"))
+				callingpres = AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN;
+			else if (!strcasecmp(screen, "no"))
+				callingpres = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
+		} else {
+			if (!strcasecmp(screen, "yes"))
+				callingpres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
+			else if (!strcasecmp(screen, "no"))
+				callingpres = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
+		}
+	}
+
+	/* Only return true if the supplied caller id is different */
+	if (!strcasecmp(p->cid_num, cid_num) && !strcasecmp(p->cid_name, cid_name) && p->callingpres == callingpres)
+		return 0;
+
+	ast_string_field_set(p, cid_num, cid_num);
+	ast_string_field_set(p, cid_name, cid_name);
+	p->callingpres = callingpres;
+
+	if (p->owner) {
+		ast_set_callerid(p->owner, cid_num, cid_name, NULL);
+		p->owner->cid.cid_pres = callingpres;
+	}
+
+	return 1;
+}
+
+/*! \brief Translate referring cause */
+static void sip_set_redirstr(struct sip_pvt *p, char *reason) {
+
+	if (!strcmp(reason, "unknown")) {
+		ast_string_field_set(p, redircause, "UNKNOWN");
+	} else if (!strcmp(reason, "user-busy")) {
+		ast_string_field_set(p, redircause, "BUSY");
+	} else if (!strcmp(reason, "no-answer")) {
+		ast_string_field_set(p, redircause, "NOANSWER");
+	} else if (!strcmp(reason, "unavailable")) {
+		ast_string_field_set(p, redircause, "UNREACHABLE");
+	} else if (!strcmp(reason, "unconditional")) {
+		ast_string_field_set(p, redircause, "UNCONDITIONAL");
+	} else if (!strcmp(reason, "time-of-day")) {
+		ast_string_field_set(p, redircause, "UNKNOWN");
+	} else if (!strcmp(reason, "do-not-disturb")) {
+		ast_string_field_set(p, redircause, "UNKNOWN");
+	} else if (!strcmp(reason, "deflection")) {
+		ast_string_field_set(p, redircause, "UNKNOWN");
+	} else if (!strcmp(reason, "follow-me")) {
+		ast_string_field_set(p, redircause, "UNKNOWN");
+	} else if (!strcmp(reason, "out-of-service")) {
+		ast_string_field_set(p, redircause, "UNREACHABLE");
+	} else if (!strcmp(reason, "away")) {
+		ast_string_field_set(p, redircause, "UNREACHABLE");
+	} else {
+		ast_string_field_set(p, redircause, "UNKNOWN");
+	}
+}
+
+/*! \brief Get referring dnis */
+static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq, char **name, char **number, int *reason)
+{
+	char tmp[256], *exten, *rexten, *rdomain, *rname = NULL;
+	char *params, *reason_param = NULL;
+	struct sip_request *req;
+	
+	req = oreq ? oreq : &p->initreq;
+
 	ast_copy_string(tmp, get_header(req, "Diversion"), sizeof(tmp));
 	if (ast_strlen_zero(tmp))
-		return 0;
-	c = get_in_brackets(tmp);
-	if (strncasecmp(c, "sip:", 4)) {
-		ast_log(LOG_WARNING, "Huh?  Not an RDNIS SIP header (%s)?\n", c);
 		return -1;
-	}
-	c += 4;
-	a = c;
-	strsep(&a, "@;");	/* trim anything after @ or ; */
+
+	if ((params = strchr(tmp, '>'))) {
+		params = strchr(params, ';');
+	}
+
+	exten = get_in_brackets(tmp);
+	if (!strncasecmp(exten, "sip:", 4)) {
+		exten += 4;
+	} else if (!strncasecmp(exten, "sips:", 5)) {
+		exten += 5;
+	} else {
+		ast_log(LOG_WARNING, "Huh?  Not an RDNIS SIP header (%s)?\n", exten);
+		return -1;
+	}
+
+	/* Get diversion-reason param if present */
+	if (params) {
+		*params = '\0';	/* Cut off parameters  */
+		params++;
+		while (*params == ';' || *params == ' ')
+			params++;
+		/* Check if we have a reason parameter */
+		if ((reason_param = strcasestr(params, "reason="))) {
+			reason_param+=7;
+			/* Remove enclosing double-quotes */
+			if (*reason_param == '"') 
+				ast_strip_quoted(reason_param, "\"", "\"");
+			if (!ast_strlen_zero(reason_param)) {
+				sip_set_redirstr(p, reason_param);
+				if (p->owner) {
+					pbx_builtin_setvar_helper(p->owner, "__PRIREDIRECTREASON", p->redircause);
+					pbx_builtin_setvar_helper(p->owner, "__SIPREDIRECTREASON", reason_param);
+				}
+			}
+		}
+	}
+
+	rdomain = exten;
+	rexten = strsep(&rdomain, "@");	/* trim anything after @ */
+	if (p->owner) 
+		pbx_builtin_setvar_helper(p->owner, "__SIPRDNISDOMAIN", rdomain);
+
 	if (sip_debug_test_pvt(p))
-		ast_verbose("RDNIS is %s\n", c);
-	ast_string_field_set(p, rdnis, c);
+		ast_verbose("RDNIS for this call is %s (reason %s)\n", exten, reason ? reason_param : "");
+
+	/*ast_string_field_set(p, rdnis, rexten);*/
+
+	if (*tmp == '\"') {
+		char *end_quote;
+		rname = tmp + 1;
+		end_quote = strchr(rname, '\"');
+		*end_quote = '\0';
+	}
+
+	if (number) {
+		*number = ast_strdup(rexten);
+	}
+
+	if (name && rname) {
+		*name = ast_strdup(rname);
+	}
+
+	if (reason && !ast_strlen_zero(reason_param)) {
+		*reason = sip_reason_str_to_code(reason_param);
+	}
 
 	return 0;
 }
@@ -9432,38 +9754,6 @@
 	return output;
 }
 
-/*! \brief  Get caller id number from Remote-Party-ID header field 
- *	Returns true if number should be restricted (privacy setting found)
- *	output is set to NULL if no number found
- */
-static int get_rpid_num(const char *input, char *output, int maxlen)
-{
-	char *start;
-	char *end;
-
-	start = strchr(input,':');
-	if (!start) {
-		output[0] = '\0';
-		return 0;
-	}
-	start++;
-
-	/* we found "number" */
-	ast_copy_string(output,start,maxlen);
-	output[maxlen-1] = '\0';
-
-	end = strchr(output,'@');
-	if (end)
-		*end = '\0';
-	else
-		output[0] = '\0';
-	if (strstr(input,"privacy=full") || strstr(input,"privacy=uri"))
-		return AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
-
-	return 0;
-}
-
-
 /*! \brief  Check if matching user or peer is defined 
  	Match user on From: user name and peer on IP/port
 	This is used on first invite (not re-invites) and subscribe requests 
@@ -9477,8 +9767,6 @@
 	struct sip_peer *peer;
 	char from[256], *c;
 	char *of;
-	char rpid_num[50];
-	const char *rpid;
 	enum check_auth_result res = AUTH_SUCCESSFUL;
 	char *t;
 	char calleridname[50];
@@ -9499,11 +9787,6 @@
 	get_calleridname(from, calleridname, sizeof(calleridname));
 	if (calleridname[0])
 		ast_string_field_set(p, cid_name, calleridname);
-
-	rpid = get_header(req, "Remote-Party-ID");
-	memset(rpid_num, 0, sizeof(rpid_num));
-	if (!ast_strlen_zero(rpid)) 
-		p->callingpres = get_rpid_num(rpid, rpid_num, sizeof(rpid_num));
 
 	of = get_in_brackets(from);
 	if (ast_strlen_zero(p->exten)) {
@@ -9721,14 +10004,19 @@
 					/* XXX this takes the name from the caller... can we override ? */
 					ast_string_field_set(p, authname, peer->username);
 				}
-				if (!ast_strlen_zero(peer->cid_num)) {
-					char *tmp = ast_strdupa(peer->cid_num);
-					if (ast_is_shrinkable_phonenumber(tmp))
-						ast_shrink_phone_number(tmp);
-					ast_string_field_set(p, cid_num, tmp);
+				if (!get_rpid(p, req)) {
+					if (!ast_strlen_zero(peer->cid_num)) {
+						char *tmp = ast_strdupa(peer->cid_num);
+						if (ast_is_shrinkable_phonenumber(tmp))
+							ast_shrink_phone_number(tmp);
+						ast_string_field_set(p, cid_num, tmp);
+					}
+					if (!ast_strlen_zero(peer->cid_name)) 
+						ast_string_field_set(p, cid_name, peer->cid_name);
+					if (peer->callingpres)
+						p->callingpres = peer->callingpres;
 				}
-				if (!ast_strlen_zero(peer->cid_name)) 
-					ast_string_field_set(p, cid_name, peer->cid_name);
+
 				ast_string_field_set(p, fullcontact, peer->fullcontact);
 				if (!ast_strlen_zero(peer->context))
 					ast_string_field_set(p, context, peer->context);
@@ -10574,7 +10862,7 @@
 		ast_cli(fd, "  User=Phone   : %s\n", ast_test_flag(&peer->flags[0], SIP_USEREQPHONE)?"Yes":"No");
 		ast_cli(fd, "  Video Support: %s\n", ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT)?"Yes":"No");
 		ast_cli(fd, "  Trust RPID   : %s\n", ast_test_flag(&peer->flags[0], SIP_TRUSTRPID) ? "Yes" : "No");
-		ast_cli(fd, "  Send RPID    : %s\n", ast_test_flag(&peer->flags[0], SIP_SENDRPID) ? "Yes" : "No");
+		ast_cli(fd, "  Send RPID    : %s\n", ast_test_flag(&peer->flags[0], SIP_PAGE2_SENDRPID) ? "Yes" : "No");
 		ast_cli(fd, "  Subscriptions: %s\n", ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE) ? "Yes" : "No");
 		ast_cli(fd, "  Overlap dial : %s\n", ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWOVERLAP) ? "Yes" : "No");
 
@@ -12104,53 +12392,216 @@
 	"- t38passthrough        1 if T38 is offered or enabled in this channel, otherwise 0\n"
 };
 
+/*XXX TODO Write this*/
+static int read_to_parts(struct sip_pvt *p, struct sip_request *req, char **name, char **number)
+{
+
+	char to_header[256];
+	char *to_name = NULL;
+	char *to_number = NULL;
+	char *separator;
+
+	ast_copy_string(to_header, get_header(req, "To"), sizeof(to_header));
+
+	/* Let's get that number first! */
+	to_number = get_in_brackets(to_header);
+
+	if (!strncasecmp(to_number, "sip:", 4)) {
+		to_number += 4;
+	} else if (!strncasecmp(to_number, "sips:", 5)) {
+		to_number += 5;
+	} else {
+		ast_log(LOG_WARNING, "Not a SIP URI? (%s)!\n", to_number);
+		return -1;
+	}
+
+	/* Remove the host and such since we just want the number */
+	if ((separator = strchr(to_number, '@'))) {
+		*separator = '\0';
+	}
+
+	/* We have the number. Let's get the name now. */
+
+	if (*to_header == '\"') {
+		to_name = to_header + 1;
+		if (!(separator = (char *)find_closing_quote(to_name, NULL))) {
+			ast_log(LOG_NOTICE, "No closing quote in name section of To: header (%s)\n", to_header);
+			return -1;
+		}
+		*separator = '\0';
+	}
+
+	if (number) {
+		*number = ast_strdup(to_number);
+	}
+	if (name && !ast_strlen_zero(to_name)) {
+		*name = ast_strdup(to_name);
+	}
+
+	return 0;
+}
+
+/*! \brief update redirecting information for a channel based on headers
+ *
+ */
+static void change_redirecting_information(struct sip_pvt *p, struct sip_request *req)
+{
+	char *redirecting_from_name = NULL;
+	char *redirecting_from_number = NULL;
+	char *redirecting_to_name = NULL;
+	char *redirecting_to_number = NULL;
+	int reason = AST_REDIRECTING_REASON_UNCONDITIONAL;
+	int is_response = req->method == SIP_RESPONSE;
+	int res = 0;
+
+	res = get_rdnis(p, req, &redirecting_from_name, &redirecting_from_number, &reason);
+	if (res == -1) {
+		if (is_response) {
+			read_to_parts(p, req, &redirecting_from_name, &redirecting_from_number);
+		} else {
+			return;
+		}
+	}
+
+	/* At this point, all redirecting "from" info should be filled in appropriately
+	 * on to the "to" info
+	 */
+
+	if (is_response) {
+		parse_moved_contact(p, req, &redirecting_to_name, &redirecting_to_number);
+	} else {
+		read_to_parts(p, req, &redirecting_to_name, &redirecting_to_number);
+	}
+
+	/* This check could probably moved up higher so we don't do any unnecessary
+	 * parsing
+	 */
+	if (!p->owner) {
+		return;
+	}
+
+	if (!ast_strlen_zero(redirecting_from_number)) {
+		if (p->owner->redirecting.from.number) {
+			ast_free(p->owner->redirecting.from.number);
+		}
+		if (option_debug > 2) {
+			ast_log(LOG_DEBUG, "Got redirecting from number %s\n", redirecting_from_number);
+		}
+		p->owner->redirecting.from.number = redirecting_from_number;
+	}
+	if (!ast_strlen_zero(redirecting_from_name)) {
+		if (p->owner->redirecting.from.name) {
+			ast_free(p->owner->redirecting.from.name);
+		}
+		if (option_debug > 2) {
+			ast_log(LOG_DEBUG, "Got redirecting from name %s\n", redirecting_from_name);
+		}
+		p->owner->redirecting.from.name = redirecting_from_name;
+	}
+	if (!ast_strlen_zero(redirecting_to_number)) {
+		if (p->owner->redirecting.to.number) {
+			ast_free(p->owner->redirecting.to.number);
+		}
+		if (option_debug > 2) {
+			ast_log(LOG_DEBUG, "Got redirecting to number %s\n", redirecting_to_number);
+		}
+		p->owner->redirecting.to.number = redirecting_to_number;
+	}
+	if (!ast_strlen_zero(redirecting_to_name)) {
+		if (p->owner->redirecting.to.name) {
+			ast_free(p->owner->redirecting.to.name);
+		}
+		if (option_debug > 2) {
+			ast_log(LOG_DEBUG, "Got redirecting to name %s\n", redirecting_from_number);
+		}
+		p->owner->redirecting.to.name = redirecting_to_name;
+	}
+	p->owner->redirecting.reason = reason;
+}
+
 /*! \brief Parse 302 Moved temporalily response */
-static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req)
-{
-	char tmp[SIPBUFSIZE];
-	char *s, *e, *uri, *t;
+static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req, char **name, char **number)
+{
+	char contact[SIPBUFSIZE];
+	char *contact_name = NULL;
+	char *contact_number = NULL;
+	char *separator;
 	char *domain;
 
-	ast_copy_string(tmp, get_header(req, "Contact"), sizeof(tmp));
-	if ((t = strchr(tmp, ',')))
-		*t = '\0';
-	s = get_in_brackets(tmp);
-	uri = ast_strdupa(s);
+	ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact));
+	if ((separator = strchr(contact, ',')))
+		*separator = '\0';
+
+	/* ooh, a name */
+	if (*contact == '"') {
+		contact_name = contact + 1;
+		if ((separator = strchr(contact_name, '"'))) {
+			*separator++ = '\0';
+		}
+	}
+
+	contact_number = get_in_brackets(contact);
+	if ((separator = strchr(contact_number, ';'))) {
+		*separator++ = '\0';
+	}
+
 	if (ast_test_flag(&p->flags[0], SIP_PROMISCREDIR)) {
-		if (!strncasecmp(s, "sip:", 4))
-			s += 4;
-		e = strchr(s, ';');
-		if (e)
-			*e = '\0';
-		if (option_debug)
-			ast_log(LOG_DEBUG, "Found promiscuous redirection to 'SIP/%s'\n", s);
+		if (!strncasecmp(contact_number, "sip:", 4))
+			contact_number += 4;
+		else if (!strncasecmp(contact_number, "sips:", 5))
+			contact_number += 5;
+		separator = strchr(contact_number, '/');
+		if (separator)
+			*separator = '\0';
+		if (option_debug > 1) {
+			ast_log(LOG_DEBUG, "Found promiscuous redirection to 'SIP/%s'\n", contact_number);
+		}
 		if (p->owner)
-			ast_string_field_build(p->owner, call_forward, "SIP/%s", s);
+			ast_string_field_build(p->owner, call_forward, "SIP/%s", contact_number);
 	} else {
-		e = strchr(tmp, '@');
-		if (e) {
-			*e++ = '\0';
-			domain = e;
+		separator = strchr(contact, '@');
+		if (separator) {
+			*separator++ = '\0';
+			domain = separator;
 		} else {
 			/* No username part */
-			domain = tmp;
-		}
-		e = strchr(s, ';');	/* Strip of parameters in the username part */
-		if (e)
-			*e = '\0';
-		e = strchr(domain, ';');	/* Strip of parameters in the domain part */
-		if (e)
-			*e = '\0';
-	
-		if (!strncasecmp(s, "sip:", 4))
-			s += 4;
-		if (option_debug > 1)
-			ast_log(LOG_DEBUG, "Received 302 Redirect to extension '%s' (domain %s)\n", s, domain);
+			domain = contact;
+		}
+		separator = strchr(contact, '/');	/* WHEN do we hae a forward slash in the URI? */
+		if (separator)
+			*separator = '\0';
+
+		if (!strncasecmp(contact_number, "sip:", 4))
+			contact_number += 4;
+		else if (!strncasecmp(contact_number, "sips:", 5))
+			contact_number += 5;
+		separator = strchr(contact_number, ';');	/* And username ; parameters? */
+		if (separator)
+			*separator = '\0';	
+		if (option_debug < 3) {
+			ast_log(LOG_DEBUG, "Received 302 Redirect to extension '%s' (domain %s)\n", contact_number, domain);
+		}
 		if (p->owner) {
-			pbx_builtin_setvar_helper(p->owner, "SIPREDIRECTURI", uri);
 			pbx_builtin_setvar_helper(p->owner, "SIPDOMAIN", domain);
-			ast_string_field_set(p->owner, call_forward, s);
-		}
+			ast_string_field_set(p->owner, call_forward, contact_number);
+		}
+	}
+
+	/* We've gotten the number for the contact, now get the name */
+
+	if (*contact == '\"') {
+		contact_name = contact + 1;
+		if (!(separator = (char *)find_closing_quote(contact_name, NULL))) {
+			ast_log(LOG_NOTICE, "No closing quote on name in Contact header? %s\n", contact);
+		}
+		*separator = '\0';
+	}
+
+	if (name && !ast_strlen_zero(contact_name)) {
+		*name = ast_strdup(contact_name);
+	}
+	if (number) {
+		*number = ast_strdup(contact_number);
 	}
 }
 
@@ -12211,6 +12662,7 @@
 	int xmitres = 0;
 	int reinvite = (p->owner && p->owner->_state == AST_STATE_UP);
 	struct ast_channel *bridgepeer = NULL;
+	struct ast_party_connected_line connected;
 	
 	if (option_debug > 3) {
 		if (reinvite)
@@ -12278,6 +12730,17 @@
 		if (!ast_test_flag(req, SIP_PKT_IGNORE) && (p->invitestate != INV_CANCELLED) && sip_cancel_destroy(p))
 			ast_log(LOG_WARNING, "Unable to cancel SIP destruction.  Expect bad things.\n");
 		/* Ignore 183 Session progress without SDP */
+		if (!ast_test_flag(req, SIP_PKT_IGNORE) && p->owner) {
+			if (get_rpid(p, req)) {
+				/* Queue a connected line update */
+				ast_party_connected_line_init(&connected);
+				connected.id.number = (char *) p->cid_num;
+				connected.id.name = (char *) p->cid_name;
+				connected.id.number_presentation = p->callingpres;
+				connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
+				ast_queue_connected_line_update(p->owner, &connected);
+			}
+		}
 		if (find_sdp(req)) {
 			if (p->invitestate != INV_CANCELLED)
 				p->invitestate = INV_EARLY_MEDIA;
@@ -12372,6 +12835,9 @@
 
 		if (!ast_test_flag(req, SIP_PKT_IGNORE) && p->owner) {
 			if (!reinvite) {
+				struct ast_party_connected_line connected;
+				ast_party_connected_line_collect_caller(&connected, &p->owner->cid);
+				ast_queue_connected_line_update(p->owner, &connected);
 				ast_queue_control(p->owner, AST_CONTROL_ANSWER);
 			} else {	/* RE-invite */
 				ast_queue_frame(p->owner, &ast_null_frame);
@@ -13028,7 +13494,7 @@
 				case 301: /* Moved permenantly */
 				case 302: /* Moved temporarily */
 				case 305: /* Use Proxy */
-					parse_moved_contact(p, req);
+					change_redirecting_information(p, req);
 					/* Fall through */
 				case 486: /* Busy here */
 				case 600: /* Busy everywhere */
@@ -14082,10 +14548,11 @@
 }
 
 
-/*! \brief Handle incoming INVITE request
-\note 	If the INVITE has a Replaces header, it is part of an
+/*!
+ * \brief Handle incoming INVITE request
+ * \note If the INVITE has a Replaces header, it is part of an
  *	attended transfer. If so, we do not go through the dial
- *	plan but tries to find the active call and masquerade
+ *	plan but try to find the active call and masquerade
  *	into it 
  */
 static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int debug, int seqno, struct sockaddr_in *sin, int *recount, char *e, int *nounlock)
@@ -14305,6 +14772,16 @@
 			parse_ok_contact(p, req);
 		} else {	/* Re-invite on existing call */
 			ast_clear_flag(&p->flags[0], SIP_OUTGOING);	/* This is now an inbound dialog */
+			if (get_rpid(p, req)) {
+				struct ast_party_connected_line connected;
+
+				ast_party_connected_line_init(&connected);
+				connected.id.number = (char *) p->cid_num;
+				connected.id.name = (char *) p->cid_name;
+				connected.id.number_presentation = p->callingpres;

[... 91 lines stripped ...]



More information about the svn-commits mailing list