Ver Fonte

Merge branch 'master' of ssh://git.sip-router.org/sip-router

Jason Penton há 12 anos atrás
pai
commit
5fc244a81f

+ 0 - 2
modules/rtpproxy/rtpproxy.c

@@ -1464,8 +1464,6 @@ insert_candidates(struct sip_msg *msg, char *where, str *ip, unsigned int port,
     append_str(at, rtp_port.s, rtp_port.len);
     append_str(at, rtp_port.s, rtp_port.len);
     append_str(at, " typ relay\r\n", 12);
     append_str(at, " typ relay\r\n", 12);
 
 
-    LM_DBG("inserting '%.*s'\n", at - buf, buf);
-
     anchor = anchor_lump(msg, where - msg->buf, 0, 0);
     anchor = anchor_lump(msg, where - msg->buf, 0, 0);
     if (anchor == 0) {
     if (anchor == 0) {
 	LOG(L_ERR, "insert_candidates: can't get anchor\n");
 	LOG(L_ERR, "insert_candidates: can't get anchor\n");

+ 2 - 1
modules_k/outbound/README

@@ -205,7 +205,8 @@ failure_route[REPLY_OUTBOUND] {
 ...
 ...
 loadmodule "registrar.so"
 loadmodule "registrar.so"
 ...
 ...
-TBD
+modparam("registrar", "outbound_mode", 2)
+### TBD
 ...
 ...
 
 
 2. Dependencies
 2. Dependencies

+ 2 - 1
modules_k/outbound/doc/outbound_admin.xml

@@ -163,7 +163,8 @@ failure_route[REPLY_OUTBOUND] {
 ...
 ...
 loadmodule "registrar.so"
 loadmodule "registrar.so"
 ...
 ...
-TBD
+modparam("registrar", "outbound_mode", 2)
+### TBD
 ...
 ...
 ]]></programlisting>
 ]]></programlisting>
 	</example>
 	</example>

+ 120 - 58
modules_k/registrar/README

@@ -16,7 +16,7 @@ Edited by
 
 
 Bogdan-Andre Iancu
 Bogdan-Andre Iancu
 
 
-   Copyright © 2003 FhG FOKUS
+   Copyright © 2003 FhG FOKUS
      __________________________________________________________________
      __________________________________________________________________
 
 
    Table of Contents
    Table of Contents
@@ -58,6 +58,8 @@ Bogdan-Andre Iancu
               3.21. xavp_cfg (string)
               3.21. xavp_cfg (string)
               3.22. xavp_rcd (string)
               3.22. xavp_rcd (string)
               3.23. gruu_enabled (integer)
               3.23. gruu_enabled (integer)
+              3.24. outbound_mode (integer)
+              3.25. flow_timer (integer)
 
 
         4. Functions
         4. Functions
 
 
@@ -108,15 +110,17 @@ Bogdan-Andre Iancu
    1.20. Set xavp_cfg parameter
    1.20. Set xavp_cfg parameter
    1.21. Set xavp_rcd parameter
    1.21. Set xavp_rcd parameter
    1.22. Set gruu_enabled parameter
    1.22. Set gruu_enabled parameter
-   1.23. save usage
-   1.24. lookup usage
-   1.25. lookup_branches usage
-   1.26. registered usage
-   1.27. add_sock_hdr usage
-   1.28. unregister usage
-   1.29. reg_fetch_contacts usage
-   1.30. reg_free_contacts usage
-   1.31. $ulc(name) usage
+   1.23. Set outbound_mode parameter
+   1.24. Set flow_timer parameter
+   1.25. save usage
+   1.26. lookup usage
+   1.27. lookup_branches usage
+   1.28. registered usage
+   1.29. add_sock_hdr usage
+   1.30. unregister usage
+   1.31. reg_fetch_contacts usage
+   1.32. reg_free_contacts usage
+   1.33. $ulc(name) usage
 
 
 Chapter 1. Admin Guide
 Chapter 1. Admin Guide
 
 
@@ -157,6 +161,8 @@ Chapter 1. Admin Guide
         3.21. xavp_cfg (string)
         3.21. xavp_cfg (string)
         3.22. xavp_rcd (string)
         3.22. xavp_rcd (string)
         3.23. gruu_enabled (integer)
         3.23. gruu_enabled (integer)
+        3.24. outbound_mode (integer)
+        3.25. flow_timer (integer)
 
 
    4. Functions
    4. Functions
 
 
@@ -201,8 +207,8 @@ Chapter 1. Admin Guide
      * off - stores the value of the Path headers into usrloc without
      * off - stores the value of the Path headers into usrloc without
        passing it back to the UAC in the reply.
        passing it back to the UAC in the reply.
      * lazy - stores the Path header and passes it back to the UAC if
      * lazy - stores the Path header and passes it back to the UAC if
-       Path-support is indicated by the "path" param in the Supported HF.
-     * strict - rejects the registration with "420 Bad Extension" if
+       Path-support is indicated by the “path� param in the Supported HF.
+     * strict - rejects the registration with “420 Bad Extension� if
        there's a Path header but no support for it is indicated by the
        there's a Path header but no support for it is indicated by the
        UAC. Otherwise it's stored and passed back to the UAC.
        UAC. Otherwise it's stored and passed back to the UAC.
 
 
@@ -214,8 +220,8 @@ Chapter 1. Admin Guide
    client's NAT).
    client's NAT).
 
 
    The whole process is transparent to the user, so no config changes are
    The whole process is transparent to the user, so no config changes are
-   required beside setting the registrar-parameters "use_path" and
-   "path_mode".
+   required beside setting the registrar-parameters “use_path� and
+   “path_mode�.
 
 
 1.2. GRUU Support
 1.2. GRUU Support
 
 
@@ -270,6 +276,8 @@ Chapter 1. Admin Guide
    3.21. xavp_cfg (string)
    3.21. xavp_cfg (string)
    3.22. xavp_rcd (string)
    3.22. xavp_rcd (string)
    3.23. gruu_enabled (integer)
    3.23. gruu_enabled (integer)
+   3.24. outbound_mode (integer)
+   3.25. flow_timer (integer)
 
 
 3.1. default_expires (integer)
 3.1. default_expires (integer)
 
 
@@ -277,7 +285,7 @@ Chapter 1. Admin Guide
    contact parameters, this value will be used for newly created usrloc
    contact parameters, this value will be used for newly created usrloc
    records. The parameter contains number of second to expire (for example
    records. The parameter contains number of second to expire (for example
    use 3600 for one hour). If it is set to a lower value than the
    use 3600 for one hour). If it is set to a lower value than the
-   "min_expires" parameter then it will be ignored. This parameter can be
+   “min_expires� parameter then it will be ignored. This parameter can be
    modified via ser config framework. A random value in a specific
    modified via ser config framework. A random value in a specific
    interval can be selected by using the default_expires_range parameter
    interval can be selected by using the default_expires_range parameter
 
 
@@ -291,9 +299,9 @@ modparam("registrar", "default_expires", 1800)
 3.2. default_expires_range (integer)
 3.2. default_expires_range (integer)
 
 
    This parameter specifies that the expiry used for newly created usrloc
    This parameter specifies that the expiry used for newly created usrloc
-   records are not fixed(when "default_expires" applies), but a random
-   value in the interval "[default_expires-default_expires_range%,
-   default_expires+default_expires_range%]". The value is between 0 and
+   records are not fixed(when “default_expires� applies), but a random
+   value in the interval “[default_expires-default_expires_range%,
+   default_expires+default_expires_range%]�. The value is between 0 and
    100 and represent the maximim percentage from default_expires that will
    100 and represent the maximim percentage from default_expires that will
    be substracted or added when computing the value. Default in 0, meaning
    be substracted or added when computing the value. Default in 0, meaning
    default_expires is left unmodified. This parameter can be modified via
    default_expires is left unmodified. This parameter can be modified via
@@ -512,7 +520,7 @@ modparam("registrar", "method_filtering", 1)
 3.17. use_path (integer)
 3.17. use_path (integer)
 
 
    If set to 1, the Path header is handled according to the parameter This
    If set to 1, the Path header is handled according to the parameter This
-   parameter can be modified via ser config framework. "path_mode".
+   parameter can be modified via ser config framework. “path_mode�.
 
 
    Default value is 0 (disabled).
    Default value is 0 (disabled).
 
 
@@ -529,12 +537,12 @@ modparam("registrar", "use_path", 1)
        the reply.
        the reply.
      * 1 - The Path header is saved into usrloc, but is only included in
      * 1 - The Path header is saved into usrloc, but is only included in
        the reply if path support is indicated in the registration request
        the reply if path support is indicated in the registration request
-       by the "path" option of the "Supported" header.
+       by the “path� option of the “Supported� header.
      * 2 - The path header is only saved into usrloc, if path support is
      * 2 - The path header is only saved into usrloc, if path support is
-       indicated in the registration request by the "path" option of the
-       "Supported" header. If no path support is indicated, the request is
-       rejected with "420 - Bad Extension" and the header "Unsupported:
-       path" is included in the reply along with the received "Path"
+       indicated in the registration request by the “path� option of the
+       “Supported� header. If no path support is indicated, the request is
+       rejected with “420 - Bad Extension� and the header “Unsupported:
+       path� is included in the reply along with the received “Path�
        header. This mode is the one recommended by RFC-3327.
        header. This mode is the one recommended by RFC-3327.
 
 
    Default value is 2.
    Default value is 2.
@@ -546,10 +554,10 @@ modparam("registrar", "path_mode", 0)
 
 
 3.19. path_use_received (integer)
 3.19. path_use_received (integer)
 
 
-   If set to 1, the "received" parameter of the first Path URI of a
+   If set to 1, the “received� parameter of the first Path URI of a
    registration is set as received-uri and the NAT branch flag is set for
    registration is set as received-uri and the NAT branch flag is set for
    this contact. This is useful if the registrar is placed behind a SIP
    this contact. This is useful if the registrar is placed behind a SIP
-   loadbalancer, which passes the nat'ed UAC address as "received"
+   loadbalancer, which passes the nat'ed UAC address as “received�
    parameter in it's Path uri.
    parameter in it's Path uri.
 
 
    Default value is 0 (disabled).
    Default value is 0 (disabled).
@@ -610,7 +618,7 @@ modparam("registrar", "xavp_cfg", "ulrcd")
 
 
 3.23. gruu_enabled (integer)
 3.23. gruu_enabled (integer)
 
 
-   If set to 1 and GRUU "+sip.instance" parameter to Contact header of
+   If set to 1 and GRUU “+sip.instance� parameter to Contact header of
    REGISTER is present, then the value of the parameter is saved to
    REGISTER is present, then the value of the parameter is saved to
    location and pub-gruu and temp-gruu addresses are generated.
    location and pub-gruu and temp-gruu addresses are generated.
 
 
@@ -623,6 +631,60 @@ modparam("registrar", "xavp_cfg", "ulrcd")
 modparam("registrar", "gruu_enabled", 0)
 modparam("registrar", "gruu_enabled", 0)
 ...
 ...
 
 
+3.24. outbound_mode (integer)
+
+   If set to 0 then this module will accept REGISTER requests that do not
+   contain a Supported: header with the outbound options-tag. The 200 OK
+   response to REGISTER requests that this module generates will not
+   contain Require: or Supported: headers with the outbound options tag.
+
+   If set to 1 then this module will accept REGISTER requests that do not
+   contain a Supported: header with the outbound options-tag. The 200 OK
+   response to REGISTER requests that this module generates will contain a
+   Supported: header with the outbound options tag.
+
+   If set to 2 then this module will reject REGISTER requests that do not
+   contain a Supported: header with the outbound options-tag. The 200 OK
+   response to REGISTER requests that this module generates will contain
+   Require: and Supported: headers with the outbound options tag.
+
+   Set this parameter to 2 if you are using SIP Outbound (RFC 5626) and
+   want your Edge Proxy to insert a Flow-Timer: header into the 200 OK
+   response to REGISTERs (as per RFC 5626 section 5.4).
+
+   Default value is 0.
+
+   Example 1.23. Set outbound_mode parameter
+...
+modparam("registrar", "outbound_mode", 2)
+...
+
+3.25. flow_timer (integer)
+
+   If set to 0 then this module will not add a Flow-Timer: header to 200
+   OK responses to REGISTER requests.
+
+   If set to > 0 then this module will add a Flow-Timer: header containing
+   this value to 200 OK responses to REGISTER requests. This parameter may
+   only be set to a value > 0 when outbound_mode is set to 2.
+
+   When set to a value > 0 this parameter should be set to slightly less
+   than the connection timeout value between the UAC and the network (this
+   corresponds to the core tcp_connection_lifetime option and websocket
+   keepalive_timeout modparam). This parameter is most useful when you
+   have a single edge proxy/registrar. If you are using a separate SIP
+   Outbound Edge Proxy you should consider leaving this parameter set to 0
+   and adding the Flow-Timer: header on the Edge Proxy (as this allows you
+   to keep all of the timer values for a specific flow in one
+   configuration - that of the Edge Proxy).
+
+   Default value is 0.
+
+   Example 1.24. Set flow_timer parameter
+...
+modparam("registrar", "flow_timer", 25)
+...
+
 4. Functions
 4. Functions
 
 
    4.1. save(domain, [, flags [, uri]])
    4.1. save(domain, [, flags [, uri]])
@@ -634,7 +696,7 @@ modparam("registrar", "gruu_enabled", 0)
    4.7. reg_fetch_contacts(domain, uri, profile)
    4.7. reg_fetch_contacts(domain, uri, profile)
    4.8. reg_free_contacts(profile)
    4.8. reg_free_contacts(profile)
 
 
-4.1. save(domain, [, flags [, uri]])
+4.1.  save(domain, [, flags [, uri]])
 
 
    The function processes a REGISTER message. It can add, remove or modify
    The function processes a REGISTER message. It can add, remove or modify
    usrloc records depending on Contact and Expires HFs in the REGISTER
    usrloc records depending on Contact and Expires HFs in the REGISTER
@@ -671,14 +733,14 @@ modparam("registrar", "gruu_enabled", 0)
 
 
    This function can be used from REQUEST_ROUTE and REPLY_ROUTE.
    This function can be used from REQUEST_ROUTE and REPLY_ROUTE.
 
 
-   Example 1.23. save usage
+   Example 1.25. save usage
 ...
 ...
 save("location");
 save("location");
 save("location", "0x01");
 save("location", "0x01");
 save("location", "0x00", "sip:[email protected]");
 save("location", "0x00", "sip:[email protected]");
 ...
 ...
 
 
-4.2. lookup(domain [, uri])
+4.2.  lookup(domain [, uri])
 
 
    The function extracts username from Request-URI and tries to find all
    The function extracts username from Request-URI and tries to find all
    contacts for the username in usrloc. If there are no such contacts, -1
    contacts for the username in usrloc. If there are no such contacts, -1
@@ -704,7 +766,7 @@ save("location", "0x00", "sip:[email protected]");
 
 
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
 
 
-   Example 1.24. lookup usage
+   Example 1.26. lookup usage
 ...
 ...
 lookup("location");
 lookup("location");
 switch ($retcode) {
 switch ($retcode) {
@@ -718,7 +780,7 @@ switch ($retcode) {
 };
 };
 ...
 ...
 
 
-4.3. lookup_branches(domain)
+4.3.  lookup_branches(domain)
 
 
    The function performs lookup(domain) on r-uri and additional branches
    The function performs lookup(domain) on r-uri and additional branches
    (only branches that have no other attributes set than uri).
    (only branches that have no other attributes set than uri).
@@ -730,12 +792,12 @@ switch ($retcode) {
 
 
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
 
 
-   Example 1.25. lookup_branches usage
+   Example 1.27. lookup_branches usage
 ...
 ...
 lookup_branches("location");
 lookup_branches("location");
 ...
 ...
 
 
-4.4. registered(domain [, uri])
+4.4.  registered(domain [, uri])
 
 
    The function returns true if the AOR in the Request-URI is registered,
    The function returns true if the AOR in the Request-URI is registered,
    false otherwise. The function does not modify the message being
    false otherwise. The function does not modify the message being
@@ -749,7 +811,7 @@ lookup_branches("location");
 
 
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
 
 
-   Example 1.26. registered usage
+   Example 1.28. registered usage
 ...
 ...
 if (registered("location")) {
 if (registered("location")) {
         sl_send_reply("100", "Trying");
         sl_send_reply("100", "Trying");
@@ -757,9 +819,9 @@ if (registered("location")) {
 };
 };
 ...
 ...
 
 
-4.5. add_sock_hdr(hdr_name)
+4.5.  add_sock_hdr(hdr_name)
 
 
-   Adds to the current REGISTER request a new header with "hdr_name" which
+   Adds to the current REGISTER request a new header with “hdr_name� which
    contains the description of the received socket (proto:ip:port)
    contains the description of the received socket (proto:ip:port)
 
 
    This make sens only in multiple replicated servers scenarios.
    This make sens only in multiple replicated servers scenarios.
@@ -769,12 +831,12 @@ if (registered("location")) {
 
 
    This function can be used from REQUEST_ROUTE.
    This function can be used from REQUEST_ROUTE.
 
 
-   Example 1.27. add_sock_hdr usage
+   Example 1.29. add_sock_hdr usage
 ...
 ...
 add_sock_hdr("Sock-Info");
 add_sock_hdr("Sock-Info");
 ...
 ...
 
 
-4.6. unregister(domain, uri)
+4.6.  unregister(domain, uri)
 
 
    The function remove all the contact associated to 'uri'.
    The function remove all the contact associated to 'uri'.
 
 
@@ -787,13 +849,13 @@ add_sock_hdr("Sock-Info");
 
 
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
 
 
-   Example 1.28. unregister usage
+   Example 1.30. unregister usage
 ...
 ...
 unregister("location", "$ru");
 unregister("location", "$ru");
 unregister("location", "sip:[email protected]");
 unregister("location", "sip:[email protected]");
 ...
 ...
 
 
-4.7. reg_fetch_contacts(domain, uri, profile)
+4.7.  reg_fetch_contacts(domain, uri, profile)
 
 
    The function fetches the contacts for 'uri' from table 'domain' to
    The function fetches the contacts for 'uri' from table 'domain' to
    pseudo-variable $ulc(profile).
    pseudo-variable $ulc(profile).
@@ -809,13 +871,13 @@ unregister("location", "sip:[email protected]");
 
 
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
 
 
-   Example 1.29. reg_fetch_contacts usage
+   Example 1.31. reg_fetch_contacts usage
 ...
 ...
 reg_fetch_contacts("location", "$ru", "callee");
 reg_fetch_contacts("location", "$ru", "callee");
 reg_fetch_contacts("location", "sip:[email protected]", "caller");
 reg_fetch_contacts("location", "sip:[email protected]", "caller");
 ...
 ...
 
 
-4.8. reg_free_contacts(profile)
+4.8.  reg_free_contacts(profile)
 
 
    The function frees the contacts from pseudo-variable $ulc(profile).
    The function frees the contacts from pseudo-variable $ulc(profile).
    Should be called to release the content of a profile. Anyhow, fetching
    Should be called to release the content of a profile. Anyhow, fetching
@@ -828,7 +890,7 @@ reg_fetch_contacts("location", "sip:[email protected]", "caller");
 
 
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
 
 
-   Example 1.30. reg_free_contacts usage
+   Example 1.32. reg_free_contacts usage
 ...
 ...
 reg_free_contacts("callee");
 reg_free_contacts("callee");
 ...
 ...
@@ -868,12 +930,12 @@ reg_free_contacts("callee");
 6.1. $ulc(profile=>attr)
 6.1. $ulc(profile=>attr)
 
 
    Access the attributes of contact addresses stored in 'profile'. It must
    Access the attributes of contact addresses stored in 'profile'. It must
-   be used after a call of "reg_fetch_contacts()".
+   be used after a call of “reg_fetch_contacts()�.
 
 
-   The "profile" has to be one of the values used with
-   "reg_fetch_contacts()".
+   The “profile� has to be one of the values used with
+   “reg_fetch_contacts()�.
 
 
-   The "attr" can be:
+   The “attr� can be:
      * aor - address of record
      * aor - address of record
      * domain - use location domain name
      * domain - use location domain name
      * aorhash - hash id for the record
      * aorhash - hash id for the record
@@ -894,7 +956,7 @@ reg_free_contacts("callee");
    The pseudo-variable accepts positive index value to access a specific
    The pseudo-variable accepts positive index value to access a specific
    contact record.
    contact record.
 
 
-   Example 1.31. $ulc(name) usage
+   Example 1.33. $ulc(name) usage
 ...
 ...
 if(reg_fetch_contacts("location", "$fu", "caller"))
 if(reg_fetch_contacts("location", "$fu", "caller"))
 {
 {
@@ -926,9 +988,9 @@ if(reg_fetch_contacts("location", "$fu", "caller"))
 
 
 Chapter 2. Frequently Asked Questions
 Chapter 2. Frequently Asked Questions
 
 
-   2.1. What happend with the old "nat_flag" module parameter?
-   2.2. What happend with the old "use_domain" module parameter?
-   2.3. What happend with the old "save_noreply" and "save_memory"
+   2.1. What happend with the old “nat_flag� module parameter?
+   2.2. What happend with the old “use_domain� module parameter?
+   2.3. What happend with the old “save_noreply� and “save_memory�
           functions?
           functions?
 
 
    2.4. Where can I find more about Kamailio?
    2.4. Where can I find more about Kamailio?
@@ -938,23 +1000,23 @@ Chapter 2. Frequently Asked Questions
 
 
    2.1.
    2.1.
 
 
-   What happend with the old "nat_flag" module parameter?
+   What happend with the old “nat_flag� module parameter?
 
 
    In was removed, as the module internally loads this value from the
    In was removed, as the module internally loads this value from the
-   "USRLOC" module (see the "nat_bflag" USRLOC parameter).
+   “USRLOC� module (see the “nat_bflag� USRLOC parameter).
 
 
    2.2.
    2.2.
 
 
-   What happend with the old "use_domain" module parameter?
+   What happend with the old “use_domain� module parameter?
 
 
    In was removed, as the module internally loads this option from the
    In was removed, as the module internally loads this option from the
-   "USRLOC" module. This was done in order to simplify the configuration.
+   “USRLOC� module. This was done in order to simplify the configuration.
 
 
    2.3.
    2.3.
 
 
-   What happend with the old "save_noreply" and "save_memory" functions?
+   What happend with the old “save_noreply� and “save_memory� functions?
 
 
-   There functions were merged into the new "save(domain,flags)"
+   There functions were merged into the new “save(domain,flags)�
    functions. If a reply should be sent or if the DB should be updated
    functions. If a reply should be sent or if the DB should be updated
    also is controlled via the flags.
    also is controlled via the flags.
 
 

+ 86 - 0
modules_k/registrar/doc/registrar_admin.xml

@@ -721,6 +721,92 @@ modparam("registrar", "gruu_enabled", 0)
 		</example>
 		</example>
 	</section>
 	</section>
 
 
+	<section>
+		<title><varname>outbound_mode</varname> (integer)</title>
+		<para>
+		If set to 0 then this module will accept REGISTER requests
+		that do not contain a Supported: header with the outbound
+		options-tag. The 200 OK response to REGISTER requests that this
+		module generates will not contain Require: or Supported: headers
+		with the outbound options tag.
+		</para>
+		<para>
+		If set to 1 then this module will accept REGISTER requests
+		that do not contain a Supported: header with the outbound
+		options-tag. The 200 OK response to REGISTER requests that this
+		module generates will contain a Supported: header with the
+		outbound options tag.
+		</para>
+		<para>
+		If set to 2 then this module will reject REGISTER requests
+		that do not contain a Supported: header with the outbound
+		options-tag. The 200 OK response to REGISTER requests that this
+		module generates will contain Require: and Supported: headers
+		with the outbound options tag.
+		</para>
+		<para>
+		Set this parameter to 2 if you are using SIP Outbound (RFC
+		5626) and want your Edge Proxy to insert a Flow-Timer: header
+		into the 200 OK response to REGISTERs (as per RFC 5626 section
+		5.4).
+		</para>
+		<para>
+		<emphasis>
+			Default value is 0.
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>outbound_mode</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("registrar", "outbound_mode", 2)
+...
+		</programlisting>
+		</example>
+	</section>
+
+	<section>
+		<title><varname>flow_timer</varname> (integer)</title>
+		<para>
+		If set to 0 then this module will not add a Flow-Timer: header
+		to 200 OK responses to REGISTER requests.
+		</para>
+		<para>
+		If set to > 0 then this module will add a Flow-Timer: header
+		containing this value to 200 OK responses to REGISTER requests.
+		This parameter may only be set to a value > 0 when
+		<emphasis>outbound_mode</emphasis> is set to 2.
+		</para>
+		<para>
+		When set to a value > 0 this parameter should be set to slightly
+		less than the connection timeout value between the UAC and the
+		network (this corresponds to the core
+		<emphasis>tcp_connection_lifetime</emphasis> option and
+		<emphasis>websocket</emphasis>
+		<emphasis>keepalive_timeout</emphasis> modparam). This parameter
+		is most useful when you have a single edge proxy/registrar. If
+		you are using a separate SIP Outbound Edge Proxy you should
+		consider leaving this parameter set to 0 and adding the
+		Flow-Timer: header on the Edge Proxy (as this allows you to
+		keep all of the timer values for a specific flow in one
+		configuration - that of the Edge Proxy).
+		</para>
+		<para>
+		<emphasis>
+			Default value is 0.
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>flow_timer</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("registrar", "flow_timer", 25)
+...
+		</programlisting>
+		</example>
+	</section>
+
+
 	</section>
 	</section>
 
 
 	
 	

+ 15 - 0
modules_k/registrar/reg_mod.c

@@ -119,6 +119,8 @@ int path_use_params = 0;			/*!< if the received- and nat-parameters of last Path
 sruid_t _reg_sruid;
 sruid_t _reg_sruid;
 
 
 int reg_gruu_enabled = 1;
 int reg_gruu_enabled = 1;
+int reg_outbound_mode = 0;
+int reg_flow_timer = 0;
 
 
 /* Populate this AVP if testing for specific registration instance. */
 /* Populate this AVP if testing for specific registration instance. */
 char *reg_callid_avp_param = 0;
 char *reg_callid_avp_param = 0;
@@ -222,6 +224,8 @@ static param_export_t params[] = {
 	{"xavp_cfg",           STR_PARAM, &reg_xavp_cfg.s     					},
 	{"xavp_cfg",           STR_PARAM, &reg_xavp_cfg.s     					},
 	{"xavp_rcd",           STR_PARAM, &reg_xavp_rcd.s     					},
 	{"xavp_rcd",           STR_PARAM, &reg_xavp_rcd.s     					},
 	{"gruu_enabled",       INT_PARAM, &reg_gruu_enabled    					},
 	{"gruu_enabled",       INT_PARAM, &reg_gruu_enabled    					},
+	{"outbound_mode",      INT_PARAM, &reg_outbound_mode					},
+	{"flow_timer",         INT_PARAM, &reg_flow_timer					},
 	{0, 0, 0}
 	{0, 0, 0}
 };
 };
 
 
@@ -373,6 +377,17 @@ static int mod_init(void)
 		sock_flag = -1;
 		sock_flag = -1;
 	}
 	}
 
 
+	if (reg_outbound_mode < 0 || reg_outbound_mode > 2) {
+		LM_ERR("outbound_mode modparam must be 0 (not supported), 1 (supported), or 2 (supported and required)\n");
+		return -1;
+	}
+
+	if (reg_flow_timer < 0 || reg_flow_timer > REG_FLOW_TIMER_MAX
+			|| (reg_flow_timer > 0 && reg_outbound_mode != REG_OUTBOUND_REQUIRE)) {
+		LM_ERR("bad value for flow_timer\n");
+		return -1;
+	}
+
 	/* fix the flags */
 	/* fix the flags */
 	sock_flag = (sock_flag!=-1)?(1<<sock_flag):0;
 	sock_flag = (sock_flag!=-1)?(1<<sock_flag):0;
 	tcp_persistent_flag = (tcp_persistent_flag!=-1)?(1<<tcp_persistent_flag):0;
 	tcp_persistent_flag = (tcp_persistent_flag!=-1)?(1<<tcp_persistent_flag):0;

+ 11 - 0
modules_k/registrar/reg_mod.h

@@ -67,6 +67,15 @@
 #define REG_SAVE_REPL_FL    (1<<2)
 #define REG_SAVE_REPL_FL    (1<<2)
 #define REG_SAVE_ALL_FL     ((1<<3)-1)
 #define REG_SAVE_ALL_FL     ((1<<3)-1)
 
 
+#define REG_OUTBOUND_NONE	0
+#define REG_OUTBOUND_SUPPORTED	1
+#define REG_OUTBOUND_REQUIRE	2
+
+/* Maximum of 999 to keep flow-timer to 3 digits
+   - make sure to update reply.c:add_flow_timer() if the number of digits
+     increases! */
+#define REG_FLOW_TIMER_MAX	999
+
 extern int nat_flag;
 extern int nat_flag;
 extern int tcp_persistent_flag;
 extern int tcp_persistent_flag;
 extern int received_avp;
 extern int received_avp;
@@ -84,6 +93,8 @@ extern int path_enabled;
 extern int path_mode;
 extern int path_mode;
 extern int path_use_params;
 extern int path_use_params;
 extern int reg_gruu_enabled;
 extern int reg_gruu_enabled;
+extern int reg_outbound_mode;
+extern int reg_flow_timer;
 
 
 extern str sock_hdr_name;
 extern str sock_hdr_name;
 extern int sock_flag;
 extern int sock_flag;

+ 121 - 20
modules_k/registrar/reply.c

@@ -373,6 +373,7 @@ int build_contact(sip_msg_t *msg, ucontact_t* c, str *host)
 #define MSG_200 "OK"
 #define MSG_200 "OK"
 #define MSG_400 "Bad Request"
 #define MSG_400 "Bad Request"
 #define MSG_420 "Bad Extension"
 #define MSG_420 "Bad Extension"
+#define MSG_421 "Extension Required"
 #define MSG_500 "Server Internal Error"
 #define MSG_500 "Server Internal Error"
 #define MSG_503 "Service Unavailable"
 #define MSG_503 "Service Unavailable"
 
 
@@ -406,6 +407,7 @@ int build_contact(sip_msg_t *msg, ucontact_t* c, str *host)
 #define EI_R_CALLID_LEN  "Callid too long"                          /* R_CALLID_LEN */
 #define EI_R_CALLID_LEN  "Callid too long"                          /* R_CALLID_LEN */
 #define EI_R_PARSE_PATH  "Path parse error"                         /* R_PARSE_PATH */
 #define EI_R_PARSE_PATH  "Path parse error"                         /* R_PARSE_PATH */
 #define EI_R_PATH_UNSUP  "No support for found Path indicated"      /* R_PATH_UNSUP */
 #define EI_R_PATH_UNSUP  "No support for found Path indicated"      /* R_PATH_UNSUP */
+#define EI_R_OB_UNSUP    "No support for Outbound indicated"        /* R_OB_UNSUP */
 
 
 str error_info[] = {
 str error_info[] = {
 	{EI_R_FINE,       sizeof(EI_R_FINE) - 1},
 	{EI_R_FINE,       sizeof(EI_R_FINE) - 1},
@@ -437,7 +439,8 @@ str error_info[] = {
 	{EI_R_CONTACT_LEN,sizeof(EI_R_CONTACT_LEN) - 1},
 	{EI_R_CONTACT_LEN,sizeof(EI_R_CONTACT_LEN) - 1},
 	{EI_R_CALLID_LEN, sizeof(EI_R_CALLID_LEN) - 1},
 	{EI_R_CALLID_LEN, sizeof(EI_R_CALLID_LEN) - 1},
 	{EI_R_PARSE_PATH, sizeof(EI_R_PARSE_PATH) - 1},
 	{EI_R_PARSE_PATH, sizeof(EI_R_PARSE_PATH) - 1},
-	{EI_R_PATH_UNSUP, sizeof(EI_R_PATH_UNSUP) - 1}
+	{EI_R_PATH_UNSUP, sizeof(EI_R_PATH_UNSUP) - 1},
+	{EI_R_OB_UNSUP,   sizeof(EI_R_OB_UNSUP) - 1},
 
 
 };
 };
 
 
@@ -471,7 +474,8 @@ int codes[] = {
 	400, /* R_CONTACT_LEN */
 	400, /* R_CONTACT_LEN */
 	400, /* R_CALLID_LEN */
 	400, /* R_CALLID_LEN */
 	400, /* R_PARSE_PATH */
 	400, /* R_PARSE_PATH */
-	420  /* R_PATH_UNSUP */
+	420, /* R_PATH_UNSUP */
+	421  /* R_OB_UNSUP */
 
 
 };
 };
 
 
@@ -537,6 +541,69 @@ static int add_unsupported(struct sip_msg* _m, str* _p)
  		     LUMP_RPL_HDR | LUMP_RPL_NODUP);
  		     LUMP_RPL_HDR | LUMP_RPL_NODUP);
  	return 0;
  	return 0;
 }
 }
+
+#define REQUIRE "Require: "
+#define REQUIRE_LEN (sizeof(REQUIRE) - 1)
+
+static int add_require(struct sip_msg* _m, str* _p)
+{
+	char* buf;
+
+ 	buf = (char*)pkg_malloc(REQUIRE_LEN + _p->len + CRLF_LEN);
+ 	if (!buf) {
+ 		LM_ERR("no pkg memory left\n");
+ 		return -1;
+ 	}
+ 	memcpy(buf, REQUIRE, REQUIRE_LEN);
+ 	memcpy(buf + REQUIRE_LEN, _p->s, _p->len);
+ 	memcpy(buf + REQUIRE_LEN + _p->len, CRLF, CRLF_LEN);
+ 	add_lump_rpl(_m, buf, REQUIRE_LEN + _p->len + CRLF_LEN,
+ 		     LUMP_RPL_HDR | LUMP_RPL_NODUP);
+ 	return 0;
+}
+
+#define SUPPORTED "Supported: "
+#define SUPPORTED_LEN (sizeof(SUPPORTED) - 1)
+
+static int add_supported(struct sip_msg* _m, str* _p)
+{
+	char* buf;
+
+ 	buf = (char*)pkg_malloc(SUPPORTED_LEN + _p->len + CRLF_LEN);
+ 	if (!buf) {
+ 		LM_ERR("no pkg memory left\n");
+ 		return -1;
+ 	}
+ 	memcpy(buf, SUPPORTED, SUPPORTED_LEN);
+ 	memcpy(buf + SUPPORTED_LEN, _p->s, _p->len);
+ 	memcpy(buf + SUPPORTED_LEN + _p->len, CRLF, CRLF_LEN);
+ 	add_lump_rpl(_m, buf, SUPPORTED_LEN + _p->len + CRLF_LEN,
+ 		     LUMP_RPL_HDR | LUMP_RPL_NODUP);
+ 	return 0;
+}
+
+#define FLOW_TIMER "Flow-Timer: "
+#define FLOW_TIMER_LEN (sizeof(FLOW_TIMER) - 1)
+
+static int add_flow_timer(struct sip_msg* _m)
+{
+	char* buf;
+	int lump_len;
+
+	/* Add three as REG_FLOW_TIMER_MAX is 999 - three digits */
+ 	buf = (char*)pkg_malloc(FLOW_TIMER_LEN + 3 + CRLF_LEN);
+ 	if (!buf) {
+ 		LM_ERR("no pkg memory left\n");
+ 		return -1;
+ 	}
+	lump_len = snprintf(buf, FLOW_TIMER_LEN + 3 + CRLF_LEN,
+				"%.*s%d%.*s",
+				FLOW_TIMER_LEN, FLOW_TIMER,
+				reg_flow_timer,
+				CRLF_LEN, CRLF);
+ 	add_lump_rpl(_m, buf, lump_len, LUMP_RPL_HDR | LUMP_RPL_NODUP);
+ 	return 0;
+}
  
  
 /*! \brief
 /*! \brief
  * Send a reply
  * Send a reply
@@ -544,6 +611,7 @@ static int add_unsupported(struct sip_msg* _m, str* _p)
 int reg_send_reply(struct sip_msg* _m)
 int reg_send_reply(struct sip_msg* _m)
 {
 {
 	str unsup = str_init(SUPPORTED_PATH_STR);
 	str unsup = str_init(SUPPORTED_PATH_STR);
+	str outbound_str = str_init(SUPPORTED_OUTBOUND_STR);
 	long code;
 	long code;
 	str msg = str_init(MSG_200); /* makes gcc shut up */
 	str msg = str_init(MSG_200); /* makes gcc shut up */
 	char* buf;
 	char* buf;
@@ -552,34 +620,67 @@ int reg_send_reply(struct sip_msg* _m)
 		add_lump_rpl( _m, contact.buf, contact.data_len, LUMP_RPL_HDR|LUMP_RPL_NODUP|LUMP_RPL_NOFREE);
 		add_lump_rpl( _m, contact.buf, contact.data_len, LUMP_RPL_HDR|LUMP_RPL_NODUP|LUMP_RPL_NOFREE);
 		contact.data_len = 0;
 		contact.data_len = 0;
 	}
 	}
-			
-	if (rerrno == R_FINE && path_enabled && _m->path_vec.s) {
-		if (path_mode != PATH_MODE_OFF) {
-			if (parse_supported(_m)<0 && path_mode == PATH_MODE_STRICT) {
-				rerrno = R_PATH_UNSUP;
-				if (add_unsupported(_m, &unsup) < 0)
-					return -1;
-				if (add_path(_m, &_m->path_vec) < 0)
-					return -1;
+
+	switch (rerrno) {
+	case R_FINE:
+		if (path_enabled && _m->path_vec.s) {
+			if (path_mode != PATH_MODE_OFF) {
+				if (parse_supported(_m)<0 && path_mode == PATH_MODE_STRICT) {
+					rerrno = R_PATH_UNSUP;
+					if (add_unsupported(_m, &unsup) < 0)
+						return -1;
+					if (add_path(_m, &_m->path_vec) < 0)
+						return -1;
+				}
+				else if (get_supported(_m) & F_SUPPORTED_PATH) {
+					if (add_path(_m, &_m->path_vec) < 0)
+						return -1;
+				} else if (path_mode == PATH_MODE_STRICT) {
+					rerrno = R_PATH_UNSUP;
+					if (add_unsupported(_m, &unsup) < 0)
+						return -1;
+					if (add_path(_m, &_m->path_vec) < 0)
+						return -1;
+				}
 			}
 			}
-			else if (get_supported(_m) & F_SUPPORTED_PATH) {
-				if (add_path(_m, &_m->path_vec) < 0)
-					return -1;
-			} else if (path_mode == PATH_MODE_STRICT) {
-				rerrno = R_PATH_UNSUP;
-				if (add_unsupported(_m, &unsup) < 0)
-					return -1;
-				if (add_path(_m, &_m->path_vec) < 0)
+		}
+
+		switch(reg_outbound_mode)
+		{
+		case REG_OUTBOUND_NONE:
+		default:
+			break;
+		case REG_OUTBOUND_REQUIRE:
+			if (add_require(_m, &outbound_str) < 0)
+				return -1;
+
+			if (reg_flow_timer > 0) {
+				if (add_flow_timer(_m) < 0)
 					return -1;
 					return -1;
 			}
 			}
+			/* Fall-thru */
+		case REG_OUTBOUND_SUPPORTED:
+			if (add_supported(_m, &outbound_str) < 0)
+				return -1;
+			break;
 		}
 		}
+		break;
+	case R_OB_UNSUP:
+		if (add_require(_m, &outbound_str) < 0)
+			return -1;
+		if (add_supported(_m, &outbound_str) < 0)
+			return -1;
+		break;
+	default:
+		break;
 	}
 	}
 
 
 	code = codes[rerrno];
 	code = codes[rerrno];
 	switch(code) {
 	switch(code) {
-	case 200: msg.s = MSG_200; msg.len = sizeof(MSG_200)-1; break;
+	case 200: msg.s = MSG_200; msg.len = sizeof(MSG_200)-1;break;
 	case 400: msg.s = MSG_400; msg.len = sizeof(MSG_400)-1;break;
 	case 400: msg.s = MSG_400; msg.len = sizeof(MSG_400)-1;break;
 	case 420: msg.s = MSG_420; msg.len = sizeof(MSG_420)-1;break;
 	case 420: msg.s = MSG_420; msg.len = sizeof(MSG_420)-1;break;
+	case 421: msg.s = MSG_420; msg.len = sizeof(MSG_421)-1;break;
 	case 500: msg.s = MSG_500; msg.len = sizeof(MSG_500)-1;break;
 	case 500: msg.s = MSG_500; msg.len = sizeof(MSG_500)-1;break;
 	case 503: msg.s = MSG_503; msg.len = sizeof(MSG_503)-1;break;
 	case 503: msg.s = MSG_503; msg.len = sizeof(MSG_503)-1;break;
 	}
 	}

+ 2 - 1
modules_k/registrar/rerrno.h

@@ -63,7 +63,8 @@ typedef enum rerr {
 	R_CONTACT_LEN,/*!< Contact URI or RECEIVED too long */
 	R_CONTACT_LEN,/*!< Contact URI or RECEIVED too long */
 	R_CALLID_LEN, /*!< Callid too long */
 	R_CALLID_LEN, /*!< Callid too long */
 	R_PARSE_PATH, /*!< Error while parsing Path */
 	R_PARSE_PATH, /*!< Error while parsing Path */
-	R_PATH_UNSUP  /*!< Path not supported by UAC */
+	R_PATH_UNSUP, /*!< Path not supported by UAC */
+	R_OB_UNSUP    /*!< Outbound not supported by UAC */
 
 
 } rerr_t;
 } rerr_t;
 
 

+ 10 - 0
modules_k/registrar/save.c

@@ -61,6 +61,7 @@
 #include "../../mod_fix.h"
 #include "../../mod_fix.h"
 #include "../../lib/srutils/sruid.h"
 #include "../../lib/srutils/sruid.h"
 #include "../../lib/kcore/cmpapi.h"
 #include "../../lib/kcore/cmpapi.h"
+#include "../../lib/kcore/parse_supported.h"
 #include "../../lib/kcore/statistics.h"
 #include "../../lib/kcore/statistics.h"
 #ifdef USE_TCP
 #ifdef USE_TCP
 #include "../../tcp_server.h"
 #include "../../tcp_server.h"
@@ -840,6 +841,15 @@ int save(struct sip_msg* _m, udomain_t* _d, int _cflags, str *_uri)
 	if (check_contacts(_m, &st) > 0) {
 	if (check_contacts(_m, &st) > 0) {
 		goto error;
 		goto error;
 	}
 	}
+
+	if (parse_supported(_m) == 0) {
+		if (!(((struct supported_body *)_m->supported->parsed)->supported_all
+				& F_SUPPORTED_OUTBOUND) && reg_outbound_mode == REG_OUTBOUND_REQUIRE) {
+			LM_WARN("Outbound required by server and not supported by UAC\n");
+			rerrno = R_OB_UNSUP;
+			goto error;
+		}
+	}
 	
 	
 	get_act_time();
 	get_act_time();
 	c = get_first_contact(_m);
 	c = get_first_contact(_m);

+ 1 - 1
socket_info.c

@@ -2018,7 +2018,7 @@ void print_all_socket_lists()
 						si->flags & SI_IS_MCAST ? " mcast" : "",
 						si->flags & SI_IS_MCAST ? " mcast" : "",
 						si->flags & SI_IS_MHOMED? " mhomed" : "");
 						si->flags & SI_IS_MHOMED? " mhomed" : "");
 				if (si->useinfo.name.s)
 				if (si->useinfo.name.s)
-					printf(" advertise %s", si->useinfo.name.s);
+					printf(" advertise %s:%d", si->useinfo.name.s, si->useinfo.port_no);
 				printf("\n");
 				printf("\n");
 			}
 			}
 		}
 		}