瀏覽代碼

Merge pull request #115 from kamailio/lazedo/registrar-registered

registrar : add optional params to registered function
Daniel-Constantin Mierla 10 年之前
父節點
當前提交
4763dfab3b

+ 42 - 1
modules/registrar/doc/registrar_admin.xml

@@ -658,6 +658,11 @@ modparam("registrar", "path_check_local", 1)
 
 	<section id="registrar.p.reg_callid_avp">
 		<title><varname>reg_callid_avp</varname> (string)</title>
+		<para>
+			<emphasis>
+				obsolete. use match_option in registered function
+			</emphasis>
+		</para>
 		<para>
 		If reg_callid_avp is defined and populated when the
 		<function>registered()</function> is invoked, the result is 
@@ -1102,7 +1107,7 @@ lookup_branches("location");
 
 	<section id="registrar.f.registered">
 		<title>
-		<function moreinfo="none">registered(domain [, uri])</function>
+		<function moreinfo="none">registered(domain [, uri [, match_option [, match_action]]])</function>
 		</title>
 		<para>
 		The function returns true if the AOR in the Request-URI is 
@@ -1124,6 +1129,35 @@ lookup_branches("location");
 			of R-URI. It can be a dynamic string with pseudo-variables.
 			</para>
 		</listitem>
+		<listitem>
+			<para>
+			<emphasis>match_option</emphasis> (optional) - flag parameter to restrict
+			contact search. use reg_xavp_cfg to set the values to compare to.
+			</para>
+            <para>flag values is as follows:</para>
+			<itemizedlist>
+				<listitem>
+					<para>1 - match_callid</para>
+				</listiem>
+				<listitem>
+					<para>2 - match_received</para>
+				</listiem>
+				<listitem>
+					<para>4 - match_contact</para>
+				</listiem>
+			</itemizedlist>			
+		</listitem>
+		<listitem>
+			<para>
+			<emphasis>match_action</emphasis> (optional) - actions to perform when match is positive.
+			</para>
+            <para>flag values is as follows:</para>
+			<itemizedlist>
+				<listitem>
+					<para>1 - set xavp_rcd with value from matched contact</para>
+				</listiem>
+			</itemizedlist>						
+		</listitem>
 		</itemizedlist>
 		<para>
 		This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
@@ -1137,6 +1171,13 @@ if (registered("location")) {
 	...
 };
 ...
+$xavp(regcfg=>match_received) = $su;
+if (registered("location","$rz:$Au", 2)) {
+	sl_send_reply("100", "Trying");
+	...
+};
+...
+
 </programlisting>
 		</example>
 	</section>

+ 60 - 14
modules/registrar/lookup.c

@@ -619,13 +619,24 @@ done:
  * it is similar to lookup but registered neither rewrites
  * the Request-URI nor appends branches
  */
-int registered(struct sip_msg* _m, udomain_t* _d, str* _uri)
+int registered(struct sip_msg* _m, udomain_t* _d, str* _uri) {
+	return registered4(_m, _d, _uri, 0, 0);
+}
+
+int registered3(struct sip_msg* _m, udomain_t* _d, str* _uri, int match_flag) {
+	return registered4(_m, _d, _uri, match_flag, 0);
+}
+
+int registered4(struct sip_msg* _m, udomain_t* _d, str* _uri, int match_flag, int match_action_flag)
 {
 	str uri, aor;
 	urecord_t* r;
 	ucontact_t* ptr;
 	int res;
-	int_str match_callid=(int_str)0;
+	str match_callid = {0,0};
+	str match_received = {0,0};
+	str match_contact = {0,0};
+	sr_xavp_t *vavp = NULL;
 
 	if(_uri!=NULL)
 	{
@@ -650,26 +661,61 @@ int registered(struct sip_msg* _m, udomain_t* _d, str* _uri)
 	}
 
 	if (res == 0) {
-		
-		if (reg_callid_avp_name.n) {
-			struct usr_avp *avp =
-				search_first_avp( reg_callid_avp_type, reg_callid_avp_name, &match_callid, 0);
-			if (!(avp && is_avp_str_val(avp)))
-				match_callid.n = 0;
-				match_callid.s.s = NULL;
-		} else {
-			match_callid.n = 0;
-			match_callid.s.s = NULL;
+		LM_DBG("searching with match flags (%d,%d)\n", match_flag, reg_match_flag_param);
+		if(reg_xavp_cfg.s!=NULL) {
+
+			if((match_flag & 1)
+					&& (vavp = xavp_get_child_with_sval(&reg_xavp_cfg, &match_callid_name)) != NULL
+					&& vavp->val.v.s.len > 0) {
+				match_callid = vavp->val.v.s;
+				LM_DBG("matching with callid %.*s\n", match_callid.len, match_callid.s);
+			}
+
+			if((match_flag & 2)
+					&& (vavp = xavp_get_child_with_sval(&reg_xavp_cfg, &match_received_name)) != NULL
+					&& vavp->val.v.s.len > 0) {
+				match_received = vavp->val.v.s;
+				LM_DBG("matching with received %.*s\n", match_received.len, match_received.s);
+			}
+
+			if((match_flag & 4)
+					&& (vavp = xavp_get_child_with_sval(&reg_xavp_cfg, &match_contact_name)) != NULL
+					&& vavp->val.v.s.len > 0) {
+				match_contact = vavp->val.v.s;
+				LM_DBG("matching with contact %.*s\n", match_contact.len, match_contact.s);
+			}
 		}
 
 		for (ptr = r->contacts; ptr; ptr = ptr->next) {
 			if(!VALID_CONTACT(ptr, act_time)) continue;
-			if (match_callid.s.s && /* optionally enforce tighter matching w/ Call-ID */
-				memcmp(match_callid.s.s,ptr->callid.s,match_callid.s.len))
+			if (match_callid.s && /* optionally enforce tighter matching w/ Call-ID */
+				match_callid.len > 0 &&
+				(match_callid.len != ptr->callid.len || 
+				memcmp(match_callid.s, ptr->callid.s, match_callid.len)))
+				continue;
+			if (match_received.s && /* optionally enforce tighter matching w/ ip:port */
+				match_received.len > 0 &&
+				(match_received.len != ptr->received.len || 
+				memcmp(match_received.s, ptr->received.s, match_received.len)))
 				continue;
+			if (match_contact.s && /* optionally enforce tighter matching w/ Contact */
+				match_contact.len > 0 &&
+				(match_contact.len != ptr->c.len || 
+				memcmp(match_contact.s, ptr->c.s, match_contact.len)))
+				continue;
+
+			if(ptr->xavp!=NULL && match_action_flag == 1) {
+				sr_xavp_t *xavp = xavp_clone_level_nodata(ptr->xavp);
+				if(xavp_add(xavp, NULL)<0) {
+					LM_ERR("error adding xavp for %.*s after successful match\n", aor.len, ZSW(aor.s));
+					xavp_destroy_list(&xavp);
+				}
+			}
+
 			ul.release_urecord(r);
 			ul.unlock_udomain(_d, &aor);
 			LM_DBG("'%.*s' found in usrloc\n", aor.len, ZSW(aor.s));
+
 			return 1;
 		}
 	}

+ 2 - 1
modules/registrar/lookup.h

@@ -67,6 +67,7 @@ int lookup_branches(sip_msg_t *msg, udomain_t *d);
  * the Request-URI nor appends branches
  */
 int registered(struct sip_msg* _m, udomain_t* _d, str* _uri);
-
+int registered3(struct sip_msg* _m, udomain_t* _d, str* _uri, int match_flag);
+int registered4(struct sip_msg* _m, udomain_t* _d, str* _uri, int match_flag, int match_action_flag);
 
 #endif /* LOOKUP_H */

+ 61 - 24
modules/registrar/reg_mod.c

@@ -101,10 +101,9 @@ int reg_outbound_mode = 0;
 int reg_regid_mode = 0;
 int reg_flow_timer = 0;
 
-/* Populate this AVP if testing for specific registration instance. */
-char *reg_callid_avp_param = 0;
-unsigned short reg_callid_avp_type = 0;
-int_str reg_callid_avp_name;
+str match_callid_name = str_init("match_callid");
+str match_received_name = str_init("match_received");
+str match_contact_name = str_init("match_contact");
 
 char* rcv_avp_param = 0;
 unsigned short rcv_avp_type = 0;
@@ -164,6 +163,10 @@ static cmd_export_t cmds[] = {
 			REQUEST_ROUTE | FAILURE_ROUTE },
 	{"registered",   (cmd_function)w_registered,  2,  domain_uri_fixup, 0,
 			REQUEST_ROUTE | FAILURE_ROUTE },
+	{"registered",   (cmd_function)w_registered3, 3,  registered_fixup, 0,
+			REQUEST_ROUTE | FAILURE_ROUTE },
+	{"registered",   (cmd_function)w_registered4, 4,  registered_fixup, 0,
+			REQUEST_ROUTE | FAILURE_ROUTE },
 	{"add_sock_hdr", (cmd_function)add_sock_hdr,  1,  fixup_str_null, 0,
 			REQUEST_ROUTE },
 	{"unregister",   (cmd_function)w_unregister,  2,  unreg_fixup, 0,
@@ -200,7 +203,6 @@ static param_export_t params[] = {
 	{"max_expires",        INT_PARAM, &default_registrar_cfg.max_expires			},
 	{"received_param",     PARAM_STR, &rcv_param           					},
 	{"received_avp",       PARAM_STRING, &rcv_avp_param       					},
-	{"reg_callid_avp",     PARAM_STRING, &reg_callid_avp_param					},
 	{"max_contacts",       INT_PARAM, &default_registrar_cfg.max_contacts			},
 	{"retry_after",        INT_PARAM, &default_registrar_cfg.retry_after			},
 	{"sock_flag",          INT_PARAM, &sock_flag           					},
@@ -209,7 +211,7 @@ static param_export_t params[] = {
 	{"use_path",           INT_PARAM, &path_enabled        					},
 	{"path_mode",          INT_PARAM, &path_mode           					},
 	{"path_use_received",  INT_PARAM, &path_use_params     					},
-        {"path_check_local",   INT_PARAM, &path_check_local                                     },
+	{"path_check_local",   INT_PARAM, &path_check_local                                     },
 	{"xavp_cfg",           PARAM_STR, &reg_xavp_cfg     					},
 	{"xavp_rcd",           PARAM_STR, &reg_xavp_rcd     					},
 	{"gruu_enabled",       INT_PARAM, &reg_gruu_enabled    					},
@@ -306,24 +308,6 @@ static int mod_init(void)
 		rcv_avp_type = 0;
 	}
 
-	if (reg_callid_avp_param && *reg_callid_avp_param) {
-		s.s = reg_callid_avp_param; s.len = strlen(s.s);
-		if (pv_parse_spec(&s, &avp_spec)==0
-			|| avp_spec.type!=PVT_AVP) {
-			LM_ERR("malformed or non AVP %s AVP definition\n", reg_callid_avp_param);
-			return -1;
-		}
-
-		if(pv_get_avp_name(0, &avp_spec.pvp, &reg_callid_avp_name, &reg_callid_avp_type)!=0)
-		{
-			LM_ERR("[%s]- invalid AVP definition\n", reg_callid_avp_param);
-			return -1;
-		}
-	} else {
-		reg_callid_avp_name.n = 0;
-		reg_callid_avp_type = 0;
-	}
-
 	bind_usrloc = (bind_usrloc_t)find_export("ul_bind_usrloc", 1, 0);
 	if (!bind_usrloc) {
 		LM_ERR("can't bind usrloc\n");
@@ -488,6 +472,46 @@ static int w_registered(struct sip_msg* _m, char* _d, char* _uri)
 	return registered(_m, (udomain_t*)_d, (uri.len>0)?&uri:NULL);
 }
 
+static int w_registered3(struct sip_msg* _m, char* _d, char* _uri, char* _flags)
+{
+	str uri = {0};
+	int flags = 0;
+	if(_uri!=NULL && (fixup_get_svalue(_m, (gparam_p)_uri, &uri)!=0 || uri.len<=0))
+	{
+		LM_ERR("invalid uri parameter\n");
+		return -1;
+	}
+	if(_flags!=NULL && (fixup_get_ivalue(_m, (fparam_t*)_flags, &flags)) < 0)
+	{
+		LM_ERR("invalid flags parameter\n");
+		return -1;
+	}
+	return registered3(_m, (udomain_t*)_d, (uri.len>0)?&uri:NULL, flags);
+}
+
+static int w_registered4(struct sip_msg* _m, char* _d, char* _uri, char* _flags, char* _actionflags)
+{
+	str uri = {0};
+	int flags = 0;
+	int actionflags = 0;
+	if(_uri!=NULL && (fixup_get_svalue(_m, (gparam_p)_uri, &uri)!=0 || uri.len<=0))
+	{
+		LM_ERR("invalid uri parameter\n");
+		return -1;
+	}
+	if(_flags!=NULL && (fixup_get_ivalue(_m, (fparam_t*)_flags, &flags)) < 0)
+	{
+		LM_ERR("invalid flags parameter\n");
+		return -1;
+	}
+	if(_actionflags!=NULL && (fixup_get_ivalue(_m, (fparam_t*)_actionflags, &actionflags)) < 0)
+	{
+		LM_ERR("invalid action flag parameter\n");
+		return -1;
+	}
+	return registered4(_m, (udomain_t*)_d, (uri.len>0)?&uri:NULL, flags, actionflags);
+}
+
 static int w_unregister(struct sip_msg* _m, char* _d, char* _uri)
 {
 	str uri = {0};
@@ -550,6 +574,19 @@ static int domain_uri_fixup(void** param, int param_no)
 	return 0;
 }
 
+static int registered_fixup(void** param, int param_no)
+{
+	if (param_no == 1) {
+		return domain_fixup(param, 1);
+	} else if (param_no == 2) {
+		return fixup_spve_null(param, 1);
+	} else if (param_no == 3) {
+		return fixup_igp_null(param, 1);
+	} else if (param_no == 4) {
+		return fixup_igp_null(param, 1);
+	}
+	return 0;
+}
 
 /*! \brief
  * Convert char* parameter to udomain_t* pointer

+ 4 - 2
modules/registrar/reg_mod.h

@@ -74,8 +74,10 @@ extern float def_q;
 
 extern unsigned short rcv_avp_type;
 extern int_str rcv_avp_name;
-extern unsigned short reg_callid_avp_type;
-extern int_str reg_callid_avp_name;
+
+extern str match_callid_name;
+extern str match_received_name;
+extern str match_contact_name;
 
 extern str rcv_param;
 extern int method_filtering;