<!-- Module User's Guide -->

<chapter>
    <title>&adminguide;</title>

    <section>
	<title>Overview</title>
	<para>A module which provides routing, balancing and blacklisting capabilities.</para>
	<para>
		The module provides routing, balancing and blacklisting capabilities.
		It reads routing entries from a database source or from a config file at OpenSER
		startup. It can uses one routing tree (for one carrier), or if needed for every user
		a different routing tree (unique for each carrier) for number prefix based routing.
		It supports several route tree domains,	e.g. for failback routes or different routing
		rules for VoIP and PSTN targets. 
	</para>
	<para>
		Based on the tree, the module decides which number prefixes are forwarded to which
		gateway. It can also distribute the traffic by ratio parameters. Furthermore, the
		requests can be distributed by a hash funcion to predictable destinations. The hash
		source is configurable, two different hash functions are available.
	</para>
	<para>
		This modules scales up to more than a few million users, and is able to handle
		more than several hundred thousand routing table entries. It should be able to handle
		more, but this is not that much tested at the moment. In load balancing scenarios the
		usage of the config file mode is recommended, to avoid the additional complexity that
		the database driven routing creates.
	</para>
	<para>
		Routing tables can be reloaded and edited (in config file mode) with the MI 
		interface, the config file is updated according the changes. This is not 
		implemented for the db interface, because its easier to do the changes 
		directly on the db. But the reload and dump functions works of course here 
		too.
	</para>
	<para>
		Some module functionality is not fully available in the config file mode, as
		it is not possible to specify all information that can be stored in the database
		tables in the config file. Further information about these limitations is given
		in later sections. For user based routing or LCR you should use the database mode.
	</para>
	<para>
		Basically this module could be used as an replacement for the lcr and the 
		dispatcher module, if you have certain performance, flexibility and/or 
		integration requirements that these modules don't handle properly. But for 
		small installations it probably make more sense to use the lcr and dispatcher
		module.
	</para>
	<para>
		If you want to use this module in failure routes, then you need to call
		<quote>append_branch()</quote> after rewriting the request URI in order to
		relay the message to the new target. Its also supportes the usage of database
		derived failure routing descisions with the carrierfailureroute table.
	</para>
    </section>
    <section>
	<title>Dependencies</title>
	<section>
	    <title>&openser; Modules</title>
	    <para>
		The following module must be loaded before this module:
	    	<itemizedlist>
		    <listitem>
			<para>
				<emphasis>a database module</emphasis>, when a database is used as configuration data source.
				Only SQL based databases are supported, as this module needs the capability to
				issue raw queries. Its not possible to use the dbtext or db_berkeley module at the moment.
			</para>
		    </listitem>
			<listitem>
			<para>
				The <emphasis>tm module</emphasis>, when you want to use the $T_reply_code pseudo-variable in
				the <quote>cr_next_domain</quote> function.
			</para>
			</listitem>
	    	</itemizedlist>
	    </para>
	</section>
	<section>
	    <title>External Libraries or Applications</title>
	    <para>
		The following libraries or applications must be installed before running
		&openser; with this module loaded:
		<itemizedlist>
		    <listitem>
			<para>
				<emphasis>libconfuse</emphasis>, a configuration file parser library.
				( http://www.nongnu.org/confuse/ )
			</para>
		    </listitem>
		</itemizedlist>
	    </para>
	</section>
    </section>
    <section>
	<title>Exported Parameters</title>
    <section>
	    <title><varname>db_url</varname> (string)</title>
	    <para>
		Url to the database containing the routing data.
	    </para>
	    <para>
		<emphasis>
		Default value is <quote>&defaultrodb;</quote>.
		</emphasis>
	    </para>
	    <example>
		<title>Set <varname>db_url</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("carrierroute", "db_url", "&exampledb;")
...
		</programlisting>
	    </example>
    </section>

    <section>
	    <title><varname>db_table</varname> (string)</title>
	    <para>
		    Name of the table where the routing data is stored.
	    </para>
	    <para>
		    <emphasis>
			    Default value is <quote>carrierroute</quote>.
		    </emphasis>
	    </para>
	    <example>
		    <title>Set <varname>db_table</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "db_table", "carrierroute")
...
		    </programlisting>
	    </example>
    </section>

    <section>
	    <title><varname>id_column</varname> (string)</title>
	    <para>
		    Name of the column containing the id identifier.
	    </para>
	    <para>
		    <emphasis>
			    Default value is <quote>id</quote>.
		    </emphasis>
	    </para>
	    <example>
		    <title>Set <varname>id_column</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "id_column", "id")
...
		    </programlisting>
	    </example>
    </section>

    <section>
	    <title><varname>carrier_column</varname> (string)</title>
	    <para>
		    Name of the column containing the  carrier id.
	    </para>
	    <para>
		    <emphasis>
			    Default value is <quote>carrier</quote>.
		    </emphasis>
	    </para>
	    <example>
		    <title>Set <varname>carrier_column</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "carrier_column", "carrier")
...
		    </programlisting>
	    </example>
    </section>

    <section>
	    <title><varname>scan_prefix_column</varname> (string)</title>
	    <para>
		    Name of column containing the scan prefixes. Scan prefixes define
		    the matching portion of a phone number, e.g. when we have the scan
		    prefixes 49721 and 49, the called number is 49721913740, it matches
		    49721, because the longest match is taken. If no prefix matches,
			the number is not routed. To prevent this, an empty prefix value
			of <quote></quote> could be added.
	    </para>
	    <para>
		    <emphasis>
			    Default value is <quote>scan_prefix</quote>.
		    </emphasis>
	    </para>
	    <example>
		    <title>Set <varname>scan_prefix_column</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "scan_prefix_column", "scan_prefix")
...
		    </programlisting>
	    </example>
    </section>

    <section>
	    <title><varname>domain_column</varname> (string)</title>
	    <para>
		    Name of column containing the rule domain. You can define several routing
		    domains to have different routing rules. Maybe you use domain 0 for normal
		    routing and domain 1 if domain 0 failed.
	    </para>
	    <para>
		    <emphasis>
			    Default value is <quote>domain</quote>.
		    </emphasis>
	    </para>
	    <example>
		    <title>Set <varname>domain_column</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "domain_column", "domain")
...
		    </programlisting>
	    </example>
    </section>

    <section>
      <title><varname>flags_column</varname> (string)</title>
			<para>
        Name of the column containing the flags.
	    </para>
	    <para>
		    <emphasis>
          Default value is <quote>flags</quote>.
		    </emphasis>
	    </para>
	    <example>
        <title>Set <varname>flags_column</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "flags_column", "flags")
...
		    </programlisting>
	    </example>
    </section>

    <section>
      <title><varname>mask_column</varname> (string)</title>
			<para>
        Name of the column containing the flags mask.
	    </para>
	    <para>
		    <emphasis>
          Default value is <quote>mask</quote>.
		    </emphasis>
	    </para>
	    <example>
        <title>Set <varname>mask_column</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "mask_column", "mask")
...
		    </programlisting>
	    </example>
    </section>

    <section>
	    <title><varname>prob_column</varname> (string)</title>
	    <para>
		    Name of column containing probability. The probability value is used to 
		    distribute the traffic between several gateways. Let's say 70 % of the 
		    traffic shall be routed to gateway A, the other 30 % shall be routed to 
		    gateway B, we define a rule for gateway A with a prob value of 0.7 and a 
		    rule for gateway B with a prob value of 0.3.
	    </para>
		<para>
			If all probabilities for a given prefix, tree and domain don't add to 100%,
			the prefix values will be adjusted according the given prob values. E.g. if
			three hosts with prob values of 0.5, 0.5 and 0.4 are defined, the resulting
			probabilities are 35.714, 35.714 and 28.571%. But its better to choose meaningful
			values in the first place because of clarity.
		</para>
	    <para>
		    <emphasis>
			    Default value is <quote>prob</quote>.
		    </emphasis>
	    </para>
	    <example>
		    <title>Set <varname>prob_column</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "prob_column", "prob")
...
		    </programlisting>
	    </example>
    </section>

    <section>
	    <title><varname>rewrite_host_column</varname> (string)</title>
	    <para>
		    Name of column containing rewrite host value. An empty field represents a
		    blacklist entry, anything else is put as domain part into the Request URI
		    of the SIP message.
	    </para>
	    <para>
		    <emphasis>
			    Default value is <quote>rewrite_host</quote>.
		    </emphasis>
	    </para>
	    <example>
		    <title>Set <varname>rewrite_host_column</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "rewrite_host_column", "rewrite_host")
...
		    </programlisting>
	    </example>
    </section>

    <section>
	    <title><varname>strip_column</varname> (string)</title>
	    <para>
		    Name of the column containing the number of digits to be stripped of the
		    userpart of an URI before prepending rewrite_prefix.
	    </para>
	    <para>
		    <emphasis>
			    Default value is <quote>strip</quote>.
		    </emphasis>
	    </para>
	    <example>
		    <title>Set <varname>strip_column</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "strip_column", "strip")
...
		    </programlisting>
	    </example>
    </section>

    <section>
	    <title><varname>comment_column</varname> (string)</title>
	    <para>
		    Name of the column containing an optional comment (useful in large routing tables)
		    The comment is also displayed by the fifo cmd "cr_dump_routes".
	    </para>
	    <para>
		    <emphasis>
			    Default value is <quote>description</quote>.
		    </emphasis>
	    </para>
	    <example>
		    <title>Set <varname>comment_column</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "comment_column", "description")
...
		    </programlisting>
	    </example>
    </section>

    <section>
	    <title><varname>carrier_table</varname> (string)</title>
	    <para>
		    The name of the table containing the existing carriers, consisting
			of the ids and corresponding names.
	    </para>
	    <para>
		    <emphasis>
			    Default value is <quote>route_tree</quote>.
		    </emphasis>
	    </para>
	    <example>
		    <title>Set <varname>carrier_table</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "carrier_table", "route_tree")
...
		    </programlisting>
	    </example>
    </section>

    <section>
	    <title><varname>rewrite_prefix_column</varname> (string)</title>
	    <para>
		    Name of column containing rewrite prefixes. Here you can define a rewrite
		    prefix for the localpart of the SIP URI.
	    </para>
	    <para>
		    <emphasis>
			    Default value is <quote>rewrite_prefix</quote>.
		    </emphasis>
	    </para>
	    <example>
		    <title>Set <varname>rewrite_prefix_column</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "rewrite_prefix_column", "rewrite_prefix")
...
		    </programlisting>
	    </example>
    </section>

    <section>
	    <title><varname>rewrite_suffix_column</varname> (string)</title>
	    <para>
		    Name of column containing rewrite suffixes. Here you can define a rewrite
		    suffix for the localpart of the SIP URI.
	    </para>
	    <para>
		    <emphasis>
			    Default value is <quote>rewrite_suffix</quote>.
		    </emphasis>
	    </para>
	    <example>
		    <title>Set <varname>rewrite_suffix_column</varname> parameter</title>
		    <programlisting format="linespecific">
			    ...
modparam("carrierroute", "rewrite_suffix_column", "rewrite_suffix")
			    ...
		    </programlisting>
	    </example>
    </section>

    <section>
	    <title><varname>carrier_id_col</varname> (string)</title>
	    <para>
		    The name of the column in the carrier table containing the carrier id.
	    </para>
	    <para>
		    <emphasis>
			    Default value is <quote>id</quote>.
		    </emphasis>
	    </para>
	    <example>
		    <title>Set <varname>id_col</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "carrier_id_col", "id")
...
		    </programlisting>
	    </example>
    </section>

    <section>
	    <title><varname>carrier_name_col</varname> (string)</title>
	    <para>
		    The name of the column in the carrier table containing the carrier name.
	    </para>
	    <para>
		    <emphasis>
			    Default value is <quote>carrier</quote>.
		    </emphasis>
	    </para>
	    <example>
		    <title>Set <varname>carrier_name_col</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "carrier_name_col", "carrier")
...
		    </programlisting>
	    </example>
    </section>

    <section>
	    <title><varname>subscriber_table</varname> (string)</title>
	    <para>
		    The name of the table containing the subscribers
	    </para>
	    <para>
		    <emphasis>
			    Default value is <quote>subscriber</quote>.
		    </emphasis>
	    </para>
	    <example>
		    <title>Set <varname>subscriber_table</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "subscriber_table", "subscriber")
...
		    </programlisting>
	    </example>
    </section>

    <section>
	    <title><varname>subscriber_user_col</varname> (string)</title>
	    <para>
		    The name of the column in the subscriber table containing the usernames.
	    </para>
	    <para>
		    <emphasis>
			    Default value is <quote>username</quote>.
		    </emphasis>
	    </para>
	    <example>
		    <title>Set <varname>subscriber_user_col</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "subscriber_user_col", "username")
...
		    </programlisting>
	    </example>
    </section>

    <section>
	    <title><varname>subscriber_domain_col</varname> (string)</title>
	    <para>
		    The name of the column in the subscriber table containing the domain of 
		    the subscriber.
	    </para>
	    <para>
		    <emphasis>
			    Default value is <quote>domain</quote>.
		    </emphasis>
	    </para>
	    <example>
		    <title>Set <varname>subscriber_domain_col</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "subscriber_domain_col", "domain")
...
		    </programlisting>
	    </example>
    </section>

    <section>
	    <title><varname>subscriber_carrier_col</varname> (string)</title>
	    <para>
		    The name of the column in the subscriber table containing the carrier id
		    of the subscriber.

	    </para>
	    <para>
		    <emphasis>
			    Default value is <quote>cr_preferred_carrier</quote>.
		    </emphasis>
	    </para>
	    <example>
		    <title>Set <varname>subscriber_carrier_col</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "subscriber_carrier_col", "cr_preferred_carrier")
...
		    </programlisting>
	    </example>
    </section>

    <section>
	    <title><varname>config_source</varname> (string)</title>
	    <para>
		    Specifies whether the module loads its config data from a file or from a
		    database. Possible values are file or db.
	    </para>
	    <para>
		    <emphasis>
			    Default value is <quote>file</quote>.
		    </emphasis>
	    </para>
	    <example>
		    <title>Set <varname>config_source</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "config_source", "file")
...
		    </programlisting>
	    </example>
    </section>

    <section>
	    <title><varname>config_file</varname> (string)</title>
	    <para>
		    Specifies the path to the config file.
	    </para>
	    <para>
		    <emphasis>
			    Default value is <quote>/etc/openser/carrierroute.conf</quote>.
		    </emphasis>
	    </para>
	    <example>
		    <title>Set <varname>config_file</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "config_file", "/etc/openser/carrierroute.conf")
...
		    </programlisting>
	    </example>
    </section>

    <section>
	    <title><varname>default_tree</varname> (string)</title>
	    <para>
		    The name of the carrier tree used per default (if the current
		    subscriber has no preferred tree)
	    </para>
	    <para>
		    <emphasis>
			    Default value is <quote>default</quote>.
		    </emphasis>
	    </para>
	    <example>
		    <title>Set <varname>default_tree</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "default_tree", "default")
...
		    </programlisting>
	    </example>
    </section>

    <section>
	    <title><varname>use_domain</varname> (int)</title>
	    <para>
		    When using tree lookup per user, this parameter specifies whether
		    to use the domain part for user matching or not.
	    </para>
	    <para>
		    <emphasis>
			    Default value is <quote>0</quote>.
		    </emphasis>
	    </para>
	    <example>
		    <title>Set <varname>use_domain</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "use_domain", 0)
...
		    </programlisting>
	    </example>
    </section>

    <section>
	    <title><varname>fallback_default</varname> (int)</title>
	    <para>
		    This parameter defines the behaviour when using user-based tree
		    lookup. If the user has a non-existing tree set and fallback_default
		    is set to 1, the default tree is used. Otherwise, cr_user_rewrite_uri
		    returns an error.
	    </para>
	    <para>
		    <emphasis>
			    Default value is <quote>1</quote>.
		    </emphasis>
	    </para>
	    <example>
		    <title>Set <varname>fallback_default</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "fallback_default", 1)
...
		    </programlisting>
	    </example>
    </section>

    <section>
      <title><varname>db_failure_table</varname> (string)</title>
			<para>
        Name of the table where the failure routing data is stored.
	    </para>
	    <para>
		    <emphasis>
          Default value is <quote>carrierfailureroute</quote>.
		    </emphasis>
	    </para>
	    <example>
        <title>Set <varname>db_failuretable</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "db_failuretable", "carrierfailureroute")
...
		    </programlisting>
	    </example>
    </section>

    <section>
      <title><varname>failure_id_column</varname> (string)</title>
			<para>
        Name of the column containing the id identifier.
	    </para>
	    <para>
		    <emphasis>
          Default value is <quote>id</quote>.
		    </emphasis>
	    </para>
	    <example>
        <title>Set <varname>failure_id_column</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "failure_id_column", "id")
...
		    </programlisting>
	    </example>
    </section>

    <section>
      <title><varname>failure_carrier_column</varname> (string)</title>
			<para>
        Name of the column containing the carrier id.
	    </para>
	    <para>
		    <emphasis>
          Default value is <quote>carrier</quote>.
		    </emphasis>
	    </para>
	    <example>
        <title>Set <varname>failure_carrier_column</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "failure_carrier_column", "carrier")
...
		    </programlisting>
	    </example>
    </section>

    <section>
      <title><varname>failure_scan_prefix_column</varname> (string)</title>
			<para>
        Name of column containing the scan prefixes. Scan prexies
        define the matching portion of a phone number, e.g. we have the
        scan prefixes 49721 and 49, the called number is 49721913740,
        it matches 49721, because the longest match is taken. If no
        prefix matches, the number is not failure routed. To prevent
        this, an empty prefix value of <quote></quote> could be added.
	    </para>
	    <para>
		    <emphasis>
          Default value is <quote>scan_prefix</quote>.
		    </emphasis>
	    </para>
	    <example>
        <title>Set <varname>failure_scan_prefix_column</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "failure_scan_prefix_column", "scan_prefix")
...
		    </programlisting>
	    </example>
    </section>

    <section>
      <title><varname>failure_domain_column</varname> (string)</title>
			<para>
        Name of column containing the rule domain. You can define
        several routing domains to have different routing rules. Maybe
        you use domain 0 for normal routing and domain 1 if domain 0
        failed.
	    </para>
	    <para>
		    <emphasis>
          Default value is <quote>domain</quote>.
		    </emphasis>
	    </para>
	    <example>
        <title>Set <varname>failure_domain_column</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "failure_domain_column", "domain")
...
		    </programlisting>
	    </example>
    </section>

    <section>
      <title><varname>failure_host_name_column</varname> (string)</title>
			<para>
        Name of the column containing the host name of the last routing
        destination.
	    </para>
	    <para>
		    <emphasis>
          Default value is <quote>host_name</quote>.
		    </emphasis>
	    </para>
	    <example>
        <title>Set <varname>failure_host_name_column</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "failure_host_name_column", "host_name")
...
		    </programlisting>
	    </example>
    </section>

    <section>
      <title><varname>failure_reply_code_column</varname> (string)</title>
			<para>
        Name of the column containing the reply code.
	    </para>
	    <para>
		    <emphasis>
          Default value is <quote>reply_code</quote>.
		    </emphasis>
	    </para>
	    <example>
        <title>Set <varname>failure_reply_code_column</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "failure_reply_code_column", "reply_code")
...
		    </programlisting>
	    </example>
    </section>

    <section>
      <title><varname>failure_flags_column</varname> (string)</title>
			<para>
        Name of the column containing the flags.
	    </para>
	    <para>
		    <emphasis>
          Default value is <quote>flags</quote>.
		    </emphasis>
	    </para>
	    <example>
        <title>Set <varname>failure_flags_column</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "failure_flags_column", "flags")
...
		    </programlisting>
	    </example>
    </section>

    <section>
      <title><varname>failure_mask_column</varname> (string)</title>
			<para>
        Name of the column containing the flags mask.
	    </para>
	    <para>
		    <emphasis>
          Default value is <quote>mask</quote>.
		    </emphasis>
	    </para>
	    <example>
        <title>Set <varname>failure_mask_column</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "failure_mask_column", "mask")
...
		    </programlisting>
	    </example>
    </section>

    <section>
      <title><varname>failure_next_domain_column</varname> (string)</title>
			<para>
        Name of the column containing the next routing domain.
	    </para>
	    <para>
		    <emphasis>
          Default value is <quote>next_domain</quote>.
		    </emphasis>
	    </para>
	    <example>
        <title>Set <varname>failure_next_domain_column</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "failure_next_domain_column", "next_domain")
...
		    </programlisting>
	    </example>
    </section>

    <section>
      <title><varname>failure_comment_column</varname> (string)</title>
			<para>
        Name of the column containing an optional comment.
	    </para>
	    <para>
		    <emphasis>
          Default value is <quote>description</quote>.
		    </emphasis>
	    </para>
	    <example>
        <title>Set <varname>failure_comment_column</varname> parameter</title>
		    <programlisting format="linespecific">
...
modparam("carrierroute", "failure_comment_column", "description")
...
		    </programlisting>
	    </example>
    </section>

</section>
    <section>
	<title>Exported Functions</title>
	<para>
    Previous versions of carriertree had some more function. All the
    old semantics can be achieved by using the few new functions
    like this:
	</para>

  <programlisting format="linespecific">
cr_rewrite_uri(domain, hash_source)
-> cr_route("default", domain, "$rU", "$rU", hash_source)

cr_prime_balance_uri(domain, hash_source)
-> cr_prime_route("default", domain, "$rU", "$rU", hash_source)

cr_rewrite_by_to(domain, hash_source)
-> cr_route("default", domain, "$tU", "$rU", hash_source)

cr_prime_balance_by_to(domain, hash_source)
-> cr_prime_route("default", domain, "$tU", "$rU", hash_source)

cr_rewrite_by_from(domain, hash_source)
-> cr_route("default", domain, "$fU", "$rU", hash_source)

cr_prime_balance_by_from(domain, hash_source)
-> cr_prime_route("default", domain, "$fU", "$rU", hash_source)

cr_user_rewrite_uri(uri, domain)
-> cr_user_carrier(user, domain, "$avp(tree_avp)")
-> cr_route("$avp(tree_avp)", domain, "$rU", "$rU", "call_id")

cr_tree_rewrite_uri(tree, domain)
-> cr_route(tree, domain, "$rU", "$rU", "call_id")
  </programlisting>
		
	<section>
	    <title>
		<function moreinfo="none">cr_user_carrier(user, domain, dstavp)</function>
	    </title>
	    <para>
      This function loads the carrier and stores it in an AVP.
      It cannot be used in the config file mode, as it needs a mapping of the
	  given user to a certain carrier. This mapping must be available in the
	  table that is specified in the <quote>subscriber_table</quote> variable.
	    </para>
	    <para>Meaning of the parameters is as follows:</para>
	    <itemizedlist>
        <listitem>
          <para><emphasis>user</emphasis> - Name of the user for the carrier tree lookup.
            Additional to a string any pseudo-variable could
            be used as input.
		      </para>
        </listitem>
        <listitem>
          <para><emphasis>domain</emphasis> - Name of the routing domain to be used.
            Additional to a string any pseudo-variable could
            be used as input.
		      </para>
        </listitem>
	      <listitem>
          <para><emphasis>dstavp</emphasis> - Name of the AVP where to store the carrier id.
		      </para>
        </listitem>
	    </itemizedlist>
	</section>
	<section>
	    <title>
		<function moreinfo="none">cr_route(carrier, domain, prefix_matching, rewrite_user, hash_source, dstavp)</function>
	    </title>
	    <para>
        This function searches for the longest match for the user given
        in prefix_matching at the given domain in the given carrier tree.
        The Request URI is rewritten using rewrite_user and the given
        hash source and algorithm. Returns -1 if there is no data found
        or an empty rewrite host on the longest match is found. Otherwise
				the rewritten host is stored in the given AVP (if obmitted, the
				host is not stored in an AVP).
        This function is only usable with rewrite_user and prefix_matching
        containing a valid numerical only string. It uses the standard crc32 algorithm
		to calculate the hash values.
	    </para>
	    <para>Meaning of the parameters is as follows:</para>
	    <itemizedlist>
        <listitem>
		      <para><emphasis>carrier</emphasis> - The routing tree to be used. Additional to a string
            any pseudo-variable could be used as input.
  		    </para>
        </listitem>
        <listitem>
		      <para><emphasis>domain</emphasis> - Name of the routing domain to be used.
            Additional to a string any pseudo-variable could
            be used as input.
  		    </para>
        </listitem>
        <listitem>
		      <para><emphasis>prefix_matching</emphasis> - User name to be used for prefix matching
            in the routing tree.
            Additional to a string any pseudo-variable could
            be used as input.
  		    </para>
        </listitem>
        <listitem>
		      <para><emphasis>rewrite_user</emphasis> - The user name to be used for applying the
            rewriting rule. Usually this is the user part of the request
            URI. Additional to a string any pseudo-variable could
            be used as input.
  		    </para>
        </listitem>
        <listitem>
		      <para><emphasis>hash_source</emphasis> - The hash values of the destination set must
            be a contiguous range starting at 1, limited by the
            configuration parameter max_targets. Possible values for
            hash_source are: call_id, from_uri, from_user, to_uri
            and to_user.
  		    </para>
        </listitem>
        <listitem>
		      <para><emphasis>dstavp</emphasis> - Name of the AVP where to store the rewritten host.
			This parameter is optional.
  		    </para>
        </listitem>
	    </itemizedlist>
	</section>
		<section>
	    <title>
		<function moreinfo="none">cr_prime_route(carrier, domain, prefix_matching, rewrite_user, hash_source, dstavp)</function>
	    </title>
	    <para>
        This function searches for the longest match for the user given
        in prefix_matching at the given domain in the given carrier tree.
        The Request URI is rewritten using rewrite_user and the given
        hash source and algorithm. Returns -1 if there is no data found
        or an empty rewrite host on the longest match is found. Otherwise
				the rewritten host is stored in the given AVP (if obmitted, the
				host is not stored in an AVP).
        This function is only usable with rewrite_user and prefix_matching
        containing a valid numerical only string. It uses the prime hash algorithm
		to calculate the hash values.
	    </para>
	    <para>Meaning of the parameters is as follows:</para>
	    <itemizedlist>
        <listitem>
		      <para><emphasis>carrier</emphasis> - The routing tree to be used. Additional to a string
            any pseudo-variable could be used as input.
  		    </para>
        </listitem>
        <listitem>
		      <para><emphasis>domain</emphasis> - Name of the routing domain to be used.
            Additional to a string any pseudo-variable could
            be used as input.
  		    </para>
        </listitem>
        <listitem>
		      <para><emphasis>prefix_matching</emphasis> - User name to be used for prefix matching
            in the routing tree.
            Additional to a string any pseudo-variable could
            be used as input.
  		    </para>
        </listitem>
        <listitem>
		      <para><emphasis>rewrite_user</emphasis> - The user name to be used for applying the
            rewriting rule. Usually this is the user part of the request
            URI. Additional to a string any pseudo-variable could
            be used as input.
  		    </para>
        </listitem>
        <listitem>
		      <para><emphasis>hash_source</emphasis> - The hash values of the destination set must
            be a contiguous range starting at 1, limited by the
            configuration parameter max_targets. Possible values for
            hash_source are: call_id, from_uri, from_user, to_uri
            and to_user.
  		    </para>
        </listitem>
        <listitem>
		      <para><emphasis>dstavp</emphasis> - Name of the AVP where to store the rewritten host.
			This parameter is optional.
  		    </para>
        </listitem>
	    </itemizedlist>
	</section>

	<section>
	    <title>
		<function moreinfo="none">cr_next_domain(carrier, domain, prefix_matching, host, reply_code, dstavp)</function>
	    </title>
	    <para>
        This function searches for the longest match for the user given
        in prefix_matching at the given domain in the given carrier
        failure tree. It tries to find a next domain matching the given
        host, reply_code and the message flags. The matching is done in this order:
        host, reply_code and then flags. The more wildcards in reply_code
        and the more bits used in flags, the lower the priority.
        Returns -1 if there is no data found or an empty next_domain on
        the longest match is found. Otherwise the next domain is stored
        in the given AVP.
        This function is only usable with prefix_matching containing a
        valid numerical only string.
	    </para>
	    <para>Meaning of the parameters is as follows:</para>
	    <itemizedlist>
        <listitem>
		      <para><emphasis>carrier</emphasis> - The routing tree to be used. Additional to a string
            any pseudo-variable could be used as input.
  		    </para>
        </listitem>
        <listitem>
		      <para><emphasis>domain</emphasis> - Name of the routing domain to be used.
            Additional to a string any pseudo-variable could
            be used as input.
  		    </para>
        </listitem>
        <listitem>
		      <para><emphasis>prefix_matching</emphasis> - User name to be used for prefix matching
            in the routing tree.
            Additional to a string any pseudo-variable could
            be used as input.
  		    </para>
        </listitem>
        <listitem>
		      <para><emphasis>host</emphasis> - The host name to be used for failure route rule
            matching. Usually this is the last tried routing destination
            stored in an avp by cr_route. Additional to a string any
            pseudo-variable could be used as input.
  		    </para>
        </listitem>
        <listitem>
		      <para><emphasis>reply_code</emphasis> - The reply code to be used for failure route rule
            matching. Additional to a string any pseudo-variable
            could be used as input.
  		    </para>
        </listitem>
        <listitem>
		      <para><emphasis>dstavp</emphasis> - Name of the AVP where to store the next routing domain.
  		    </para>
        </listitem>
	    </itemizedlist>
	</section>
    </section>

    <section>
	    <title><acronym>MI</acronym> Commands</title>
		<para>All commands understand the "-?" parameter to print a short help message.
		The options have to be quoted as one string to be passed to MI interface.
		Each option except host and new host can be wildcarded by * (but only * and not things
		like "-d prox*").</para>
	<section>
	    <title><function moreinfo="none">cr_reload_routes</function></title>
	    <para>
		This command reloads the routing data from the data source.
		</para>
		<para>
		Important: When new domains have been added, a restart of the server must be
		done, because the mapping of the ids used in the config script cannot be
		updated at runtime at the moment. So a reload could result in a wrong routing
		behaviour, because the ids used in the script could differ from the one used
		internally from the server. Modifying of already existing domains is no problem.
	    </para>
	</section>
	<section>
	    <title><function moreinfo="none">cr_dump_routes</function></title>
	    <para>
		This command prints the route rules on the command line.
	    </para>
	</section>
	<section>
	    <title><function moreinfo="none">cr_replace_host</function></title>
	    <para>
		This command can replace the rewrite_host of a route rule, it is only
		usable in file mode. Following options are possible:
	    </para>
	    <itemizedlist>
		<listitem>
		    <para><emphasis>-d</emphasis> - the domain containing the host</para>
	        </listitem>
		<listitem>
		    <para><emphasis>-p</emphasis> - the prefix containing the host</para>
		</listitem>
		<listitem>
		    <para><emphasis>-h</emphasis> - the host to be replaced</para>
		</listitem>
		<listitem>
			<para><emphasis>-t</emphasis> - the new host</para>
		</listitem>
	    </itemizedlist>
	    <para>Use the "null" prefix to specify an empty prefix.</para>
	    <example>
		<title><function>cr_replace_host</function> usage</title>
		<programlisting format="linespecific">
...
kamctl fifo cr_replace_host "-d proxy -p 49 -h proxy1 -t proxy2"
...
		</programlisting>
	    </example>
	</section>
	<section>
	    <title><function moreinfo="none">cr_deactivate_host</function></title>
	    <para>
		    This command deactivates the specified host, i.e. it sets its status to 0.
		    It is only usable in file mode. Following options are possible:
	    </para>
	    <itemizedlist>
		<listitem>
		    <para><emphasis>-d</emphasis> - the domain containing the host</para>
	        </listitem>
		<listitem>
		    <para><emphasis>-p</emphasis> - the prefix containing the host</para>
		</listitem>
		<listitem>
		    <para><emphasis>-h</emphasis> - the host to be deactivated</para>
		</listitem>
		<listitem>
			<para><emphasis>-t</emphasis> - the new host used as backup</para>
		</listitem>
	    </itemizedlist>
	    <para>When -t (new_host) is specified, the portion of traffic for the deactivated host
		is routed to the host given by -t. This is indicated in the output of dump_routes.
		The backup route is deactivated if the host is activated again.</para>
		<para>Use the "null" prefix to specify an empty prefix.</para>
	    <example>
		<title><function>cr_deactivate_host</function> usage</title>
		<programlisting format="linespecific">
...
kamctl fifo cr_deactivate_host "-d proxy -p 49 -h proxy1"
...
		</programlisting>
	    </example>
	</section>
	<section>
	    <title><function moreinfo="none">cr_activate_host</function></title>
	    <para>
		    This command activates the specified host, i.e. it sets its status to 1.
		    It is only usable in file mode. Following options are possible:
	    </para>
	    <itemizedlist>
		<listitem>
		    <para><emphasis>-d</emphasis> - the domain containing the host</para>
	        </listitem>
		<listitem>
		    <para><emphasis>-p</emphasis> - the prefix containing the host</para>
		</listitem>
		<listitem>
		    <para><emphasis>-h</emphasis> - the host to be activated</para>
		</listitem>
	    </itemizedlist>
	    <para>Use the "null" prefix to specify an empty prefix.</para>
	    <example>
		<title><function>cr_activate_host</function> usage</title>
		<programlisting format="linespecific">
...
kamctl fifo cr_activate_host "-d proxy -p 49 -h proxy1"
...
		</programlisting>
	    </example>
	</section>

	<section>
	    <title><function moreinfo="none">cr_add_host</function></title>
	    <para>
		    This command adds a route rule, it is only usable in file mode. Following options
		    are possible:
	    </para>
	    <itemizedlist>
		<listitem>
		    <para><emphasis>-d</emphasis> - the domain containing the host</para>
	        </listitem>
		<listitem>
		    <para><emphasis>-p</emphasis> - the prefix containing the host</para>
		</listitem>
		<listitem>
		    <para><emphasis>-h</emphasis> - the host to be added</para>
		</listitem>
		<listitem>
		    <para><emphasis>-w</emphasis> - the weight of the rule</para>
		</listitem>
		<listitem>
		    <para><emphasis>-P</emphasis> - an optional rewrite prefix</para>
		</listitem>
		<listitem>
		    <para><emphasis>-S</emphasis> - an optional rewrite suffix</para>
		</listitem>
		<listitem>
		    <para><emphasis>-i</emphasis> - an optional hash index</para>
		</listitem>
		<listitem>
		    <para><emphasis>-s</emphasis> - an optional strip value</para>
		</listitem>
	    </itemizedlist>
		<para>Use the "null" prefix to specify an empty prefix.</para>
	    <example>
		<title><function>cr_add_host</function> usage</title>
		<programlisting format="linespecific">
...
kamctl fifo cr_add_host "-d proxy -p 49 -h proxy1 -w 0.25"
...
		</programlisting>
	    </example>
	</section>

	<section>
	    <title><function moreinfo="none">cr_delete_host</function></title>
	    <para>
		    This command delete the specified hosts or rules, i.e. remove 
		    them from the route tree. It is only usable in file mode.
		    Following options are possible:
	    </para>
	    <itemizedlist>
		<listitem>
		    <para><emphasis>-d</emphasis> - the domain containing the host</para>
	        </listitem>
		<listitem>
		    <para><emphasis>-p</emphasis> - the prefix containing the host</para>
		</listitem>
		<listitem>
		    <para><emphasis>-h</emphasis> - the host to be added</para>
		</listitem>
		<listitem>
		    <para><emphasis>-w</emphasis> - the weight of the rule</para>
		</listitem>
		<listitem>
		    <para><emphasis>-P</emphasis> - an optional rewrite prefix</para>
		</listitem>
		<listitem>
		    <para><emphasis>-S</emphasis> - an optional rewrite suffix</para>
		</listitem>
		<listitem>
		    <para><emphasis>-i</emphasis> - an optional hash index</para>
		</listitem>
		<listitem>
		    <para><emphasis>-s</emphasis> - an optional strip value</para>
		</listitem>
	    </itemizedlist>
	    <para>Use the "null" prefix to specify an empty prefix.</para>
	    <example>
		<title><function>cr_delete_host</function> usage</title>
		<programlisting format="linespecific">
...
kamctl fifo cr_delete_host "-d proxy -p 49 -h proxy1 -w 0.25"
...
		</programlisting>
	    </example>
	</section>
    </section>
    <section>
	<title>Examples</title>
	<example>
		<title>Configuration example - Routing to default tree</title>
		<programlisting format="linespecific">
...
route {
	# route calls based on hash over callid
	# choose route domain 0 of the default carrier
	
	if(!cr_route("default", "0", "$rU", "$rU", "call_id", "crc32")){
		sl_send_reply("403", "Not allowed");
	} else {
		# In case of failure, re-route the request
		t_on_failure("1");
		# Relay the request to the gateway
		t_relay();
	}
}

failure_route[1] {
	# In case of failure, send it to an alternative route:
	if (t_check_status("408|5[0-9][0-9]")) {
		#choose route domain 1 of the default carrier
	if(!cr_route("default", "1", "$rU", "$rU", "call_id", "crc32")){
			t_reply("403", "Not allowed");
		} else {
			t_on_failure("2");
			t_relay();
		}
	}
}

failure_route[2] {
	# further processing
}

		</programlisting>
	</example>
	
	<example>
		<title>Configuration example - Routing to user tree</title>
		<programlisting format="linespecific">
...
route[1] {
	cr_user_carrier("$fU", "$fd", "$avp(s:carrier)");

	# just an example domain
	$avp(s:domain)="start";
	if (!cr_route("$avp(s:carrier)", "$avp(s:domain)", "$rU", "$rU",
			"call_id", "$avp(s:host)")) {
		xlog("L_ERR", "cr_route failed\n");
		exit;
	}
	t_on_failure("1");
		if (!t_relay()) {
			sl_reply_error();
	};
}

failure_route[1] {
	revert_uri();
	if (!cr_next_domain("$avp(s:carrier)", "$avp(s:domain)", "$rU",
			"$avp(s:host)", "$T_reply_code", "$avp(s:domain)")) {
		xlog("L_ERR", "cr_next_domain failed\n");
		exit;
	}
	if (!cr_route("$avp(s:carrier)", "$avp(s:domain)", "$rU", "$rU",
			"call_id", "$avp(s:host)")) {
		xlog("L_ERR", "cr_route failed\n");
		exit;
	}
	t_on_failure("1");
	append_branch();
	if (!t_relay()) {
		xlog("L_ERR", "t_relay failed\n");
		exit;
	};
}
...
		</programlisting>
	</example>

			
	<example>
		<title>Configuration example - module configuration</title>
		<para>
			The following config file specifies within the default carrier two
			domains, each with an prefix that contains two hosts. It is not possible
			to specify another carrier if you use the config file as data source.
		</para>
		<para>
			All traffic will be equally distributed between the hosts, both are
			active. The hash algorithm will working over the [1,2] set, messages
			hashed to one will go to the first host, the other to the second one.
			Don't use a hash index value of zero. If you ommit the hash completly,
			the module gives them a autogenerated value, starting from one.
		</para>
		<para>
			Use the <quote>NULL</quote> prefix to specify an empty prefix in the config file.
			Please note that the prefix is matched against the request URI (or to URI),
			if they did not contain a valid numerical URI, no match is possible. So
			for loadbalancing purposes e.g. for your registrars, you should use an empty
			prefix.
		</para>
		<programlisting format="linespecific">
...
domain proxy {
   prefix 49 {
     max_targets = 2
      target proxy1.localdomain {
         prob = 0.500000
         hash_index = 1
         status = 1
         comment = "test target 1"
      }
      target proxy2.localdomain {
         prob = 0.500000
         hash_index = 2
         status = 1
         comment = "test target 2"
      }
   }
}

domain register {
   prefix NULL {
     max_targets = 2
      target register1.localdomain {
         prob = 0.500000
         hash_index = 1
         status = 1
         comment = "test target 1"
      }
      target register2.localdomain {
         prob = 0.500000
         hash_index = 2
         status = 1
         comment = "test target 2"
      }
   }
}
...
		</programlisting>
	</example>
    </section>

    <section>
	<title>Installation and Running</title>
	<section>
		<title>Database setup</title>
		<para>
			Before running &openser; with carrierroute, you have to setup the database 
			table where the module will store the routing data. For that, if 
			the table was not created by the installation script or you choose
			to install everything by yourself you can use the carrierroute-create.sql
			<acronym>SQL</acronym> script in the database directories in the 
			openser/scripts folder as template. 
			Database and table name can be set with module parameters so they 
			can be changed, but the name of the columns must be as they are 
			in the <acronym>SQL</acronym> script.
			You can also find the complete database documentation on the
			project webpage, &openserdbdocs;.
			The flags and mask columns have the same function as in the
			carrierfailureroute table. A zero value in the flags and mask
			column means that any message flags will match this rule.
		</para>
		<para>
			For a minimal configuration either use the config file given above, or
			insert some data into the tables of the module.
		</para>
	<example>
		<title>Example database content - carrierroute table</title>
		<programlisting format="linespecific">
...
+----+---------+--------+-------------+-------+------+---------------+
| id | carrier | domain | scan_prefix | flags | prob | rewrite_host  |
+----+---------+--------+-------------+-------+------+---------------+
| 1  |       1 |      0 | 49          |     0 |  0.5 | de-1.carrier1 |
| 2  |       1 |      0 | 49          |     0 |  0.5 | de-2.carrier1 |
| 3  |       1 |      0 | 49          |    16 |    1 | de-3.carrier1 |
| 4  |       1 |      0 |             |     0 |    1 | gw.carrier1-1 |
| 5  |       1 |      1 | 49          |     0 |    1 | gw.carrier1-1 |
| 6  |       1 |      2 |             |     0 |    1 | gw.carrier1-2 |
| 7  |       1 |      3 |             |     0 |    1 | gw.carrier1-3 |
| 8  |       2 |      0 | 49          |     0 |  0.5 | de-1.carrier2 |
| 9  |       2 |      0 | 49          |     0 |  0.5 | de-2.carrier2 |
| 10 |       2 |      0 |             |     0 |    1 | gw.carrier2   |
| 11 |       2 |      1 | 49          |     0 |    1 | gw.carrier2   |
| 12 |       3 |  start | 49          |     0 |    1 | de-gw.default |
| 13 |       3 |  start |             |     0 |    1 | gw.default    |
+----+---------+--------+-------------+-------+------+---------------+
...
		</programlisting>
	</example>
		<para>
			This table contains three routes to two gateways for the <quote>49</quote> prefix,
			and a default route for other prefixes over carrier 2 and carrier 1. The
			gateways for the default carrier will be used for functions that don't
			support the user specific carrier lookup. The routing rules for carrier 1
			and carrier 2 for the <quote>49</quote> prefix contains a additional rule
			with the domain 1, that can be used for example as fallback if the gateways
			in domain 0 are not reachable. Two more fallback rules (domain 2 and 3) for 
			carrier 1 are also supplied to support the functionality of the carrierfailureroute
			table example that is provided in the next section. The usage of strings
			for the domains is also possible, for example at carrier 3.
		</para>
		<para>
			This table provides also a <quote>carrier1</quote> routing rule for the
			<quote>49</quote> prefix, that is only choosen if some message flags are set.
			If this flags are not set, the other two rules are used. The <quote>strip</quote>,
			<quote>mask</quote> and <quote>comment</quote> colums are omitted for brevity.
		</para>
	<example>
		<title>Example database content - simple carrierfailureroute table</title>
		<programlisting format="linespecific">
...
+----+---------+--------+---------------+------------+-------------+
| id | carrier | domain | host_name     | reply_code | next_domain |
+----+---------+--------+---------------+------------+-------------+
|  1 |       1 | 0      | gw.carrier1-2 | ...        | 3           |
|  2 |       1 | 0      | gw.carrier1-3 | ...        | 2           |
+----+---------+--------+---------------+------------+-------------+
...
</programlisting>
	</example>
		<para>
			This table contains two failure routes for the <quote>gw.carrier1-1</quote> and
			<quote>-2</quote> gateways. For any (failure) reply code the respective next
			domain is choosen. After that no more failure routes are available, an error will
			be returned from the <quote>cr_next_domain</quote> function. Not all table
			colums are show here for brevity.
		</para>
		<para>
			For each failure route domain and carrier that is added to the carrierfailureroute
			table there must be at least one corresponding entry in the carrierroute table,
			otherwise the module will not load the routing data.
		</para>

	<example>
		<title>Example database content - more complex carrierfailureroute table</title>
		<programlisting format="linespecific">
...
+----+---------+-----------+------------+--------+-----+-------------+
| id | domain  | host_name | reply_code | flags | mask | next_domain |
+----+---------+-----------+------------+-------+------+-------------+
|  1 |      99 |           | 408        |    16 |   16 |             |
|  2 |      99 | gw1       | 404        |     0 |    0 | 100         |
|  3 |      99 | gw2       | 50.        |     0 |    0 | 100         |
|  4 |      99 |           | 404        |  2048 | 2112 | asterisk-1  |
+----+---------+-----------+------------+-------+------+-------------+
...
</programlisting>
	</example>
		<para>
			This table contains four failure routes that shows the usage of more
			advanced features. The first route matches to a 408, and to some flag
			for example that indicates that ringing has happened. If this flag is set,
			there will be no further forwarding, because next_domain is empty. In the
			second and third routes are certain gateway errors matched, if this errors
			have occured, then the next domain will be choosen. The last route does
			forwarding according some flags, e.g. the customer came from a certain carrier,
			and has call-forwarding deactivated. In order to use the routing that is
			specified above, a matching carrierroute table must be provided, that holds
			domain entries for this routing rules. Not all table colums are show here for
			brevity.
		</para>

	<example>
		<title>Example database content - route_tree table</title>
		<programlisting format="linespecific">
...
+----+----------+
| id | carrier  |
+----+----------+
|  1 | carrier1 |
|  2 | carrier2 |
|  3 | default  |
+----+----------+
...
		</programlisting>
		</example>
		<para>
			This table contains the mapping of the carrier id to actual names.
		</para>
		<para>
			For a functional routing the <quote>cr_preferred_carrier</quote> column must
			be added to the subscriber table (or to the table and column that you specified
			as modul parameter) to choose the actual carrier for the users.
		</para>
	<example>
		<title>Necessary extensions for the user table</title>
		<para>Suggested changes:</para>
		<programlisting format="linespecific">
...
ALTER TABLE subscriber ADD cr_preferred_carrier int(10) default NULL; 
...
		</programlisting>
	</example>
		</section>
    </section>
</chapter>