Configuration

From Wesip

From Wesip

To have WeSIP up and running, you need to first configure OpenSER and the SEAS module, and the configure the WeSIP Application Server. The former is configured through the openser.cfg file (wherever you store it), and the latter (WeSIP) is configured through a file called server.xml, which is processed by the WeSIP container at startup.

Contents

Configuring the SEAS module: openser.cfg

The SEAS module is relatively easy to configure. There is only 1 parameter and 1 function (at the moment) exported.

The parameter is called "listen_sockets", and it tells the SEAS module the IP and port where it must be listening for Application Servers to connect. Once the SEAS module is loaded and its initialization function is called, it spawns a new process which will be listening on that socket. From then on, you can start the WeSIP application server, so that it can connect and start receiving the SIP requests and responses.

The SEAS module relies on the Transaction Module to work, as every SIP-request that is passed to the Application Server is associated to a SIP transaction.

Example:

loadmodule "modules/tm/tm.so"
loadmodule "modules/seas/seas.so"
loadmodule "modules/textops/textops.so"

modparam("seas", "listen_sockets","127.0.0.1:5080")


Within the OpenSER configuration script, you can do the message-processing logic you need (ie. authenticatin, accounting, etc), and when you're ready, you can pass the request to the Application Server invoking the function as_relay_t().

This function receives as a parameter the name of the chosen WeSIP AS instance to process this particular request. This way, you can have different WeSIP instances, each one identified by a different name, so that each one processes different SIP-requests.

If at the moment of invoking as_relay_t, the specified Application Server (the parameter) is not connected to the SEAS module, the function returns a negative value, so that you can do something like

 route{
 if(!as_relay_t("app_server_one")){
        t_reply("500","No App Server");
 }
 }

or

 route{
    if(!as_relay_t("app_server_one")"{
      if(!as_relay_t("app_server_two")){
              t_reply("500","No App Server");
       }
     }
  }


Configuring the WeSIP Application Server

The WeSIP Application Server configuration file is based on the Apache Tomcat configuration system: It is an XML-formatted file, in which the different components of the server are specified.

The default config file that comes with the WeSIP distribution package should be suitable for most of the deployment configurations.

Server

The topmost element in the XML configuration file is the "server" which has 2 xml attributes, called "port" and "shutdown". The former specifies a port on which the WeSIP AS will listen for the shutdown command, and the latter is the magic word that will make the server shutdown.

Example:

<Server port="8005" shutdown="SHUTDOWN" >

if you send the magic word "SHUTDOWN" to the port 8005 of the localhost, the server will stop cleanly.

Service

Nested within the Server element, must be a "Service" element, with an attribute called "name" which specifies the name for the service. This attribute is not very relevant, you can call it whatever you like.

Example:

<Service name="WeSIP-Standalone">

Within the Service element must be two or more elements: the connectors and the engines. A connector is the instance that will receive messages from the network. You can specify HTTP connectors and/or SIP connectors. Every connector needs an attribute called "className" which specifies which class will be responsible for receiving the messages from the network. For HTTP connectors, the classname must be "org.apache.catalina.connector.http.HttpConnector" and for SIP connectors "com.voztele.sipservlet.connector.SipConnector".

Connector

The SIP Connector uses 6 attributes:

  • className="com.voztele.sipservlet.connector.SipConnector"

specifies the classname of the connector.

  • minProcessors="5"

specifies the minimum number of SIPprocessor instances (and threads in the pool) to process incoming SIP messages. More processors should allow more load to be processed. This is the minimum number of instances, even if they are spare and not working.

  • maxProcessors="10"

specifies the maximum number of SIP processors used (a negative value specifies that there is no limit).

  • addresses="localhost:5060"


Specifies the SIP address and port in which the Application Server from which the Application Server will process the SIP messages. This Addres is where OpenSER listens for the messages, so in fact, OpenSER is listening on them, but OpenSER passes the messages to WeSIP, so WeSIP must be aware of this IP/port.

VERY IMPORTANT: this attribute MUST match one of the listening points declared within OpenSER in the "listen" parameters. For example:

openser.cfg:
listen = tcp:localhost:5060
listen = udp:localhost:5060
  • pathName="com.voztele"

that indicates the root package where to look for the implementation classes and

  • protocol="udp"

the protocol of the connector. Currently only UDP has been tested.

Within the SIP Connector element there must be an ExtraProperties element, containing nested Property elements. Each property element specifies a parameter for the SIP Stack. Each property is specified by a key and a value. The most significant keys are:

com.voztele.javax.sip.SER_ADDRESS

This specifies the IP and port in which the OpenSER is listening for Application Servers to connect and register. IMPORTANT: This needs to match the listen_sockets seas module parameter within the OpenSER configuration file (ie.

 modparam("seas", "listen_sockets","127.0.0.1:5080") 

javax.sip.STACK_NAME

VERY IMPORTANT this is the name you will set in the OpenSER configuration 

script when you invoke the WeSIP Application Server, by calling the as_relay_t function. This is the name you pass as the parameter of the function. If you have different WeSIP instances all connecting to the same OpenSER, they must each one have a different STACK_NAME", and within OpenSER you can call each of them by invoking as_relay_t() with a different name.

example: <Property key="javax.sip.STACK_NAME" value="app_server_one" />


com.voztele.javax.sip.THREAD_POOL_SIZE

(integer) Specifies the number of threads there must be in the pool to process incoming SIP messages. If unspecificed, the default is "infinity".

com.voztele.javax.sip.SPIRAL_HDR

This property tells WeSIP and SEAS that every SipRequest and UAC transaction generated from WeSIP, Must spiral through SER, and will be added a special Header called "X-WeSIP-SPIRAL: true" this will make all the outgoing messages pass again through the OpenSER script, so that they can be accounted or whatever the configurator wants. For example, the configuration script could go:

route{
        if(is_present_hf("X-WeSIP-SPIRAL")){
 /* account, log, register, or whatever */
                t_relay();
        }else{
                as_relay_t("app_server_one");
        }
}

Engine

The Engine must also be nested within the Server element, along with the Connectors. It must have a "name" attribute with whatever name you feel like. It needs to have another attribute called "defaultHost" which will be the default host to which to pass the incoming request (in HTTP/1.0 the requests dont have a Host header, so they will be passed to this default host, in SIP, this attribute doesn't have a meaning.). In order to have this Engine handling also SIP messages, the "className" attribute of the Engine MUST BE "com.voztele.sipservlet.core.ConvergedEngine"

Within the Engine, there can be one or more Hosts, each one specified within a "Host" element nested in the engine.

Mapper

A mapper is used to map an incoming request to one or another SIP or HTTP host. In case it is a SIP request, the mapping is done based on the sip.xml deployment descriptor rules. The classname of the SIP mapper MUST BE "com.voztele.sipservlet.core.EngineSipMapper". The "mapper" element must also have a "protocol" attribute, specifying which protocol this mapper handles. In case of the SIP mapper it must be "SIP/2.0". The HTTP mapper's classname must be "org.apache.catalina.core.StandardEngineMapper" and the protocol attribute "HTTP/1.1"

Realm

The authentication in HTTP is performed in Apache-Tomcat through Realms. The memory realm is (textual copy from the Apache-Tomcat javadoc"): "Simple implementation of Realm that reads an XML file to configure the valid users, passwords, and roles."

The classname must be "org.apache.catalina.realm.MemoryRealm"

A "pathname" attribute can be specified to tell the Realm which file contains the usernames, passwords and roles. If not specified, it is "conf/wesip-users.xml"


Host

A Host represents a VirtualHost in HTTP/1.1 servers, so the requests will be dispatched to one or another virtual host depending on the Host: header. In SIP this doesn't make much sense, because there's no such Host: header, and virtual hosting is not done in this way. Every host must have a "name" attribute which specifies the name of the virtual host, it must also have a "nameSip" attribute which MUST MATCH the IP or hostname _and_ port" specified in OpenSER listen parameters and in the Sip Connector the hostname and the port must be separated with an underscore. for example: nameSip="localhost_5060" or nameSip="192.168.1.1_5060"

The next important attribute that must have the Host element is "appBase" which declares the directory where the WEB and SIP applications reside. It usually is a directory called apps in the directory from which the server runs.

The attribute "unpackWARs" says the WeSIP Application Server to unpack the Web or Sip Application Archives (.war or .sar extensions) found inside the appBase directory. It should usually be set to "true".

The "port" attribute specifies the port where this host is going to receive SIP messages . This only has to do with the SIP protocol, not with HTTP. It must be the same as the port specified in OpenSER parameter "listen_sockets" (for the seas module).

The "autoDeploy" attribute tells the host to monitor the "appBase" directory for new application archives (.sar or .war) so they can automatically be deployed. This parameter should be set to "true".

The "className" used for the Host _must_be_ "com.voztele.sipservlet.core.ConvergedHost"

Mapper

Hosts must also have a nested Mapper element, but when the mapper is inside a Host (and not in an Engine) the classnames must be "com.voztele.sipservlet.core.SipHostMapper" for the "SIP/2.0" protocol and "org.apache.catalina.core.HttpHostMapper" for the "HTTP/1.1" protocol. (2 mappers must be nested inside the Host).

Configuration Examples

In general, you can configure WeSIP to work with your OpenSER in two ways: have 2 OpenSER instances, the first acting as Proxy/Registrar/Redirect and the second cooperating with WeSIP to act as the Application Server. This is the preferred deployment layout, as the first OpenSER works as usual, and the requests that need special services are relaied to another OpenSER which acts on behalf of the WeSIP AS. This configuration profile distributes load (call-routing logic in one instance, and Application Services in the other), and is also more fault-tolerant.

On the other hand, you can have all your call-routing logic and Application Server on the same OpenSER, having one script handle all the logic, and then invoking the App Server at any point.

Openser.cfg in standalone

debug=3            # debug level (cmd line: -dddddddddd)
fork=yes
log_stderror=no    # (cmd line: -E)
check_via=no    # (cmd. line: -v)
dns=no          # (cmd. line: -r)
rev_dns=no      # (cmd. line: -R)
port=5060
children=4
fifo="/tmp/openser_fifo"
loadmodule "/usr/local/lib/openser/modules/sl.so"
loadmodule "/usr/local/lib/openser/modules/tm.so"
loadmodule "/usr/local/lib/openser/modules/rr.so"
loadmodule "/usr/local/lib/openser/modules/maxfwd.so"
loadmodule "/usr/local/lib/openser/modules/usrloc.so"
loadmodule "/usr/local/lib/openser/modules/registrar.so"
loadmodule "/usr/local/lib/openser/modules/textops.so"
loadmodule "/usr/local/lib/openser/modules/seas.so"
modparam("usrloc", "db_mode",   0)
modparam("rr", "enable_full_lr", 1)
modparam("seas", "listen_sockets", "127.0.0.1:5080");
route{
       if (!mf_process_maxfwd_header("10")) {
               sl_send_reply("483","Too Many Hops");
               exit;
       };
       if (msg:len >=  2048 ) {
               sl_send_reply("513", "Message too big");
               exit;
       };
       if (!method=="REGISTER")
               record_route();
       if (loose_route()) {
               append_hf("P-hint: rr-enforced\r\n");
               route(1);
       };
       if (uri==myself) {
               if (method=="REGISTER") {
                       save("location");
                       exit;
               };
               lookup("aliases");
               if (!uri==myself) {
                       append_hf("P-hint: outbound alias\r\n");
                       route(1);
               };
               if (!lookup("location")) {
                       sl_send_reply("404", "Not Found");
                       exit;
               };
               append_hf("P-hint: usrloc applied\r\n");
       };
       route(1);
}
route[1] {
                if(!as_relay_t("app_server_one")){
                       t_reply("500","Application Server error");
               }
}

Openser.cfg working as WeSIP front-end

debug=9            # debug level (cmd line: -dddddddddd)
fork=yes
log_stderror=yes    # (cmd line: -E)

check_via=no    # (cmd. line: -v)
dns=no          # (cmd. line: -r)
rev_dns=no      # (cmd. line: -R)
port=5060
children=4
fifo="/tmp/openser_fifo"

reply_to_via=1
listen = tcp:localhost:5060 
listen = udp:localhost:5060 

mpath="/home/elias/src/sipservlet/seas"

loadmodule "modules/tm/tm.so"
loadmodule "modules/seas/seas.so"

modparam("seas", "listen_sockets","127.0.0.1:5080")

route{
                if(!as_relay_t("app_server_one")){
                        t_reply("500","Application Server error");
                }
}

Server.xml

<Server port="8005" shutdown="SHUTDOWN" debug="0">
  <Service name="WeSIP-Standalone">
    <Connector className="org.apache.catalina.connector.http.HttpConnector"
        port="8080" minProcessors="5" maxProcessors="75"
        enableLookups="true" address="localhost" acceptCount="10" debug="10" />
        <Connector className="com.voztele.sipservlet.connector.SipConnector"
        minProcessors="5" maxProcessors="75"
        addresses="localhost:5060" pathName="com.voztele" protocol="udp">
               <ExtraProperties>
                       <Property key="com.voztele.javax.sip.SER_ADDRESS" value="127.0.0.1:5080" />
                       <Property key="javax.sip.STACK_NAME" value="app_server_one" />
                       <Property key="com.voztele.javax.sip.THREAD_POOL_SIZE" value="10" />
               </ExtraProperties>
       </Connector>
    <Engine name="Standalone" defaultHost="localhost" debug="10"
       className="com.voztele.sipservlet.core.ConvergedEngine">
        <Logger className="org.apache.catalina.logger.SystemOutLogger"
           timestamp="true"/>
        <Mapper className="org.apache.catalina.core.StandardEngineMapper" protocol="HTTP/1.1"/>
        <Mapper className="com.voztele.sipservlet.core.EngineSipMapper" protocol="SIP/2.0"/>
        <Realm  className="org.apache.catalina.realm.MemoryRealm" />
        <Host name="localhost" nameSip="localhost_5060" debug="10" appBase="webapps" unpackWARs="true"
        port="5060" autoDeploy="true" className="com.voztele.sipservlet.core.ConvergedHost">
               <Mapper className="com.voztele.sipservlet.core.SipHostMapper" protocol="SIP/2.0"/>
               <Mapper className="org.apache.catalina.core.HttpHostMapper" protocol="HTTP/1.1"/>
     </Host>
  </Engine>
</Service>
</Server>