Hi all,

BRIstuff 0.4.0-RC3b (and possibly in earlier versions, too), all the code 
necessary to update the callerid on snom phones after an attended transfer  
(using "message/sipfrag"; as available in BRIstuff 0.3.0-PRE-1y-p, improved 
in 0.3.0-PRE-1y-r) is there, but it's commented out, unfortunately.

The attached patch (121-sip_changes.diff.patch) removes the comments from the 
few relevant lines in file patches/asterisk/121-sip_changes.diff , 
121-sip_changes.diff is the patched version from BRIstuff 0.4.0-RC3b.
Additionally, I've changed the two lines so that both, caller id name and 
number are shown. This change might also be interresting for BRIstuff 0.3 / 
Asterisk 1.2.

The patch is somewhat tested with snom 320s firmware version 7.1.33. I'll see 
that I can also test the BRIstuff 0.3 / Asterisk 1.2 version of it with snom 
320s and 360s during the next days/weeks.
Any chance of getting this change into BRIstuff 0.4? (Who do I have to contact 
to request this?)

Best regards,
Philipp

-- 
Philipp Walker
Binatec AG
Ingenieurbüro für Nachrichten- und Informationstechnik
Q4 Altdorf Ost
Hellgasse 23 / Postfach
6460 Altdorf

[EMAIL PROTECTED]
www.binatec.ch
--- 121-sip_changes.diff.orig	2008-07-07 14:57:43.000000000 +0200
+++ 121-sip_changes.diff	2008-07-07 15:46:57.000000000 +0200
@@ -378,15 +378,15 @@
  static int attempt_transfer(struct sip_dual *transferer, struct sip_dual *target)
  {
  	int res = 0;
-+//	struct sip_request req;
-+//	struct sip_pvt *p = NULL;
++	struct sip_request req;
++	struct sip_pvt *p = NULL;
  	struct ast_channel *peera = NULL,	
  		*peerb = NULL,
  		*peerc = NULL,
  		*peerd = NULL;
 +	char tmp[500];
-+//	char *t = tmp;
-+//	size_t maxbytes = sizeof(tmp);
++	char *t = tmp;
++	size_t maxbytes = sizeof(tmp);
  
  
  	/* We will try to connect the transferee with the target and hangup
@@ -395,18 +395,18 @@
  		} else
  			ast_log(LOG_DEBUG, "SIP transfer: Succeeded to masquerade channels.\n");
 +
-+/*		if (peerd && !strcasecmp(peerd->tech->type, "SIP")) {
++		if (peerd && !strcasecmp(peerd->tech->type, "SIP")) {
 +		    p = peerd->tech_pvt;
 +		    if (p && ast_test_flag(&(p->flags[1]), SIP_PAGE2_CID_UPDATE_INFO)) {
 +		        reqprep(&req, p, SIP_INFO, 0, 1);
 +			add_header(&req, "Content-Type", "message/sipfrag");
-+		        ast_build_string(&t, &maxbytes, "From: \"%s\"\r\n", peerd->cid.cid_num);
-+		        ast_build_string(&t, &maxbytes, "To: \"%s\"\r\n", peerc->cid.cid_num);
++		        ast_build_string(&t, &maxbytes, "From: \"%s\" <%s>\r\n", peerd->cid.cid_name, peerd->cid.cid_num);
++		        ast_build_string(&t, &maxbytes, "To: \"%s\" <%s>\r\n", peerc->cid.cid_name, peerc->cid.cid_num);
 +		        add_header_contentLength(&req, strlen(tmp));
 +		        add_line(&req, tmp);
 +		        send_request(p, &req, 0, p->ocseq);
 +		    }
-+		} */
++		}
 +
  		return res;
  	} else {
Index: asterisk-1.4.21/configs/sip.conf.sample
===================================================================
--- asterisk-1.4.21.orig/configs/sip.conf.sample
+++ asterisk-1.4.21/configs/sip.conf.sample
@@ -430,6 +430,18 @@ srvlookup=yes			; Enable DNS SRV lookups
 ; jblog = no                  ; Enables jitterbuffer frame logging. Defaults to "no".
 ;-----------------------------------------------------------------------------------
 
+
+;nationalprefix=0
+;internationalprefix=00
+;countrycode=49
+;areacode=30
+;dialplan=international			; convert 123456 to 004930123456
+;dialplan=national			; convert 123456 to 030123456
+;dialplan=local				; do not change the dialed number, default behaviour.
+;prefix=666
+;rtpip=192.168.1.1			; if RTP should go to asterisk you can configure the
+;					; used IP address here (for multihomed machines)
+
 [authentication]
 ; Global credentials for outbound calls, i.e. when a proxy challenges your
 ; Asterisk server for authentication. These credentials override
Index: asterisk-1.4.21/channels/chan_sip.c
===================================================================
--- asterisk-1.4.21.orig/channels/chan_sip.c
+++ asterisk-1.4.21/channels/chan_sip.c
@@ -198,6 +198,10 @@ static int expiry = DEFAULT_EXPIRY;
 #endif
 
 #define CALLERID_UNKNOWN        "Unknown"
+#define CALLERID_ANONYMOUS	"Anonymous"
+
+#define SIP_DIALPLAN_LOCAL 0
+#define SIP_DIALPLAN_INTERNATIONAL 1
 
 #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 */
@@ -797,9 +801,14 @@ struct sip_auth {
 #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_CID_UPDATE		(3 << 30)
+#define SIP_PAGE2_CID_UPDATE_NEVER	(0 << 30)
+#define SIP_PAGE2_CID_UPDATE_INFO	(1 << 30)
+#define SIP_PAGE2_CID_UPDATE_REINVITE	(2 << 30)
+
 #define SIP_PAGE2_FLAGS_TO_COPY \
 	(SIP_PAGE2_ALLOWSUBSCRIBE | SIP_PAGE2_ALLOWOVERLAP | SIP_PAGE2_VIDEOSUPPORT | \
-	SIP_PAGE2_T38SUPPORT | SIP_PAGE2_RFC2833_COMPENSATE | SIP_PAGE2_BUGGY_MWI | SIP_PAGE2_UDPTL_DESTINATION)
+	SIP_PAGE2_T38SUPPORT | SIP_PAGE2_RFC2833_COMPENSATE | SIP_PAGE2_BUGGY_MWI | SIP_PAGE2_UDPTL_DESTINATION | SIP_PAGE2_CID_UPDATE)
 
 /* SIP packet flags */
 #define SIP_PKT_DEBUG		(1 << 0)	/*!< Debug this packet */
@@ -946,6 +955,9 @@ static struct sip_pvt {
 		AST_STRING_FIELD(our_contact);	/*!< Our contact header */
 		AST_STRING_FIELD(rpid);		/*!< Our RPID header */
 		AST_STRING_FIELD(rpid_from);	/*!< Our RPID From header */
+		AST_STRING_FIELD(assertedid);			/*!< P-Asserted-ID */
+		AST_STRING_FIELD(preferredid);			/*!< P-Preferred-ID */
+		AST_STRING_FIELD(privacy);
 	);
 	unsigned int ocseq;			/*!< Current outgoing seqno */
 	unsigned int icseq;			/*!< Current incoming seqno */
@@ -983,6 +995,7 @@ static struct sip_pvt {
 	int rtptimeout;				/*!< RTP timeout time */
 	struct sockaddr_in recv;		/*!< Received as */
 	struct in_addr ourip;			/*!< Our IP */
+	struct in_addr rtpip;			/*!< Our RTP IP */
 	struct ast_channel *owner;		/*!< Who owns us (if we have an owner) */
 	struct sip_route *route;		/*!< Head of linked list of routing steps (fm Record-Route) */
 	int route_persistant;			/*!< Is this the "real" route? */
@@ -1094,6 +1107,9 @@ struct sip_peer {
 	char fullcontact[256];		/*!< Contact registered with us (not in sip.conf) */
 	char cid_num[80];		/*!< Caller ID num */
 	char cid_name[80];		/*!< Caller ID name */
+	char assertedid[256];
+	char preferredid[256];
+	char privacy[80];
 	int callingpres;		/*!< Calling id presentation */
 	int inUse;			/*!< Number of calls in use */
 	int inRinging;			/*!< Number of calls ringing */
@@ -1119,6 +1135,15 @@ struct sip_peer {
 	ast_group_t callgroup;		/*!<  Call group */
 	ast_group_t pickupgroup;	/*!<  Pickup group */
 	struct sockaddr_in addr;	/*!<  IP address of peer */
+	/* Dialplan */
+	char countrycode[10];
+	char prefix[10];
+	char nationalprefix[10];
+	char internationalprefix[10];
+	int dialplan;
+
+	/* RTP IP address */
+	struct in_addr rtpip;
 	int maxcallbitrate;		/*!< Maximum Bitrate for a video call */
 	
 	/* Qualification */
@@ -1221,6 +1246,7 @@ static struct ast_config *notify_types;	
 static struct ast_channel *sip_request_call(const char *type, int format, void *data, int *cause);
 static int sip_devicestate(void *data);
 static int sip_sendtext(struct ast_channel *ast, const char *text);
+static int sip_sendmessage(struct ast_channel *ast, const char *dest, const char *text, int ispdu);
 static int sip_call(struct ast_channel *ast, char *dest, int timeout);
 static int sip_hangup(struct ast_channel *ast);
 static int sip_answer(struct ast_channel *ast);
@@ -1343,7 +1369,7 @@ static void ast_quiet_chan(struct ast_ch
 static int attempt_transfer(struct sip_dual *transferer, struct sip_dual *target);
 
 /*--- Device monitoring and Device/extension state handling */
-static int cb_extensionstate(char *context, char* exten, int state, void *data);
+static int cb_extensionstate(char *context, char* exten, int state, void *data, char *cid_num, char* cid_name);
 static int sip_devicestate(void *data);
 static int sip_poke_noanswer(const void *data);
 static int sip_poke_peer(struct sip_peer *peer);
@@ -1482,7 +1508,7 @@ static int get_rdnis(struct sip_pvt *p, 
 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 int transmit_state_notify(struct sip_pvt *p, int state, int full, int timeout, char *cid_num, char *cid_name);
 
 /*--- Constructing requests and responses */
 static void initialize_initreq(struct sip_pvt *p, struct sip_request *req);
@@ -1570,6 +1596,7 @@ static const struct ast_channel_tech sip
 	.send_digit_end = sip_senddigit_end,
 	.bridge = ast_rtp_bridge,
 	.send_text = sip_sendtext,
+	.send_message = sip_sendmessage,
 	.func_channel_read = acf_channel_read,
 };
 
@@ -2069,7 +2096,7 @@ static int __sip_autodestruct(const void
 
 	/* If this is a subscription, tell the phone that we got a timeout */
 	if (p->subscribed) {
-		transmit_state_notify(p, AST_EXTENSION_DEACTIVATED, 1, TRUE);	/* Send last notification */
+		transmit_state_notify(p, AST_EXTENSION_DEACTIVATED, 1, TRUE, NULL, NULL);	/* Send last notification */
 		p->subscribed = NONE;
 		append_history(p, "Subscribestatus", "timeout");
 		if (option_debug > 2)
@@ -3304,7 +3331,9 @@ static int update_call_counter(struct si
 		ast_log(LOG_ERROR, "update_call_counter(%s, %d) called with no event!\n", name, event);
 	}
 	if (p) {
-		ast_device_state_changed("SIP/%s", p->name);
+		/* Do not trigger a fale AST_STATE_RINGING state change or we will not get the caller ID for the extension state! */
+		if (event != INC_CALL_RINGING)
+		    ast_device_state_changed("SIP/%s", p->name);
 		ASTOBJ_UNREF(p, sip_destroy_peer);
 	} else /* u must be set */
 		ASTOBJ_UNREF(u, sip_destroy_user);
@@ -3444,6 +3473,8 @@ static const char *hangup_cause2sip(int 
 		case AST_CAUSE_CONGESTION:		/* 34 */
 		case AST_CAUSE_SWITCH_CONGESTION:	/* 42 */
 			return "503 Service Unavailable";
+		case AST_CAUSE_NORMAL_CLEARING:		/* 16 */
+			return "480 Temporarily unavailable";
 		case AST_CAUSE_NO_USER_RESPONSE:	/* 18 */
 			return "408 Request Timeout";
 		case AST_CAUSE_NO_ANSWER:		/* 19 */
@@ -3685,9 +3716,13 @@ static int sip_answer(struct ast_channel
 			p->t38.state = T38_ENABLED;
 			if (option_debug > 1)
 				ast_log(LOG_DEBUG,"T38State change to %d on channel %s\n", p->t38.state, ast->name);
+		    if (!ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
 			res = transmit_response_with_t38_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL);
+		    }
 		} else {
+		    if (!ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
 			res = transmit_response_with_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL);
+		    }
 		}
 	}
 	ast_mutex_unlock(&p->lock);
@@ -6502,6 +6537,9 @@ static enum sip_result add_sdp(struct si
 	if (p->redirip.sin_addr.s_addr) {
 		dest.sin_port = p->redirip.sin_port;
 		dest.sin_addr = p->redirip.sin_addr;
+	} else if (p->rtpip.s_addr) {
+		dest.sin_addr = p->rtpip;
+		dest.sin_port = sin.sin_port;
 	} else {
 		dest.sin_addr = p->ourip;
 		dest.sin_port = sin.sin_port;
@@ -6994,7 +7032,7 @@ static void initreqprep(struct sip_reque
 	/* 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;
+		l = CALLERID_ANONYMOUS;
 		n = l;
 	}
 	if (ast_strlen_zero(l))
@@ -7086,6 +7124,45 @@ static void initreqprep(struct sip_reque
 		add_header(req, "Remote-Party-ID", p->rpid);
 }
 
+static int transmit_sip_request(struct sip_pvt *p,struct sip_request *req);
+
+/*! \brief  sip_sendmessage: Send SIP MESSAGE text within a call ---*/
+/*      Called from PBX core text message functions */
+static int sip_sendmessage(struct ast_channel *ast, const char *dest, const char *text, int ispdu)
+{
+	struct sip_request req;
+	struct sip_pvt *p = ast->tech_pvt;
+	int debug=sip_debug_test_pvt(p);
+
+	if (debug)
+		ast_verbose("Sending text %s on %s\n", text, ast->name);
+	if (!p)
+		return -1;
+	if (ast_strlen_zero(text))
+		return 0;
+	if (ispdu) {
+		ast_log(LOG_WARNING, "Don't know how to send PDU on channel of type SIP\n");
+		return -1;
+	}
+
+	if (debug)
+		ast_verbose("Really sending text %s on %s\n", text, ast->name);
+
+	if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
+	    transmit_message_with_text(p, text);
+	} else {
+	    initreqprep(&req, p, SIP_MESSAGE);
+	    if (ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip))
+		memcpy(&p->ourip, &__ourip, sizeof(p->ourip));
+	    build_via(p);
+	    build_callid_pvt(p);
+	    add_text(&req, text);
+	    transmit_sip_request(p, &req);
+	    sip_scheddestroy(p, 15000);
+	}
+	return 0;
+}
+
 /*! \brief Build REFER/INVITE/OPTIONS message and transmit it */
 static int transmit_invite(struct sip_pvt *p, int sipmethod, int sdp, int init)
 {
@@ -7166,6 +7243,15 @@ static int transmit_invite(struct sip_pv
 
 		ast_channel_unlock(chan);
 	}
+	if (!ast_strlen_zero(p->assertedid)) {
+	    add_header(&req, "P-Asserted-Identity", p->assertedid);
+	}
+	if (!ast_strlen_zero(p->preferredid)) {
+	    add_header(&req, "P-Preferred-Identity", p->preferredid);
+	}
+	if (!ast_strlen_zero(p->privacy)) {
+	    add_header(&req, "Privacy", p->privacy);
+	}
 	if (sdp) {
 		if (p->udptl && (p->t38.state == T38_LOCAL_DIRECT || p->t38.state == T38_LOCAL_REINVITE)) {
 			ast_udptl_offered_from_local(p->udptl, 1);
@@ -7185,7 +7271,7 @@ static int transmit_invite(struct sip_pv
 }
 
 /*! \brief Used in the SUBSCRIBE notification subsystem */
-static int transmit_state_notify(struct sip_pvt *p, int state, int full, int timeout)
+static int transmit_state_notify(struct sip_pvt *p, int state, int full, int timeout, char *cid_num, char *cid_name)
 {
 	char tmp[4000], from[256], to[256];
 	char *t = tmp, *c, *mfrom, *mto;
@@ -7340,10 +7426,19 @@ static int transmit_state_notify(struct 
 	case DIALOG_INFO_XML: /* SNOM subscribes in this format */
 		ast_build_string(&t, &maxbytes, "<?xml version=\"1.0\"?>\n");
 		ast_build_string(&t, &maxbytes, "<dialog-info xmlns=\"urn:ietf:params:xml:ns:dialog-info\" version=\"%d\" state=\"%s\" entity=\"%s\">\n", p->dialogver++, full ? "full":"partial", mto);
-		if ((state & AST_EXTENSION_RINGING) && global_notifyringing)
-			ast_build_string(&t, &maxbytes, "<dialog id=\"%s\" direction=\"recipient\">\n", p->exten);
-		else
+		if ((state & AST_EXTENSION_RINGING) && global_notifyringing) {
+		    ast_build_string(&t, &maxbytes, "<dialog id=\"%s\" direction=\"recipient\">\n", p->exten);
+		    ast_build_string(&t, &maxbytes, "<local><identity display=\"%s\">%s</identity><target uri=\"%s\"/></local>\n", p->exten, p->exten, mfrom);
+		    if (!ast_strlen_zero(cid_num)) {
+			if (cid_name && !ast_strlen_zero(cid_name)) {
+                           ast_build_string(&t, &maxbytes, "<remote><identity display=\"%s\">sip:[EMAIL PROTECTED]</identity><target uri=\"sip:[EMAIL PROTECTED]"/></remote>\n", cid_name, cid_num, p->fromdomain, ast_pickup_ext(), p->exten, p->fromdomain);
+			} else {
+                           ast_build_string(&t, &maxbytes, "<remote><identity display=\"%s\">sip:[EMAIL PROTECTED]</identity><target uri=\"sip:[EMAIL PROTECTED]"/></remote>\n", cid_num, cid_num, p->fromdomain, ast_pickup_ext(), p->exten, p->fromdomain);
+			}
+		    }
+		} else {
 			ast_build_string(&t, &maxbytes, "<dialog id=\"%s\">\n", p->exten);
+		}
 		ast_build_string(&t, &maxbytes, "<state>%s</state>\n", statestring);
 		if (state == AST_EXTENSION_ONHOLD) {
 			ast_build_string(&t, &maxbytes, "<local>\n<target uri=\"%s\">\n"
@@ -8599,12 +8694,11 @@ static void sip_peer_hold(struct sip_pvt
 /*! \brief Callback for the devicestate notification (SUBSCRIBE) support subsystem
 \note	If you add an "hint" priority to the extension in the dial plan,
 	you will get notifications on device state changes */
-static int cb_extensionstate(char *context, char* exten, int state, void *data)
+static int cb_extensionstate(char *context, char* exten, int state, void *data, char *cid_num, char *cid_name)
 {
 	struct sip_pvt *p = data;
 
 	ast_mutex_lock(&p->lock);
-
 	switch(state) {
 	case AST_EXTENSION_DEACTIVATED:	/* Retry after a while */
 	case AST_EXTENSION_REMOVED:	/* Extension is gone */
@@ -8622,7 +8716,7 @@ static int cb_extensionstate(char *conte
 	}
 	if (p->subscribed != NONE) {	/* Only send state NOTIFY if we know the format */
 		if (!p->pendinginvite) {
-			transmit_state_notify(p, state, 1, FALSE);
+			transmit_state_notify(p, state, 1, FALSE, cid_num, cid_name);
 		} else {
 			/* We already have a NOTIFY sent that is not answered. Queue the state up.
 			   if many state changes happen meanwhile, we will only send a notification of the last one */
@@ -10473,6 +10567,9 @@ static int _sip_show_peer(int type, int 
 		ast_cli(fd, "  Call limit   : %d\n", peer->call_limit);
 		ast_cli(fd, "  Dynamic      : %s\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_DYNAMIC)?"Yes":"No"));
 		ast_cli(fd, "  Callerid     : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>"));
+		ast_cli(fd, "  Assertedid   : %s\n", peer->assertedid);
+		ast_cli(fd, "  Preferredid   : %s\n", peer->preferredid);
+		ast_cli(fd, "  Privacy      : %s\n", peer->privacy);
 		ast_cli(fd, "  MaxCallBR    : %d kbps\n", peer->maxcallbitrate);
 		ast_cli(fd, "  Expire       : %ld\n", ast_sched_when(sched, peer->expire));
 		ast_cli(fd, "  Insecure     : %s\n", insecure2str(ast_test_flag(&peer->flags[0], SIP_INSECURE_PORT), ast_test_flag(&peer->flags[0], SIP_INSECURE_INVITE)));
@@ -11187,6 +11284,7 @@ static void handle_request_info(struct s
 	char buf[1024];
 	unsigned int event;
 	const char *c = get_header(req, "Content-Type");
+//	struct ast_call_feature *feature;
 
 	/* Need to check the media/type */
 	if (!strcasecmp(c, "application/dtmf-relay") ||
@@ -11269,6 +11367,19 @@ static void handle_request_info(struct s
 			transmit_response(p, "403 Unauthorized", req);
 		}
 		return;
+/*	} else if (!ast_strlen_zero((c = get_header(req, "Record")))) {
+		feature = ast_find_builtin_feature("automon");
+		if (feature && (!ast_strlen_zero(feature->exten))) {
+		    int i = 0;
+		    for (i=0; i<strlen(feature->exten); i++) {
+			struct ast_frame f = { AST_FRAME_DTMF, feature->exten[i] };
+			ast_queue_frame(p->owner, &f);
+		    }
+		} else {
+		    ast_log(LOG_NOTICE, "Feature \"One Touch Monitor\" not configured in features.conf.\n");
+		}
+		return;
+*/
 	} else if (ast_strlen_zero(c = get_header(req, "Content-Length")) || !strcasecmp(c, "0")) {
 		/* This is probably just a packet making sure the signalling is still up, just send back a 200 OK */
 		transmit_response(p, "200 OK", req);
@@ -12171,7 +12282,7 @@ static void handle_response_invite(struc
 		if (!ast_test_flag(req, SIP_PKT_IGNORE) && p->owner) {
 			ast_queue_control(p->owner, AST_CONTROL_RINGING);
 			if (p->owner->_state != AST_STATE_UP) {
-				ast_setstate(p->owner, AST_STATE_RINGING);
+				ast_setstate_and_callerid(p->owner, AST_STATE_RINGING, p->owner->cid.cid_num, p->owner->cid.cid_name);
 			}
 		}
 		if (find_sdp(req)) {
@@ -12787,7 +12898,7 @@ static void handle_response(struct sip_p
 					if (ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE)) {
 						/* Ready to send the next state we have on queue */
 						ast_clear_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE);
-						cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p);
+						cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p, NULL, NULL);
 					}
 				}
 			} else if (sipmethod == SIP_REGISTER) 
@@ -13040,7 +13151,7 @@ static void handle_response(struct sip_p
 					if (ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE)) {
 						/* Ready to send the next state we have on queue */
 						ast_clear_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE);
-						cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p);
+						cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p, NULL, NULL);
 					}
 				}
 			} else if (sipmethod == SIP_BYE)
@@ -13314,10 +13425,15 @@ static void ast_quiet_chan(struct ast_ch
 static int attempt_transfer(struct sip_dual *transferer, struct sip_dual *target)
 {
 	int res = 0;
+	struct sip_request req;
+	struct sip_pvt *p = NULL;
 	struct ast_channel *peera = NULL,	
 		*peerb = NULL,
 		*peerc = NULL,
 		*peerd = NULL;
+	char tmp[500];
+	char *t = tmp;
+	size_t maxbytes = sizeof(tmp);
 
 
 	/* We will try to connect the transferee with the target and hangup
@@ -13385,6 +13501,20 @@ static int attempt_transfer(struct sip_d
 			res = -1;
 		} else
 			ast_log(LOG_DEBUG, "SIP transfer: Succeeded to masquerade channels.\n");
+
+		if (peerd && !strcasecmp(peerd->tech->type, "SIP")) {
+		    p = peerd->tech_pvt;
+		    if (p && ast_test_flag(&(p->flags[1]), SIP_PAGE2_CID_UPDATE_INFO)) {
+		        reqprep(&req, p, SIP_INFO, 0, 1);
+			add_header(&req, "Content-Type", "message/sipfrag");
+		        ast_build_string(&t, &maxbytes, "From: \"%s\" <%s>\r\n", peerd->cid.cid_name, peerd->cid.cid_num);
+		        ast_build_string(&t, &maxbytes, "To: \"%s\" <%s>\r\n", peerc->cid.cid_name, peerc->cid.cid_num);
+		        add_header_contentLength(&req, strlen(tmp));
+		        add_line(&req, tmp);
+		        send_request(p, &req, 0, p->ocseq);
+		    }
+		}
+
 		return res;
 	} else {
 		ast_log(LOG_NOTICE, "SIP Transfer attempted with no appropriate bridged calls to transfer\n");
@@ -15115,8 +15245,8 @@ static int handle_request_subscribe(stru
 
 	if (p->subscribed != MWI_NOTIFICATION && !resubscribe) {
 		if (p->stateid > -1)
-			ast_extension_state_del(p->stateid, cb_extensionstate);
-		p->stateid = ast_extension_state_add(p->context, p->exten, cb_extensionstate, p);
+			ast_extension_state_callerid_del(p->stateid, cb_extensionstate);
+		p->stateid = ast_extension_state_callerid_add(p->context, p->exten, cb_extensionstate, p);
 	}
 
 	if (!ast_test_flag(req, SIP_PKT_IGNORE) && p)
@@ -15160,7 +15290,7 @@ static int handle_request_subscribe(stru
 			}
 
 			transmit_response(p, "200 OK", req);
-			transmit_state_notify(p, firststate, 1, FALSE);	/* Send first notification */
+			transmit_state_notify(p, firststate, 1, FALSE, NULL, NULL);	/* Send first notification */
 			append_history(p, "Subscribestatus", "%s", ast_extension_state2str(firststate));
 			/* hide the 'complete' exten/context in the refer_to field for later display */
 			ast_string_field_build(p, subscribeuri, "[EMAIL PROTECTED]", p->exten, p->context);
@@ -15951,6 +16081,100 @@ static int sip_poke_peer(struct sip_peer
 	return 0;
 }
 
+static char mandescr_sip_notify[] =
+"Description: Send a NOTIFY message to one or more SIP peers.\n"
+"Variables: \n"
+"  Peer: <name>           The peer name you want to send a NOTIFY to.\n"
+"  Type: <name>           The notify type (see sip_notify.conf).\n"
+"  ActionID: <id>	  Optional action ID for this AMI transaction.\n";
+
+/*! \brief  sip_notify: Send SIP notify to peer */
+static int sip_send_notify(int fd, const char *notify_type, const char *peer)
+{
+	struct ast_variable *varlist;
+	struct sip_pvt *p;
+	struct sip_request req;
+	struct ast_variable *var;
+
+	varlist = ast_variable_browse(notify_types, notify_type);
+
+	if (!varlist) {
+		if (fd > 0)
+		    ast_cli(fd, "Unable to find notify type '%s'\n", notify_type);
+		return RESULT_FAILURE;
+	}
+
+	p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY);
+	if (!p) {
+		ast_log(LOG_WARNING, "Unable to build sip pvt data for notify\n");
+		return RESULT_FAILURE;
+	}
+
+	if (create_addr(p, peer)) {
+		/* Maybe they're not registered, etc. */
+		sip_destroy(p);
+		if (fd > 0)
+		    ast_cli(fd, "Could not create address for '%s'\n", peer);
+		return RESULT_FAILURE;
+	}
+
+	initreqprep(&req, p, SIP_NOTIFY);
+
+	for (var = varlist; var; var = var->next)
+		add_header(&req, var->name, var->value);
+
+//	add_blank_header(&req);
+	/* Recalculate our side, and recalculate Call ID */
+	if (ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip))
+		memcpy(&p->ourip, &__ourip, sizeof(p->ourip));
+	build_via(p);
+	build_callid_pvt(p);
+	if (fd > 0)
+	    ast_cli(fd, "Sending NOTIFY of type '%s' to '%s'\n", notify_type, peer);
+	transmit_sip_request(p, &req);
+	sip_scheddestroy(p, 15000);
+
+	return RESULT_SUCCESS;
+}
+
+/*! \brief  manager_sip_notify: Send a notify (see sip_notify.conf) to a peer ---*/
+static int manager_sip_notify(struct mansession *s, const struct message *m)
+{
+	const char *id = astman_get_header(m,"ActionID");
+	const char *peer;
+	const char *notify_type;
+	int res = 0;
+
+	peer = astman_get_header(m,"Peer");
+	if (ast_strlen_zero(peer)) {
+		astman_send_error(s, m, "Peer: <name> missing.\n");
+		return 0;
+	}
+	notify_type = astman_get_header(m,"Type");
+	if (ast_strlen_zero(notify_type)) {
+		astman_send_error(s, m, "Type: <name> missing.\n");
+		return 0;
+	}
+
+	res = sip_send_notify(-1, notify_type, peer);
+	if (res != RESULT_SUCCESS) {
+	    astman_append(s, "Response: SIPNotify Failure\r\n"
+			"Peer: %s\r\n"
+			"Type: %s\r\n"
+			"ActionID: %s\r\n"
+			"\r\n",
+			peer, notify_type, id);
+	} else {
+	    astman_append(s, "Response: SIPNotify Success\r\n"
+			"Peer: %s\r\n"
+			"Type: %s\r\n"
+			"ActionID: %s\r\n"
+			"\r\n",
+			peer, notify_type, id);
+	}
+	return res;
+}
+
 /*! \brief Part of PBX channel interface
 \note
 \par	Return values:---
@@ -16058,10 +16282,14 @@ static struct ast_channel *sip_request_c
 {
 	int oldformat;
 	struct sip_pvt *p;
+	struct sip_peer *peer = NULL;
 	struct ast_channel *tmpc = NULL;
 	char *ext, *host;
 	char tmp[256];
 	char *dest = data;
+	char *number = NULL;
+	int strip = 0;
+	int ton = 0; /* 0 local, 1 national, 2 international */
 
 	oldformat = format;
 	if (!(format &= ((AST_FORMAT_MAX_AUDIO << 1) - 1))) {
@@ -16121,6 +16349,70 @@ static struct ast_channel *sip_request_c
 	if (ext) {
 		ast_string_field_set(p, username, ext);
 		ast_string_field_free(p, fullcontact);
+		peer = find_peer(host, NULL, 1);
+		if (peer) {
+		    if (peer->dialplan != SIP_DIALPLAN_LOCAL) {
+			/* do the dialplan thingie */
+			ton = 0;
+			strip = 0;
+			if (!ast_strlen_zero(peer->internationalprefix)) {
+			    number = strstr(p->username, peer->internationalprefix);
+			    if (number == p->username) {
+				strip += strlen(peer->internationalprefix);
+				if (option_verbose > 4) ast_log(LOG_NOTICE, "found int prefix, rest is %s\n",number+strip);
+				ton = 2;
+			    }
+			}
+			if (!ton && (!ast_strlen_zero(peer->nationalprefix))) {
+			    number = strstr(p->username, peer->nationalprefix);
+			    if (number == p->username) {
+				strip += strlen(peer->nationalprefix);
+			        if (option_verbose > 4) ast_log(LOG_NOTICE, "found national prefix, rest is %s\n",number+strip);
+				ton = 1;
+			    }
+			}
+			if (peer->dialplan == SIP_DIALPLAN_INTERNATIONAL) {
+			    if (ton == 1) {
+				char tmp[128];
+				/* add countrycode */
+				snprintf(tmp, sizeof(tmp) - 1, "%s%s", peer->countrycode, p->username + strip);
+				ast_string_field_set(p, username, tmp);
+			    } else {
+				snprintf(tmp, sizeof(tmp) - 1, "%s", p->username + strip);
+				ast_string_field_set(p, username, tmp);
+			    }
+			}
+			if (option_verbose > 4) ast_log(LOG_NOTICE, "calling %s\n", p->username);
+		    }
+		    if (!ast_strlen_zero(peer->prefix)) {
+			char tmp[128];
+			snprintf(tmp, sizeof(tmp) - 1, "%s%s", peer->prefix, p->username);
+			ast_string_field_set(p, username, tmp);
+			if (option_verbose > 4) ast_log(LOG_NOTICE, "calling %s (prefix %s)\n", p->username, peer->prefix);
+		    }
+		    if (peer->rtpip.s_addr) {
+			memcpy(&p->rtpip, &peer->rtpip, sizeof(p->rtpip));
+			if (p->rtp) {
+			    ast_rtp_destroy(p->rtp);
+			}
+			p->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, p->rtpip);
+		    }
+		    if (!ast_strlen_zero(peer->assertedid)) {
+			ast_string_field_set(p, assertedid, peer->assertedid);
+		    }
+		    if (!ast_strlen_zero(peer->preferredid)) {
+			ast_string_field_set(p, preferredid, peer->preferredid);
+		    }
+		    if (!ast_strlen_zero(peer->privacy)) {
+			ast_string_field_set(p, privacy, peer->privacy);
+		    }
+		    if (!ast_strlen_zero(peer->cid_num)) {
+			ast_string_field_set(p, cid_num, peer->cid_num);
+		    }
+		    if (!ast_strlen_zero(peer->cid_name)) {
+			ast_string_field_set(p, cid_name, peer->cid_name);
+		    }
+		}
 	}
 #if 0
 	printf("Setting up to call extension '%s' at '%s'\n", ext ? ext : "<none>", host);
@@ -16517,6 +16809,14 @@ static struct sip_user *build_user(const
 			ast_copy_string(user->md5secret, v->value, sizeof(user->md5secret));
 		} else if (!strcasecmp(v->name, "callerid")) {
 			ast_callerid_split(v->value, user->cid_name, sizeof(user->cid_name), user->cid_num, sizeof(user->cid_num));
+		} else if (!strcasecmp(v->name, "calleridupdate")) {
+			if (!strcasecmp(v->value, "never")) {
+			    ast_clear_flag((&user->flags[1]), SIP_PAGE2_CID_UPDATE_INFO);
+			    ast_set_flag((&user->flags[1]), SIP_PAGE2_CID_UPDATE_NEVER);
+			} else if (!strcasecmp(v->value, "info")) {
+			    ast_clear_flag((&user->flags[1]), SIP_PAGE2_CID_UPDATE_NEVER);
+			    ast_set_flag((&user->flags[1]), SIP_PAGE2_CID_UPDATE_INFO);
+			}
 		} else if (!strcasecmp(v->name, "fullname")) {
 			ast_copy_string(user->cid_name, v->value, sizeof(user->cid_name));
 		} else if (!strcasecmp(v->name, "cid_number")) {
@@ -16651,6 +16951,8 @@ static struct sip_peer *build_peer(const
 	struct ast_flags peerflags[2] = {{(0)}};
 	struct ast_flags mask[2] = {{(0)}};
 	char fullcontact[sizeof(peer->fullcontact)] = "";
+	struct ast_hostent ahp;
+	struct hostent *hp;
 
 	if (!realtime || ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS))
 		/* Note we do NOT use find_peer here, to avoid realtime recursion */
@@ -16848,6 +17150,14 @@ static struct sip_peer *build_peer(const
 				ast_log(LOG_WARNING, "'%s' is not a valid RTP keepalive time at line %d.  Using default.\n", v->value, v->lineno);
 				peer->rtpkeepalive = global_rtpkeepalive;
 			}
+		} else if (!strcasecmp(v->name, "calleridupdate")) {
+			if (!strcasecmp(v->value, "never")) {
+			    ast_clear_flag((&peer->flags[1]), SIP_PAGE2_CID_UPDATE_INFO);
+			    ast_set_flag((&peer->flags[1]), SIP_PAGE2_CID_UPDATE_NEVER);
+			} else if (!strcasecmp(v->value, "info")) {
+			    ast_clear_flag((&peer->flags[1]), SIP_PAGE2_CID_UPDATE_NEVER);
+			    ast_set_flag((&peer->flags[1]), SIP_PAGE2_CID_UPDATE_INFO);
+			}
 		} else if (!strcasecmp(v->name, "setvar")) {
 			/* Set peer channel variable */
 			varname = ast_strdupa(v->value);
@@ -16871,6 +17181,32 @@ static struct sip_peer *build_peer(const
 			peer->maxcallbitrate = atoi(v->value);
 			if (peer->maxcallbitrate < 0)
 				peer->maxcallbitrate = default_maxcallbitrate;
+		} else if (!strcasecmp(v->name, "prefix")) {
+			ast_copy_string(peer->prefix, v->value, sizeof(peer->prefix));
+		} else if (!strcasecmp(v->name, "nationalprefix")) {
+			ast_copy_string(peer->nationalprefix, v->value, sizeof(peer->nationalprefix));
+		} else if (!strcasecmp(v->name, "internationalprefix")) {
+			ast_copy_string(peer->internationalprefix, v->value, sizeof(peer->internationalprefix));
+		} else if (!strcasecmp(v->name, "countrycode")) {
+			ast_copy_string(peer->countrycode, v->value, sizeof(peer->countrycode));
+		} else if (!strcasecmp(v->name, "dialplan")) {
+			if (!strcasecmp(v->value, "international")) {
+			    peer->dialplan = SIP_DIALPLAN_INTERNATIONAL;
+			} else {
+			    peer->dialplan = SIP_DIALPLAN_LOCAL;
+			}
+		} else if (!strcasecmp(v->name, "rtpip")) {
+			if (!(hp = ast_gethostbyname(v->value, &ahp))) {
+				ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
+			} else {
+				memcpy(&peer->rtpip, hp->h_addr, sizeof(peer->rtpip));
+			}
+		} else if (!strcasecmp(v->name, "assertedid")) {
+			ast_copy_string(peer->assertedid, v->value, sizeof(peer->assertedid));
+		} else if (!strcasecmp(v->name, "preferredid")) {
+			ast_copy_string(peer->preferredid, v->value, sizeof(peer->preferredid));
+		} else if (!strcasecmp(v->name, "privacy")) {
+			ast_copy_string(peer->privacy, v->value, sizeof(peer->privacy));
 		}
 	}
 	if (!ast_strlen_zero(fullcontact)) {
@@ -17096,6 +17432,14 @@ static int reload_config(enum channelrel
 			ast_set2_flag(&global_flags[1], i || ast_true(v->value), SIP_PAGE2_RTAUTOCLEAR);
 		} else if (!strcasecmp(v->name, "usereqphone")) {
 			ast_set2_flag(&global_flags[0], ast_true(v->value), SIP_USEREQPHONE);	
+		} else if (!strcasecmp(v->name, "calleridupdate")) {
+			if (!strcasecmp(v->value, "never")) {
+			    ast_clear_flag((&global_flags[1]), SIP_PAGE2_CID_UPDATE_INFO);
+			    ast_set_flag((&global_flags[1]), SIP_PAGE2_CID_UPDATE_NEVER);
+			} else if (!strcasecmp(v->value, "info")) {
+			    ast_clear_flag((&global_flags[1]), SIP_PAGE2_CID_UPDATE_NEVER);
+			    ast_set_flag((&global_flags[1]), SIP_PAGE2_CID_UPDATE_INFO);
+			}
 		} else if (!strcasecmp(v->name, "relaxdtmf")) {
 			global_relaxdtmf = ast_true(v->value);
 		} else if (!strcasecmp(v->name, "checkmwi")) {
@@ -18186,6 +18530,8 @@ static int load_module(void)
 			"List SIP peers (text format)", mandescr_show_peers);
 	ast_manager_register2("SIPshowpeer", EVENT_FLAG_SYSTEM, manager_sip_show_peer,
 			"Show SIP peer (text format)", mandescr_show_peer);
+	ast_manager_register2("SIPNotify", EVENT_FLAG_SYSTEM, manager_sip_notify,
+			"Send NOTIFY to peer", mandescr_sip_notify);
 
 	sip_poke_all_peers();	
 	sip_send_all_registers();
@@ -18226,6 +18572,7 @@ static int unload_module(void)
 	/* Unregister AMI actions */
 	ast_manager_unregister("SIPpeers");
 	ast_manager_unregister("SIPshowpeer");
+	ast_manager_unregister("SIPNotify");
 
 	ast_mutex_lock(&iflock);
 	/* Hangup all interfaces if they have an owner */
_______________________________________________
Bristuff-users mailing list
[email protected]
http://lists.three-dimensional.net/mailman/listinfo/bristuff-users

Reply via email to