[asterisk-commits] rizzo: branch rizzo/astobj2 r72802 - /team/rizzo/astobj2/channels/chan_sip.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Sat Jun 30 17:41:31 CDT 2007


Author: rizzo
Date: Sat Jun 30 17:41:31 2007
New Revision: 72802

URL: http://svn.digium.com/view/asterisk?view=rev&rev=72802
Log:
merge from trunk svn 63613

Modified:
    team/rizzo/astobj2/channels/chan_sip.c

Modified: team/rizzo/astobj2/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/rizzo/astobj2/channels/chan_sip.c?view=diff&rev=72802&r1=72801&r2=72802
==============================================================================
--- team/rizzo/astobj2/channels/chan_sip.c (original)
+++ team/rizzo/astobj2/channels/chan_sip.c Sat Jun 30 17:41:31 2007
@@ -1634,6 +1634,7 @@
 static const char *__get_header(const struct sip_request *req, const char *name, int *start);
 static int lws2sws(char *msgbuf, int len);
 static void extract_uri(struct sip_pvt *p, struct sip_request *req);
+static char *remove_uri_parameters(char *uri);
 static int get_refer_info(struct sip_pvt *transferer, struct sip_request *outgoing_req);
 static int get_also_info(struct sip_pvt *p, struct sip_request *oreq);
 static int parse_ok_contact(struct sip_pvt *pvt, struct sip_request *req);
@@ -2706,10 +2707,11 @@
 	return tmp;
 }
 
-/*!
- * parses a URI in its components.
- * If scheme is specified, drop it from the top.
- * If a component is not requested, do not split around it.
+/*! \brief * parses a URI in its components.
+ *
+ * \note 
+ *- If scheme is specified, drop it from the top.
+ * - If a component is not requested, do not split around it.
  * This means that if we don't have domain, we cannot split
  * name:pass and domain:port.
  * It is safe to call with ret_name, pass, domain, port
@@ -2717,6 +2719,7 @@
  * Init pointers to empty string so we never get NULL dereferencing.
  * Overwrites the string.
  * return 0 on success, other values on error.
+ * general form we are expecting is sip[s]:username[:password][;parameter]@host[:port][;...] 
  */
 static int parse_uri(char *uri, char *scheme,
 	char **ret_name, char **pass, char **domain, char **port, char **options)
@@ -2729,13 +2732,12 @@
 		*pass = "";
 	if (port)
 		*port = "";
-	name = strsep(&uri, ";");	/* remove options */
 	if (scheme) {
 		int l = strlen(scheme);
-		if (!strncmp(name, scheme, l))
-			name += l;
+		if (!strncmp(uri, scheme, l))
+			uri += l;
 		else {
-			ast_log(LOG_NOTICE, "Missing scheme '%s' in '%s'\n", scheme, name);
+			ast_log(LOG_NOTICE, "Missing scheme '%s' in '%s'\n", scheme, uri);
 			error = -1;
 		}
 	}
@@ -2749,14 +2751,20 @@
 		 */
 		char *c, *dom = "";
 
-		if ((c = strchr(name, '@')) == NULL) {
+		if ((c = strchr(uri, '@')) == NULL) {
 			/* domain-only URI, according to the SIP RFC. */
-			dom = name;
+			dom = uri;
 			name = "";
 		} else {
 			*c++ = '\0';
 			dom = c;
-		}
+			name = uri;
+		}
+
+		/* Remove options in domain and name */
+		dom = strsep(&dom, ";");
+		name = strsep(&name, ";");
+
 		if (port && (c = strchr(dom, ':'))) { /* Remove :port */
 			*c++ = '\0';
 			*port = c;
@@ -4543,6 +4551,12 @@
 		pbx_builtin_setvar_helper(tmp,v->name,v->value);
 
 	append_history(i, "NewChan", "Channel %s - from %s", tmp->name, i->callid);
+
+	/* Inform manager user about new channel and their SIP call ID */
+	if (global_callevents)
+		manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate",
+			"Channel: %s\r\nUniqueid: %s\r\nChanneltype: %s\r\nSIPcallid: %s\r\nSIPfullcontact: %s\r\n",
+			tmp->name, tmp->uniqueid, "SIP", i->callid, i->fullcontact);
 
 	return tmp;
 }
@@ -6312,7 +6326,7 @@
 	int debug=sip_debug_test_pvt(p);
 
 	/* Parse uri to h (host) and port - uri is already just the part inside the <> */
-	/* general form we are expecting is sip[s]:username[:password]@host[:port][;...] */
+	/* general form we are expecting is sip[s]:username[:password][;parameter]@host[:port][;...] */
 
 	if (debug)
 		ast_verbose("set_destination: Parsing <%s> for address/port to send to\n", uri);
@@ -6493,7 +6507,7 @@
 		ast_copy_string(stripped, get_header(orig, is_outbound ? "To" : "From"),
 				sizeof(stripped));
 		n = get_in_brackets(stripped);
-		c = strsep(&n, ";");	/* trim ; and beyond */
+		c = remove_uri_parameters(n);
 	}	
 	init_req(req, sipmethod, c);
 
@@ -7423,6 +7437,19 @@
 	return send_request(p, &req, XMIT_CRITICAL, p->ocseq);
 }
 
+/* \brief Remove URI parameters at end of URI, not in username part though */
+static char *remove_uri_parameters(char *uri)	/* XXX simplify if possible with strsep */
+{
+	char *atsign;
+	atsign = strchr(uri, '@');	/* First, locate the at sign */
+	if (!atsign)
+		atsign = uri;	/* Ok hostname only, let's stick with the rest */
+	atsign = strchr(atsign, ';');	/* Locate semi colon */
+	if (atsign)
+		*atsign = '\0';	/* Kill at the semi colon */
+	return uri;
+}
+
 /*! \brief Check Contact: URI of SIP message */
 static void extract_uri(struct sip_pvt *p, struct sip_request *req)
 {
@@ -7431,7 +7458,8 @@
 
 	ast_copy_string(stripped, get_header(req, "Contact"), sizeof(stripped));
 	c = get_in_brackets(stripped);
-	c = strsep(&c, ";");	/* trim ; and beyond */
+	/* Cut the URI at the at sign after the @, not in the username part */
+	c = remove_uri_parameters(c);
 	if (!ast_strlen_zero(c))
 		ast_string_field_set(p, uri, c);
 }
@@ -7819,11 +7847,14 @@
 	
 	/* Check which device/devices we are watching  and if they are registered */
 	if (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, p->context, p->exten)) {
-		/* If they are not registered, we will override notification and show no availability */
-		if (ast_device_state(hint) == AST_DEVICE_UNAVAILABLE) {
-			local_state = NOTIFY_CLOSED;
-			pidfstate = "away";
-			pidfnote = "Not online";
+		char *hint2 = hint, *individual_hint = NULL;
+		while ((individual_hint = strsep(&hint2, "&"))) {
+			/* If they are not registered, we will override notification and show no availability */
+			if (ast_device_state(individual_hint) == AST_DEVICE_UNAVAILABLE) {
+				local_state = NOTIFY_CLOSED;
+				pidfstate = "away";
+				pidfnote = "Not online";
+			}
 		}
 	}
 
@@ -7833,7 +7864,8 @@
 		ast_log(LOG_WARNING, "Huh?  Not a SIP header (%s)?\n", c);
 		return -1;
 	}
-	mfrom = strsep(&c, ";");	/* trim ; and beyond */
+
+	mfrom = remove_uri_parameters(c);
 
 	ast_copy_string(to, get_header(&p->initreq, "To"), sizeof(to));
 	c = get_in_brackets(to);
@@ -7841,7 +7873,7 @@
 		ast_log(LOG_WARNING, "Huh?  Not a SIP header (%s)?\n", c);
 		return -1;
 	}
-	mto = strsep(&c, ";");	/* trim ; and beyond */
+	mto = remove_uri_parameters(c);
 
 	reqprep(&req, p, SIP_NOTIFY, 0, 1);
 
@@ -8586,6 +8618,7 @@
 		ast_sched_del(sched, peer->expire);
 	peer->expire = ast_sched_add(sched, (expiry + 10) * 1000, expire_register, peer);
 	register_peer_exten(peer, TRUE);
+	ast_device_state_changed("SIP/%s", peer->name);
 }
 
 /*! \brief Save contact header for 200 OK on INVITE */
@@ -9193,7 +9226,7 @@
 		ast_uri_decode(tmp);
 
 	c = get_in_brackets(tmp);
-	c = strsep(&c, ";");	/* Ditch ;user=phone */
+	c = remove_uri_parameters(c);
 
 	if (!strncmp(c, "sip:", 4)) {
 		name = c + 4;
@@ -9218,6 +9251,9 @@
 			}
 		}
 	}
+	c = strchr(name, ';');	/* Remove any Username parameters */
+	if (c)
+		*c = '\0';
 
 	ast_string_field_set(p, exten, name);
 	build_contact(p);
@@ -12074,8 +12110,57 @@
 				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, "403 Forbidden", req);
+		}
+		return;
+	} else if (!ast_strlen_zero(c = get_header(req, "Record"))) {
+		/* INFO messages generated by some phones to start/stop recording
+			on phone calls. 
+			OEJ: I think this should be something that is enabled/disabled
+			per device. I don't want incoming callers to record calls in my
+			pbx.
+		*/
+		/* first, get the feature string, if it exists */
+		struct ast_call_feature *feat;
+		int j;
+		struct ast_frame f = { AST_FRAME_DTMF, };
+
+		ast_rdlock_call_features();
+		feat = ast_find_call_feature("automon");
+		if (!feat || ast_strlen_zero(feat->exten)) {
+			ast_log(LOG_WARNING,"Recording requested, but no One Touch Monitor registered. (See features.conf)\n");
+			/* 403 means that we don't support this feature, so don't request it again */
+			transmit_response(p, "403 Forbidden", req);
+			ast_unlock_call_features();
+			return;
+		} 
+		/* OEJ: Why is the DTMF code included in the record section? */
+		f.len = 100;
+		for (j=0; j<strlen(feat->exten); j++) {
+			f.subclass = feat->exten[j];
+			ast_queue_frame(p->owner, &f);
+			if (sipdebug)
+				ast_verbose("* DTMF-relay event received: %c\n", f.subclass);
+		}
+		ast_unlock_call_features();
+#ifdef DISABLED_CODE
+		/* And feat isn't used here - Is this code tested at all??? 
+			We just send a reply ... 
+		*/
+		if (strcasecmp(c, "on")== 0) {
+			if (option_debug)
+				ast_log(LOG_DEBUG, "Got a Request to Record the channel!\n");
+
+			transmit_response(p, "200 OK", req);
+			return;
+		} else if (strcasecmp(c, "off")== 0) {
+			if (option_debug)
+				ast_log(LOG_DEBUG, "Got a Request to Stop Recording the channel\n");
+			transmit_response(p, "200 OK", req);
+			return;
+		}
+#endif
+		transmit_response(p, "200 OK", req);
 		return;
 	}
 	/* Other type of INFO message, not really understood by Asterisk */
@@ -12770,8 +12855,8 @@
 	char *domain;
 
 	ast_copy_string(tmp, get_header(req, "Contact"), sizeof(tmp));
-	s = get_in_brackets(tmp);
-	s = strsep(&s, ";");	/* strip ; and beyond */
+	/* s = get_in_brackets(tmp); */ /* XXX why removed ? */
+	s = remove_uri_parameters(get_in_brackets(tmp));
 	if (ast_test_flag(&p->flags[0], SIP_PROMISCREDIR)) {
 		if (!strncasecmp(s, "sip:", 4))
 			s += 4;
@@ -12791,11 +12876,14 @@
 			/* No username part */
 			domain = tmp;
 		}
-		e = strchr(tmp, '/');
+		e = strchr(tmp, '/');	/* WHEN do we hae a forward slash in the URI? */
 		if (e)
 			*e = '\0';
 		if (!strncasecmp(s, "sip:", 4))
 			s += 4;
+		e = strchr(s, ';');	/* And username ; parameters? */
+		if (e)
+			*e = '\0';	
 		if (option_debug > 1)
 			ast_log(LOG_DEBUG, "Received 302 Redirect to extension '%s' (domain %s)\n", s, domain);
 		if (p->owner) {
@@ -13000,6 +13088,10 @@
 		if (!req_ignore(req) && p->owner) {
 			if (!reinvite) {
 				ast_queue_control(p->owner, AST_CONTROL_ANSWER);
+				if (global_callevents)
+					manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate",
+						"Channel: %s\r\nChanneltype: %s\r\nUniqueid: %s\r\nSIPcallid: %s\r\nSIPfullcontact: %s\r\nPeername: %s\r\n",
+						p->owner->name, p->owner->uniqueid, "SIP", p->callid, p->fullcontact, p->peername);
 			} else {	/* RE-invite */
 				ast_queue_frame(p->owner, &ast_null_frame);
 			}
@@ -14924,8 +15016,7 @@
 				} 
 				/* Respond to normal re-invite */
 				if (sendok)
-					transmit_response_with_sdp(p, "200 OK", req, XMIT_CRITICAL);
-
+					transmit_response_with_sdp(p, "200 OK", req, ast_test_flag(req, SIP_PKT_IGNORE) ?  XMIT_UNRELIABLE : XMIT_CRITICAL);
 			}
 			p->invitestate = INV_TERMINATED;
 			break;
@@ -14997,7 +15088,6 @@
   	        transferer->refer->status = REFER_FAILED;
   	        sip_pvt_unlock(targetcall_pvt);
   	        ast_channel_unlock(current->chan1);
-  	        ast_channel_unlock(targetcall_pvt->owner);
   	        return -1;
 	}
 
@@ -16809,6 +16899,10 @@
 	p->jointcapability = oldformat;
 	sip_pvt_lock(p);
 	tmpc = sip_new(p, AST_STATE_DOWN, host);	/* Place the call */
+	if (global_callevents)
+		manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate",
+			"Channel: %s\r\nChanneltype: %s\r\nSIPcallid: %s\r\nSIPfullcontact: %s\r\nPeername: %s\r\n",
+			p->owner? p->owner->name : "", "SIP", p->callid, p->fullcontact, p->peername);
 	/* XXX who keeps the reference ? */
 	sip_pvt_unlock(p);
 	if (!tmpc)
@@ -17892,6 +17986,7 @@
 			if (ast_true(hassip) || (!hassip && genhassip)) {
 				peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0);
 				if (peer) {
+					ast_device_state_changed("SIP/%s", peer->name);
 					ASTOBJ_CONTAINER_LINK(&peerl,peer);
 					unref_peer(peer);
 					peer_count++;
@@ -18695,6 +18790,7 @@
 /*! \brief PBX load module - initialization */
 static int load_module(void)
 {
+	ast_verbose("SIP channel loading...\n");
 	ASTOBJ_CONTAINER_INIT(&userl);	/* User object list */
 	ASTOBJ_CONTAINER_INIT(&peerl);	/* Peer object list */
 	ASTOBJ_CONTAINER_INIT(&regl);	/* Registry object list */




More information about the asterisk-commits mailing list