Software SIP - H.323 gateway

A short foreword:

Many installed PBX’s are capable of H.323, but it will be difficult to upgrade them to understand SIP. So a challenge to interconnect sipx with existing PBX via H.323 protocol appears. Below is an example implementation via freeswitch/mod_h323.

The principal idea (Thanks Josh) of how to do it documented here: http://wiki.sipfoundry.org/display/sipXecs/Custom+FreeSWITCH+programming

The goal:

The goal is to make the following scheme to work.

sipX  =====sip=====  FS  =====h323=====  PBX

Steps:

  1. Compile FS with mod_h323 on the sipx server.
  2. Create separate FS sofia profile and dial plan.
  3. Configure sipx dialplan.

Step 1. Compile FS with mod_h323.

The main idea of recompiling FS on the sipx server is documented here:
http://wiki.sipfoundry.org/display/sipXecs/HowTo+recompile+Freeswitch+on+a+CentOS+5+sipXecs+install

The difference is that before actually compiling FS with mod_h323 one should compile prerequisite libraries (ptlib, and h323plus). It is documented here: http://wiki.freeswitch.org/wiki/Mod_h323

So the whole sequence will be:

  • In FS source directory edit file modules.conf and uncomment endpoints/mod_h323 line
  • Configure FS with different prefix like this:
    ./configure \--prefix=/usr/local/freeswitch_custom
    
  • Run make, verify that mod_h323 is compiled.
  • Run make install to install FS into configured “prefix” directory.
  • Edit file /usr/bin/freeswitch.sh so that sipx startup scripts will start this newly compiled FS.
  • /usr/local/freeswitch should be changed to /usr/local/freeswitch_custom on lines 47, 118, 120:
    47: {{FS_EXEC="/usr/local/freeswitch_custom/bin/freeswitch \}}
    
    118: {{if \[WikiWelcome: \! \-x /usr/local/freeswitch_custom/bin/freeswitch \]}}
    
    120: {{echo "Error: FreeSWITCH executable is not at /usr/local/freeswitch_custom/bin/freeswitch" >&2}}
    
  • Backup original /usr/bin/freeswitch.sh file with different name, you’ll be able to return to default FS instance at any time.

Now you should be able to stop old and then start new FS instance by

sipxproc -k FreeSwITCH
sipxproc -s FreeSwITCH
  • For the FS to be able to load mod_h323 the following links should be created:
    {{/usr/local/freeswitch_custom/lib/libh323_linux_x86_.so.1.22.0 \-> /usr/local/lib/libh323_linux_x86_.so.1.22.0}}
    
    And
    {{/usr/local/freeswitch_custom/lib/libpt.so.2.9-beta0 \-> /usr/local/lib/libpt.so.2.9-beta0}}
    

Now you should be able to load mod_h323 from fs_cli command line.

  • Configure FS to autoload mod_h323:
    In the directory /etc/sipxpbx/freeswitch/conf/autoload_configs create file h323.conf:
    <configuration name="h323.conf" description="Opal Endpoints">
      <settings>
        <param name="trace-level" value="4"/>
        <param name="context" value="h323gw"/>
        <param name="dialplan" value="XML"/>
        <param name="codec-prefs" value="PCMA"/>
        <param name="gk-address" value=""/>    <!-- empty to disable, "*" to search LAN -->
        <param name="gk-identifer" value=""/>  <!-- optional name of gk -->
        <param name="gk-interface" value=""/>  <!-- optional listener interface name -->
      </settings>
      <listeners>
        <listener name="default">
          <param name="h323-ip" value="$${local_ip_v4}"/>
          <param name="h323-port" value="1720"/>
        </listener>
      </listeners>
    </configuration>
    
    In the same directory edit file modules.conf.xml: add line
    <load module="mod_h323"/>
    
    to the endpoints section.

Add the same line to the /etc/sipxpbx/freeswitch/modules.conf.xml.vm file.

Now after restarting FreeSWITCH mod_h323 should be loaded.

I don’t know why, but I had to restart the whole sipxecs at this moment, because sipxproc --s “FreeSWITCH” did not start FS, it failed with “configuration check failed. After restarting the whole sipxecs, restarting of just fs, that is sipxproc --k FreeSWITCH and then sipxproc --s FreeSWITCH works ok.

  • Check that mod_h323 is loaded:
    run
    /usr/local/freeswitch_custom/bin/fs_cli -x "show modules" | grep 323
    
    It should show
    endpoint,h323,mod_h323,/usr/local/freeswitch_custom/mod/mod_h323.so
    
    check that port 1720 “is being listened”, run:
    netstat -an | grep -i listen | grep 1720
    
    it should show
    tcp   0   0   172.23.9.2:1720   0.0.0.0:*   LISTEN
    

Step 2: Create separate FS sofia profile and dial plan.

We want to be independent from the main (used by sipx) FS instance. That’s why we create separate sofia profile (named h323gw) and dialplan.

  • Create sofia profile: in the directory /etc/sipxpbx/freeswitch/conf/sip_profiles create a file h323gw.xml:
<profile name="h323gw">
  <!-- http://wiki.freeswitch.org/wiki/Sofia_Configuration_Files -->
  <gateways>
  </gateways>

  <aliases>
  </aliases>

  <domains>
    <domain name="all" alias="false" parse="true"/>
  </domains>

  <settings>
    <param name="debug" value="0"/>
    <param name="sip-trace" value="no"/>
    <param name="rfc2833-pt" value="101"/>
    <param name="sip-port" value="15080"/>
    <param name="dialplan" value="XML"/>
    <param name="context" value="h323gw"/>
    <param name="dtmf-duration" value="100"/>
    <param name="inbound-codec-prefs" value="$${global_codec_prefs}"/>
    <param name="outbound-codec-prefs" value="$${outbound_codec_prefs}"/>
    <param name="hold-music" value="$${hold_music}"/>
    <param name="rtp-timer-name" value="soft"/>
    <!--<param name="enable-100rel" value="true"/>-->
    <!-- This could be set to "passive" -->
    <param name="local-network-acl" value="localnet.auto"/>
    <param name="manage-presence" value="false"/>

    <!--<param name="aggressive-nat-detection" value="true"/>-->
    <param name="inbound-codec-negotiation" value="generous"/>
    <param name="nonce-ttl" value="60"/>
    <param name="auth-calls" value="false"/>
    <!-- added by kond -->
    <param name="accept-blind-auth" value="true"/>
    <!--
        DO NOT USE HOSTNAMES, ONLY IP ADDRESSES IN THESE SETTINGS!
    -->
    <param name="rtp-ip" value="$${local_ip_v4}"/>
    <param name="sip-ip" value="$${local_ip_v4}"/>
    <param name="ext-rtp-ip" value="auto-nat"/>
    <param name="ext-sip-ip" value="auto-nat"/>
    <param name="rtp-timeout-sec" value="300"/>
    <param name="rtp-hold-timeout-sec" value="1800"/>
    <!--<param name="enable-3pcc" value="true"/>-->

    <!-- TLS: disabled by default, set to "true" to enable -->
    <param name="tls" value="$${external_ssl_enable}"/>
    <!-- additional bind parameters for TLS -->
    <param name="tls-bind-params" value="transport=tls"/>
    <!-- Port to listen on for TLS requests. (5081 will be used if unspecified) -->
    <param name="tls-sip-port" value="$${external_tls_port}"/>
    <!-- Location of the agent.pem and cafile.pem ssl certificates (needed for TLS server) -->
    <param name="tls-cert-dir" value="$${external_ssl_dir}"/>
    <!-- TLS version ("sslv23" (default), "tlsv1"). NOTE: Phones may not work with TLSv1 -->
    <param name="tls-version" value="$${sip_tls_version}"/>

  </settings>
</profile>

We are especially interested in two lines
<param name="sip-port" value="15080"/> - This profile will listen on port 1580, and we will route calls from sipx to it’s own address:15080
<param name="context" value="h323gw"/> - FS will process this calls in context h323gw.

  • Create separate dialplan: in the directory /etc/sipxpbx/freeswitch/conf/dialplan create file h323gw.xml:
    <!-- [http://wiki.freeswitch.org/wiki/Dialplan_XML] -->
    <include>
      <context name="h323gw">
    
        <extension name="unloop">
          <condition field="${unroll_loops}" expression="^true$"/>
          <condition field="${sip_looped_call}" expression="^true$">
            <action application="deflect" data="${destination_number}"/>
          </condition>
        </extension>
        <!--
            Tag anything pass thru here as an outside_call so you can make sure not
            to create any routing loops based on the conditions that it came from
            the outside of the switch.
        -->
        <extension name="outside_call" continue="true">
          <condition>
            <action application="set" data="outside_call=true"/>
          </condition>
        </extension>
    
        <extension name="call_debug" continue="true">
          <condition field="${call_debug}" expression="^true$" break="never">
            <action application="info"/>
          </condition>
        </extension>
    
        <X-PRE-PROCESS cmd="include" data="h323gw/*.xml"/>
      </context>
    </include>
    
    Create directory h323gw. And two files with arbitrary names there.
    One to route calls to h323:
    <include>
     <extension>
      <condition field="destination_number" expression="^(\d{7})$">
       <action application="set" data="effective_caller_id_number=${ani}"/>
       <action application="set" data="PEER_IP=172.23.14.2"/>
       <action application="set" data="call_timeout=30"/>
       <action application="set" data="hangup_after_bridge=true"/>
       <action application="bridge" data="h323/$1@${PEER_IP}"/>
      </condition>
     </extension>
    </include>
    
    And the other to route calls to sipx:
    <include>
     <extension>
       <condition field="destination_number" expression="^(28\[0-9\]{2})$\|^(3\d{3})$">
        <action application="set" data="effective_caller_id_number=${outbound_caller_id_number}"/>
        <action application="set" data="effective_caller_id_name=${outbound_caller_id_name}"/>
        <action application="set" data="ringback=${us-ring}"/>
        <action application="bridge" data="sofia/h323gw/$0@beaver.sip.nstel.ru:5080"/>
       </condition>
     </extension>
    </include>
    

I route to sipxbridge (port 5080) in the above example .

Step 3:

In sipx configure a siptrunk gw with ip address of sipx itself and port 15080.
Route calls to this siptrunk as usual.

I decided to use siptrunk for now, albeit direct (sipxproxy - fs) connection should work fine also.