Juha Heinanen wrote:
so i would suggest that if you want to include your
functionality into
lcr module, please do it using caching, because the idea is to deprecate
non-cached version of lcr implementation once we have had enough
practical experience with caching so that we are confident that there
are no bugs in it.
The patch already includes support for both the non-caching and the
caching mode (I've attached it again because last time I sent it off-list).
Andy
Index: modules/lcr/lcr_mod.c
===================================================================
RCS file: /cvsroot/openser/sip-server/modules/lcr/lcr_mod.c,v
retrieving revision 1.25
diff -u -r1.25 lcr_mod.c
--- modules/lcr/lcr_mod.c 21 Mar 2006 12:53:10 -0000 1.25
+++ modules/lcr/lcr_mod.c 27 Apr 2006 13:04:47 -0000
@@ -73,6 +73,7 @@
static void destroy(void); /* Module destroy function */
static int child_init(int rank); /* Per-child initialization function */
static int mod_init(void); /* Module initialization function */
+static int fixstring2int(void **param, int param_count); /* string to int fixup */
int reload_gws ( void );
@@ -221,9 +222,12 @@
* Module functions that are defined later
*/
int load_gws(struct sip_msg* _m, char* _s1, char* _s2);
+int load_gws_grp(struct sip_msg* _m, char* _s1, char* _s2);
int next_gw(struct sip_msg* _m, char* _s1, char* _s2);
int from_gw(struct sip_msg* _m, char* _s1, char* _s2);
+int from_gw_grp(struct sip_msg* _m, char* _s1, char* _s2);
int to_gw(struct sip_msg* _m, char* _s1, char* _s2);
+int to_gw_grp(struct sip_msg* _m, char* _s1, char* _s2);
int load_contacts (struct sip_msg*, char*, char*);
int next_contacts (struct sip_msg*, char*, char*);
@@ -232,9 +236,12 @@
*/
static cmd_export_t cmds[] = {
{"load_gws", load_gws, 0, 0, REQUEST_ROUTE | FAILURE_ROUTE},
+ {"load_gws", load_gws_grp, 1, fixstring2int, REQUEST_ROUTE |
FAILURE_ROUTE},
{"next_gw", next_gw, 0, 0, REQUEST_ROUTE | FAILURE_ROUTE},
{"from_gw", from_gw, 0, 0, REQUEST_ROUTE | FAILURE_ROUTE |
ONREPLY_ROUTE},
+ {"from_gw", from_gw_grp, 1, fixstring2int, REQUEST_ROUTE |
FAILURE_ROUTE | ONREPLY_ROUTE},
{"to_gw", to_gw, 0, 0, REQUEST_ROUTE | FAILURE_ROUTE},
+ {"to_gw", to_gw_grp, 1, fixstring2int, REQUEST_ROUTE |
FAILURE_ROUTE},
{"load_contacts", load_contacts, 0, 0, REQUEST_ROUTE},
{"next_contacts", next_contacts, 0, 0, REQUEST_ROUTE | FAILURE_ROUTE},
{0, 0, 0, 0, 0}
@@ -959,11 +966,10 @@
}
}
-
/*
* Load info of matching GWs from database to gw_uri AVPs
*/
-int load_gws(struct sip_msg* _m, char* _s1, char* _s2)
+static int do_load_gws(struct sip_msg* _m, int grp_id)
{
db_res_t* res;
db_row_t *row, *r;
@@ -1034,22 +1040,42 @@
}
if (db_mode == 0) {
- q_len = snprintf(query, MAX_QUERY_SIZE, "SELECT %.*s.%.*s, %.*s.%.*s, %.*s.%.*s,
%.*s.%.*s, %.*s.%.*s, %.*s.%.*s FROM %.*s, %.*s WHERE '%.*s' LIKE %.*s.%.*s AND
'%.*s' LIKE CONCAT(%.*s.%.*s, '%%') AND %.*s.%.*s = %.*s.%.*s ORDER BY
CHAR_LENGTH(%.*s.%.*s), %.*s.%.*s DESC, RAND()",
- gw_table.len, gw_table.s, ip_addr_col.len, ip_addr_col.s,
- gw_table.len, gw_table.s, port_col.len, port_col.s,
- gw_table.len, gw_table.s, uri_scheme_col.len, uri_scheme_col.s,
- gw_table.len, gw_table.s, transport_col.len, transport_col.s,
- gw_table.len, gw_table.s, strip_col.len, strip_col.s,
- gw_table.len, gw_table.s, prefix_col.len, prefix_col.s,
- gw_table.len, gw_table.s, lcr_table.len, lcr_table.s,
- from_uri.len, from_uri.s,
- lcr_table.len, lcr_table.s, from_uri_col.len, from_uri_col.s,
- ruri_user.len, ruri_user.s,
- lcr_table.len, lcr_table.s, prefix_col.len, prefix_col.s,
- lcr_table.len, lcr_table.s, grp_id_col.len, grp_id_col.s,
- gw_table.len, gw_table.s, grp_id_col.len, grp_id_col.s,
- lcr_table.len, lcr_table.s, prefix_col.len, prefix_col.s,
- lcr_table.len, lcr_table.s, priority_col.len, priority_col.s);
+ if(grp_id >= 0) {
+ q_len = snprintf(query, MAX_QUERY_SIZE, "SELECT %.*s.%.*s, %.*s.%.*s, %.*s.%.*s,
%.*s.%.*s, %.*s.%.*s, %.*s.%.*s FROM %.*s, %.*s WHERE %.*s.%.*s = %d AND '%.*s'
LIKE %.*s.%.*s AND '%.*s' LIKE CONCAT(%.*s.%.*s, '%%') AND %.*s.%.*s =
%.*s.%.*s ORDER BY CHAR_LENGTH(%.*s.%.*s), %.*s.%.*s DESC, RAND()",
+ gw_table.len, gw_table.s, ip_addr_col.len, ip_addr_col.s,
+ gw_table.len, gw_table.s, port_col.len, port_col.s,
+ gw_table.len, gw_table.s, uri_scheme_col.len, uri_scheme_col.s,
+ gw_table.len, gw_table.s, transport_col.len, transport_col.s,
+ gw_table.len, gw_table.s, strip_col.len, strip_col.s,
+ gw_table.len, gw_table.s, prefix_col.len, prefix_col.s,
+ gw_table.len, gw_table.s, lcr_table.len, lcr_table.s,
+ lcr_table.len, lcr_table.s, grp_id_col.len, grp_id_col.s, grp_id,
+ from_uri.len, from_uri.s,
+ lcr_table.len, lcr_table.s, from_uri_col.len, from_uri_col.s,
+ ruri_user.len, ruri_user.s,
+ lcr_table.len, lcr_table.s, prefix_col.len, prefix_col.s,
+ lcr_table.len, lcr_table.s, grp_id_col.len, grp_id_col.s,
+ gw_table.len, gw_table.s, grp_id_col.len, grp_id_col.s,
+ lcr_table.len, lcr_table.s, prefix_col.len, prefix_col.s,
+ lcr_table.len, lcr_table.s, priority_col.len, priority_col.s);
+ } else {
+ q_len = snprintf(query, MAX_QUERY_SIZE, "SELECT %.*s.%.*s, %.*s.%.*s, %.*s.%.*s,
%.*s.%.*s, %.*s.%.*s, %.*s.%.*s FROM %.*s, %.*s WHERE '%.*s' LIKE %.*s.%.*s AND
'%.*s' LIKE CONCAT(%.*s.%.*s, '%%') AND %.*s.%.*s = %.*s.%.*s ORDER BY
CHAR_LENGTH(%.*s.%.*s), %.*s.%.*s DESC, RAND()",
+ gw_table.len, gw_table.s, ip_addr_col.len, ip_addr_col.s,
+ gw_table.len, gw_table.s, port_col.len, port_col.s,
+ gw_table.len, gw_table.s, uri_scheme_col.len, uri_scheme_col.s,
+ gw_table.len, gw_table.s, transport_col.len, transport_col.s,
+ gw_table.len, gw_table.s, strip_col.len, strip_col.s,
+ gw_table.len, gw_table.s, prefix_col.len, prefix_col.s,
+ gw_table.len, gw_table.s, lcr_table.len, lcr_table.s,
+ from_uri.len, from_uri.s,
+ lcr_table.len, lcr_table.s, from_uri_col.len, from_uri_col.s,
+ ruri_user.len, ruri_user.s,
+ lcr_table.len, lcr_table.s, prefix_col.len, prefix_col.s,
+ lcr_table.len, lcr_table.s, grp_id_col.len, grp_id_col.s,
+ gw_table.len, gw_table.s, grp_id_col.len, grp_id_col.s,
+ lcr_table.len, lcr_table.s, prefix_col.len, prefix_col.s,
+ lcr_table.len, lcr_table.s, priority_col.len, priority_col.s);
+ }
if (q_len >= MAX_QUERY_SIZE) {
LOG(L_ERR, "load_gws(): Too long database query\n");
return -1;
@@ -1199,7 +1225,7 @@
if ((*gws)[j].ip_addr == 0) {
break;
}
- if (lcr_rec.grp_id == (*gws)[j].grp_id) {
+ if (lcr_rec.grp_id == (*gws)[j].grp_id && (grp_id < 0 ||
(*gws)[j].grp_id == grp_id)) {
/* 3. grp_id matching is done */
for (k = 0; k < gw_index; k++) {
if ((*gws)[j].ip_addr ==
@@ -1392,6 +1418,28 @@
}
}
+/*
+ * Load info of matching GWs from database to gw_uri AVPs
+ * taking into account the given group id.
+ */
+int load_gws_grp(struct sip_msg* _m, char* _s1, char* _s2)
+{
+ int grp_id;
+
+ grp_id = (int)(long)_s1;
+ return do_load_gws(_m, grp_id);
+}
+
+/*
+ * Load info of matching GWs from database to gw_uri AVPs
+ * ignoring the group id.
+ */
+int load_gws(struct sip_msg* _m, char* _s1, char* _s2)
+{
+ return do_load_gws(_m, -1);
+}
+
+
/*
* If called from request route block, rewrites scheme, host, port, and
@@ -1532,7 +1580,7 @@
/*
* Checks if request comes from a gateway
*/
-int from_gw(struct sip_msg* _m, char* _s1, char* _s2)
+static int do_from_gw(struct sip_msg* _m, int grp_id)
{
int i;
unsigned int src_addr;
@@ -1543,7 +1591,8 @@
if ((*gws)[i].ip_addr == 0) {
return -1;
}
- if ((*gws)[i].ip_addr == src_addr) {
+ if ((*gws)[i].ip_addr == src_addr &&
+ (grp_id < 0 || (*gws)[i].grp_id == grp_id)) {
return 1;
}
}
@@ -1553,9 +1602,31 @@
/*
+ * Checks if request comes from a gateway, taking
+ * into account the group id.
+ */
+int from_gw_grp(struct sip_msg* _m, char* _s1, char* _s2)
+{
+ int grp_id;
+
+ grp_id = (int)(long)_s1;
+ return do_from_gw(_m, grp_id);
+}
+
+/*
+ * Checks if request comes from a gateway, ignoring
+ * the group id.
+ */
+int from_gw(struct sip_msg* _m, char* _s1, char* _s2)
+{
+ return do_from_gw(_m, -1);
+}
+
+
+/*
* Checks if in-dialog request goes to gateway
*/
-int to_gw(struct sip_msg* _m, char* _s1, char* _s2)
+static int do_to_gw(struct sip_msg* _m, int grp_id)
{
char host[16];
struct in_addr addr;
@@ -1580,7 +1651,8 @@
if ((*gws)[i].ip_addr == 0) {
return -1;
}
- if ((*gws)[i].ip_addr == addr.s_addr) {
+ if ((*gws)[i].ip_addr == addr.s_addr &&
+ (grp_id < 0 || (*gws)[i].grp_id == grp_id)) {
return 1;
}
}
@@ -1589,6 +1661,29 @@
}
+/*
+ * Checks if in-dialog request goes to gateway, taking
+ * into account the group id.
+ */
+int to_gw_grp(struct sip_msg* _m, char* _s1, char* _s2)
+{
+ int grp_id;
+
+ grp_id = (int)(long)_s1;
+ return do_to_gw(_m, grp_id);
+}
+
+
+/*
+ * Checks if in-dialog request goes to gateway, ignoring
+ * the group id.
+ */
+int to_gw(struct sip_msg* _m, char* _s1, char* _s2)
+{
+ return do_to_gw(_m, -1);
+}
+
+
/*
* Frees contact list used by load_contacts function
*/
@@ -1825,3 +1920,28 @@
return 1;
}
+
+/*
+ * Convert string parameter to integer for functions that expect an integer.
+ * Taken from mediaproxy module.
+ */
+static int fixstring2int(void **param, int param_count)
+{
+ unsigned long number;
+ int err;
+
+ if (param_count == 1) {
+ number = str2s(*param, strlen(*param), &err);
+ if (err == 0) {
+ pkg_free(*param);
+ *param = (void*)number;
+ return 0;
+ } else {
+ LOG(L_ERR, "lcr/fixstring2int(): ERROR: bad number `%s'\n",
+ (char*)(*param));
+ return E_CFG;
+ }
+ }
+ return 0;
+}
+
Index: modules/lcr/doc/lcr_user.sgml
===================================================================
RCS file: /cvsroot/openser/sip-server/modules/lcr/doc/lcr_user.sgml,v
retrieving revision 1.9
diff -u -r1.9 lcr_user.sgml
--- modules/lcr/doc/lcr_user.sgml 11 Jan 2006 11:38:55 -0000 1.9
+++ modules/lcr/doc/lcr_user.sgml 27 Apr 2006 13:04:48 -0000
@@ -67,8 +67,7 @@
</para>
<para>
In addition to gw and lcr tables there is third table gw_grp that is
- used for administrative purposes only to associate names with gateway
- group ids.
+ used to associate names with gateway group ids.
</para>
</section>
@@ -594,6 +593,30 @@
</section>
<section>
<title>
+ <function moreinfo="none">load_gws(int)</function>
+ </title>
+ <para>
+ Loads URI schemes, addresses, ports, and transports of gateways
+ that match user part of Request-URI and the given group id to
+ gw_uri_avp AVPs. Returns 1 or -1 depending on success.
+ </para>
+ <para>
+ This function can be used from REQUEST_ROUTE.
+ </para>
+ <example>
+ <title><function>load_gws</function> usage</title>
+ <programlisting format="linespecific">
+...
+if (!load_gws("1")) {
+ sl_send_reply("500", "Server Internal Error - Cannot load gateways of
group 1");
+ break;
+};
+...
+</programlisting>
+ </example>
+ </section>
+ <section>
+ <title>
<function moreinfo="none">next_gw()</function>
</title>
<para>
@@ -666,6 +689,30 @@
</programlisting>
</example>
</section>
+ <section>
+ <title>
+ <function moreinfo="none">from_gw(int)</function>
+ </title>
+ <para>
+ Checks if request came from IP address of a gateway belonging
+ to the group with the given id.
+ </para>
+ <para>
+ This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
+ ONREPLY_ROUTE.
+ </para>
+ <example>
+ <title><function>from_gw</function> usage</title>
+ <programlisting format="linespecific">
+...
+if (from_gw("1")) {
+ ...
+ break;
+};
+...
+</programlisting>
+ </example>
+ </section>
<section>
<title>
<function moreinfo="none">to_gw()</function>
@@ -688,6 +735,29 @@
</programlisting>
</example>
</section>
+ <section>
+ <title>
+ <function moreinfo="none">to_gw(int)</function>
+ </title>
+ <para>
+ Checks if in-dialog request goes to a gateway belonging to
+ the group with the given id.
+ </para>
+ <para>
+ This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
+ </para>
+ <example>
+ <title><function>to_gw</function> usage</title>
+ <programlisting format = "linespecific">
+...
+if (to_gw("1")) {
+ ...
+ break;
+};
+...
+</programlisting>
+ </example>
+ </section>
<section>
<title>
<function moreinfo="none">load_contacts()</function>