Răsfoiți Sursa

modules_k/xcap_server: Enhanced org.oma.xcap-directory implementation

- Can now use a modparam to force the scheme in the listing URLs to a specific
  value (default is to work out based on whether the connection is TCP or TLS).
- Can now use a modparam to force the hostname in the listing URLs to a
  specific value (default is to work out based on the (mandatory) Host: header
  or destination IP address and port).
- Updated README
Peter Dunkley 13 ani în urmă
părinte
comite
8a00d03a93

+ 67 - 16
modules_k/xcap_server/README

@@ -30,6 +30,8 @@ Daniel-Constantin Mierla
               3.3. xcap_root (str)
               3.4. buf_size (int)
               3.5. xml_ns (str)
+              3.6. directory_scheme (int)
+              3.7. directory_hostname (str)
 
         4. Functions
 
@@ -46,12 +48,14 @@ Daniel-Constantin Mierla
    1.2. Set the “xcap_table” parameter
    1.3. Set url_match parameter
    1.4. Set the “buf_size” parameter
-   1.5. Set url_match parameter
-   1.6. xcaps_put usage
-   1.7. xcaps_get usage
-   1.8. xcaps_del usage
-   1.9. $xcapuri(...) PV
-   1.10. sample xcap server
+   1.5. Set xml_ns parameter
+   1.6. Set directory_scheme parameter
+   1.7. Set directory_hostname parameter
+   1.8. xcaps_put usage
+   1.9. xcaps_get usage
+   1.10. xcaps_del usage
+   1.11. $xcapuri(...) PV
+   1.12. sample xcap server
 
 Chapter 1. Admin Guide
 
@@ -70,6 +74,8 @@ Chapter 1. Admin Guide
         3.3. xcap_root (str)
         3.4. buf_size (int)
         3.5. xml_ns (str)
+        3.6. directory_scheme (int)
+        3.7. directory_hostname (str)
 
    4. Functions
 
@@ -133,12 +139,14 @@ Chapter 1. Admin Guide
    3.3. xcap_root (str)
    3.4. buf_size (int)
    3.5. xml_ns (str)
+   3.6. directory_scheme (int)
+   3.7. directory_hostname (str)
 
 3.1. db_url (string)
 
    Database URL.
 
-   Default value is “mysql://openser:openserrw@localhost/openser”.
+   Default value is “mysql://kamailio:kamailiorw@localhost/kamailio”.
 
    Example 1.1. Set the “db_url” parameter
 ...
@@ -186,7 +194,7 @@ modparam("xcap_server", "buf_size", 2048)
 
    Default value is 'null'.
 
-   Example 1.5. Set url_match parameter
+   Example 1.5. Set xml_ns parameter
 ...
 modparam("xcap_server", "xml_ns",
     "rl=urn:ietf:params:xml:ns:resource-lists")
@@ -194,6 +202,50 @@ modparam("xcap_server", "xml_ns",
     "my=urn:my:prefix")
 ...
 
+3.6. directory_scheme (int)
+
+   Allows the scheme used in org.openmobilealliance.xcap-directory
+   listings to be set to a specific value.
+
+   The URLs in an org.oma.xcap-directory listing must be be paths a client
+   can use to download the listed XCAP documents. In some cases (for
+   example, when the XCAP server is accessed using HTTP from an HTTP proxy
+   the client connectes to using HTTPS) the XCAP server may not be able to
+   automatically determine the correct scheme to use based on the HTTP
+   connection.
+     * -1 (default) - determine scheme automatically. HTTP for TCP
+       connections and HTTPS for TLS connections.
+     * 0 - use the HTTP scheme.
+     * 1 - use the HTTPS scheme.
+
+   Example 1.6. Set directory_scheme parameter
+...
+modparam("xcap_server", "directory_scheme", 0)
+...
+
+3.7. directory_hostname (str)
+
+   Allows the hostname (and port) used in
+   org.openmobilealliance.xcap-directory listings to be set to a specific
+   value.
+
+   The URLs in an org.oma.xcap-directory listing must be be paths a client
+   can use to download the listed XCAP documents. In some cases (for
+   example, when the XCAP server is accessed through a proxy that
+   re-writes headers, or a client is non-conformant and does not include a
+   Host: header) the XCAP server may not be able to automatically
+   determine the correct hostname to use.
+
+   When this parameter is not set the XCAP server will attempt to use the
+   contents of the (mandatory) Host: header. If the Host: header is not
+   present the XCAP server will use the IP address and port the XCAP
+   request was received on.
+
+   Example 1.7. Set directory_hostname parameter
+...
+modparam("xcap_server", "directory_hostname", "xcap.example.com")
+...
+
 4. Functions
 
    4.1. xcaps_put(uri, path, doc)
@@ -204,7 +256,7 @@ modparam("xcap_server", "xml_ns",
 
    Handle XCAP PUT command.
 
-   Example 1.6. xcaps_put usage
+   Example 1.8. xcaps_put usage
 ...
 event_route[xhttp:request] {
         if($hu=~"^/xcap-root/")
@@ -224,7 +276,7 @@ event_route[xhttp:request] {
 
    Handle XCAP GET command.
 
-   Example 1.7. xcaps_get usage
+   Example 1.9. xcaps_get usage
 ...
 event_route[xhttp:request] {
         if($hu=~"^/xcap-root/")
@@ -244,7 +296,7 @@ event_route[xhttp:request] {
 
    Handle XCAP DELETE command.
 
-   Example 1.8. xcaps_del usage
+   Example 1.10. xcaps_del usage
 ...
 event_route[xhttp:request] {
         if($hu=~"^/xcap-root/")
@@ -269,7 +321,7 @@ event_route[xhttp:request] {
    Exported pseudo-variables are documented at
    http://www.kamailio.org/dokuwiki/.
 
-   Example 1.9. $xcapuri(...) PV
+   Example 1.11. $xcapuri(...) PV
 ...
     $xcapuri(u=>data) = $hu;
     xdbg("SCRIPT: xcap service $xcapuri(u=>auid) for $xcapuri(u=>xuid)\n");
@@ -277,7 +329,7 @@ event_route[xhttp:request] {
 
 6. Simple XCAP Server Config
 
-   Example 1.10. sample xcap server
+   Example 1.12. sample xcap server
 ...
 tcp_accept_no_cl=yes
 ...
@@ -288,7 +340,7 @@ loadmodule "xcap_server.so"
 
 # ----- xcap_server params -----
 modparam("xcap_server", "db_url",
-        "mysql://openser:openserrw@localhost/openser")
+        "mysql://kamailio:kamailiorw@localhost/kamailio")
 
 ...
 
@@ -429,8 +481,7 @@ event_route[xhttp:request] {
     }
 
     # other http requests
-    xhttp_reply("200", "OK", "text/html",
-            "<html><body>OK: $si:$sp</body></html>");
+    xhttp_reply("404", "Not Found", "", "");
     exit;
 }
 ...

+ 72 - 3
modules_k/xcap_server/doc/xcap_server_admin.xml

@@ -203,7 +203,7 @@ modparam("xcap_server", "buf_size", 2048)
 		</emphasis>
 		</para>
 		<example>
-		<title>Set <varname>url_match</varname> parameter</title>
+		<title>Set <varname>xml_ns</varname> parameter</title>
 		<programlisting format="linespecific">
 ...
 modparam("xcap_server", "xml_ns",
@@ -211,6 +211,76 @@ modparam("xcap_server", "xml_ns",
 modparam("xcap_server", "xml_ns",
     "my=urn:my:prefix")
 ...
+</programlisting>
+		</example>
+	</section>
+	<section>
+		<title><varname>directory_scheme (int)</varname></title>
+		<para>
+			Allows the scheme used in
+			org.openmobilealliance.xcap-directory listings to be
+			set to a specific value.
+		</para>
+		<para>
+			The URLs in an org.oma.xcap-directory listing must be
+			be paths a client can use to download the listed XCAP
+			documents. In some cases (for example, when the XCAP
+			server is accessed using HTTP from an HTTP proxy the
+			client connectes to using HTTPS) the XCAP server may
+			not be able to automatically determine the correct
+			scheme to use based on the HTTP connection.
+		</para>
+		<itemizedlist>
+		<listitem><para>
+		<emphasis>-1 (default)</emphasis> - determine scheme
+		automatically.  HTTP for TCP connections and HTTPS for TLS
+		connections.
+		</para></listitem>
+		<listitem><para>
+		<emphasis>0</emphasis> - use the HTTP scheme.
+		</para></listitem>
+		<listitem><para>
+		<emphasis>1</emphasis> - use the HTTPS scheme. 
+		</para></listitem>
+		</itemizedlist>
+		<example>
+		<title>Set <varname>directory_scheme</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("xcap_server", "directory_scheme", 0)
+...
+</programlisting>
+		</example>
+	</section>
+	<section>
+		<title><varname>directory_hostname (str)</varname></title>
+		<para>
+			Allows the hostname (and port) used in
+			org.openmobilealliance.xcap-directory listings to be
+			set to a specific value.
+		</para>
+		<para>
+			The URLs in an org.oma.xcap-directory listing must be
+			be paths a client can use to download the listed XCAP
+			documents. In some cases (for example, when the XCAP
+			server is accessed through a proxy that re-writes
+			headers, or a client is non-conformant and does not
+			include a Host: header) the XCAP server may not be able
+			to automatically determine the correct hostname to use.
+		</para>
+		<para>
+			When this parameter is not set the XCAP server will
+			attempt to use the contents of the (mandatory) Host:
+			header. If the Host: header is not present the XCAP
+			server will use the IP address and port the XCAP
+			request was received on.
+		</para>
+		<example>
+		<title>Set <varname>directory_hostname</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("xcap_server", "directory_hostname", "xcap.example.com")
+...
 </programlisting>
 		</example>
 	</section>
@@ -480,8 +550,7 @@ event_route[xhttp:request] {
     }
 
     # other http requests
-    xhttp_reply("200", "OK", "text/html",
-            "&lt;html&gt;&lt;body>OK: $si:$sp&lt;/body&gt;&lt;/html&gt;");
+    xhttp_reply("404", "Not Found", "", "");
     exit;
 }
 ...

+ 93 - 33
modules_k/xcap_server/xcap_server.c

@@ -45,6 +45,7 @@
 #include "../../modules_k/xcap_client/xcap_callbacks.h"
 #include "../../modules/sl/sl.h"
 #include "../../lib/kcore/cmpapi.h"
+#include "../../ip_addr.h"
 
 #include "xcap_misc.h"
 
@@ -83,6 +84,8 @@ static str xcaps_db_url = str_init(DEFAULT_DB_URL);
 static int xcaps_init_time = 0;
 static int xcaps_etag_counter = 1;
 str xcaps_root = str_init("/xcap-root/");
+static int xcaps_directory_scheme = -1;
+static str xcaps_directory_hostname = {0, 0};
 
 static str xcaps_buf = {0, 8192};
 #define XCAPS_HDR_SIZE	128
@@ -113,11 +116,13 @@ static pv_export_t mod_pvs[] = {
 };
 
 static param_export_t params[] = {
-	{ "db_url",		STR_PARAM, &xcaps_db_url.s    },
-	{ "xcap_table",	STR_PARAM, &xcaps_db_table.s  },
-	{ "xcap_root",	STR_PARAM, &xcaps_root.s  },
-	{ "buf_size",	INT_PARAM, &xcaps_buf.len  },
-	{ "xml_ns",     STR_PARAM|USE_FUNC_PARAM, (void*)xcaps_xpath_ns_param },
+	{ "db_url",             STR_PARAM, &xcaps_db_url.s    },
+	{ "xcap_table",         STR_PARAM, &xcaps_db_table.s  },
+	{ "xcap_root",          STR_PARAM, &xcaps_root.s  },
+	{ "buf_size",           INT_PARAM, &xcaps_buf.len  },
+	{ "xml_ns",             STR_PARAM|USE_FUNC_PARAM, (void*)xcaps_xpath_ns_param },
+	{ "directory_scheme",   INT_PARAM, &xcaps_directory_scheme },
+	{ "directory_hostname", STR_PARAM, &xcaps_directory_hostname.s },
 	{ 0, 0, 0 }
 };
 
@@ -157,6 +162,15 @@ static int mod_init(void)
 	xcaps_db_url.len   = (xcaps_db_url.s) ? strlen(xcaps_db_url.s) : 0;
 	xcaps_db_table.len = (xcaps_db_table.s) ? strlen(xcaps_db_table.s) : 0;
 	xcaps_root.len     = (xcaps_root.s) ? strlen(xcaps_root.s) : 0;
+	xcaps_directory_hostname.len
+			   = xcaps_directory_hostname.s
+				? strlen(xcaps_directory_hostname.s) : 0;
+
+	if (xcaps_directory_scheme < -1 || xcaps_directory_scheme > 1)
+	{
+		LM_ERR("invalid xcaps_directory_scheme\n");
+		return -1;
+	}
 	
 	if(xcaps_buf.len<=0)
 	{
@@ -915,28 +929,13 @@ static int xcaps_get_directory(struct sip_msg *msg, str *user, str *domain, str
 	if (db_res == NULL)
 		goto error;
 
-	if (parse_headers(msg, HDR_EOH_F, 0) < 0)
-	{
-		LM_ERR("error parsing headers\n");
-		goto error;
-	}
-
-	while (hdr != NULL)
-	{
-		if (cmp_hdrname_strzn(&hdr->name, "Host", 4) == 0)
-		{
-			server_name = hdr->body;
-			break;
-		}
-		hdr = hdr->next;
-	}
-
 	directory->s = xcaps_buf.s;
 	directory->len = 0;
 
-	directory->len += snprintf(directory->s + directory->len, xcaps_buf.len - directory->len,
-		"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
-		"<xcap-directory xmlns=\"urn:oma:xml:xdm:xcap-directory\">\r\n");
+	directory->len += snprintf(directory->s + directory->len,
+					xcaps_buf.len - directory->len,
+			"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
+			"<xcap-directory xmlns=\"urn:oma:xml:xdm:xcap-directory\">\r\n");
 
 	rows = RES_ROWS(db_res);
 	for (i = 0; i < RES_ROW_N(db_res); i++)
@@ -947,8 +946,9 @@ static int xcaps_get_directory(struct sip_msg *msg, str *user, str *domain, str
 		{
 			if (cur_type != 0)
 			{
-				directory->len += snprintf(directory->s + directory->len, xcaps_buf.len - directory->len,
-		"</folder>\r\n");
+				directory->len += snprintf(directory->s + directory->len,
+								xcaps_buf.len - directory->len,
+			"</folder>\r\n");
 			}
 			cur_type = VAL_INT(&values[doc_type_col]);
 
@@ -969,15 +969,75 @@ static int xcaps_get_directory(struct sip_msg *msg, str *user, str *domain, str
 				goto error;
 			}
 
-			directory->len += snprintf(directory->s + directory->len, xcaps_buf.len - directory->len,
-		"<folder auid=\"%.*s\">\r\n",
-						auid_string.len, auid_string.s);
+			directory->len += snprintf(directory->s + directory->len,
+							xcaps_buf.len - directory->len,
+			"<folder auid=\"%.*s\">\r\n",
+							auid_string.len, auid_string.s);
 		}
 
-		directory->len += snprintf(directory->s + directory->len, xcaps_buf.len - directory->len,
-		"<entry uri=\"%s%.*s%s\" etag=\"%s\"/>\r\n",
-					server_name.len ? (msg->rcv.proto == PROTO_TLS ? "https://" : "http://") : "",
-					server_name.len, server_name.len ? server_name.s : "",
+		switch(xcaps_directory_scheme)
+		{
+		case -1:
+			directory->len += snprintf(directory->s + directory->len,
+							xcaps_buf.len - directory->len,
+			"<entry uri=\"%s://", msg->rcv.proto == PROTO_TLS ? "https" : "http");
+			break;
+		case 0:
+			directory->len += snprintf(directory->s + directory->len,
+							xcaps_buf.len - directory->len,
+			"<entry uri=\"http://");
+			break;
+		case 1:
+			directory->len += snprintf(directory->s + directory->len,
+							xcaps_buf.len - directory->len,
+			"<entry uri=\"https://");
+			break;
+		}
+
+		if (xcaps_directory_hostname.len > 0)
+		{
+			directory->len += snprintf(directory->s + directory->len,
+						xcaps_buf.len - directory->len,
+			"%.*s", xcaps_directory_hostname.len, xcaps_directory_hostname.s);
+		}
+		else
+		{
+			if (parse_headers(msg, HDR_EOH_F, 0) < 0)
+			{
+				LM_ERR("error parsing headers\n");
+				goto error;
+			}
+
+			while (hdr != NULL)
+			{
+				if (cmp_hdrname_strzn(&hdr->name, "Host", 4) == 0)
+				{
+					server_name = hdr->body;
+					break;
+				}
+				hdr = hdr->next;
+			}
+
+			if (server_name.len > 0)
+			{
+				directory->len += snprintf(directory->s + directory->len,
+							xcaps_buf.len - directory->len,
+			"%.*s", server_name.len, server_name.s);
+			}
+			else
+			{
+				server_name.s = pkg_malloc(IP6_MAX_STR_SIZE + 6);
+				server_name.len = ip_addr2sbuf(&msg->rcv.dst_ip, server_name.s, IP6_MAX_STR_SIZE);
+				directory->len += snprintf(directory->s + directory->len,
+							xcaps_buf.len - directory->len,
+			"%.*s:%d", server_name.len, server_name.s, msg->rcv.dst_port);
+				pkg_free(server_name.s);
+			}
+		}
+
+		directory->len += snprintf(directory->s + directory->len,
+						xcaps_buf.len - directory->len,
+		"%s\" etag=\"%s\"/>\r\n",
 					VAL_STRING(&values[doc_uri_col]),
 					VAL_STRING(&values[etag_col]));
 	}