– Kamailio SIP Server –

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

old-content:integrating_openser_and_asterisk_realtime [2006/08/26 02:00] (current)
Line 1: Line 1:
 +This is a tutorial on how to integrate OpenSER with Asterisk v1.2 and the new realtime functions.
 +
 +First, create the views. This allows you to use the same users you already had without having to manually replicate them into another database. You will need MySQL >= 5.0, or a recent version of PostgreSQL. These statements are known to work on MySQL 5, your mileage with PostgreSQL may vary.
 +
 +<​code>​
 +USE openser;
 +ALTER TABLE subscriber
 +ADD vmail_password varchar(40) NULL,
 +ADD vmail BOOL DEFAULT TRUE;
 +
 +CREATE DATABASE asterisk;
 +USE asterisk;
 +CREATE VIEW voicemail AS
 +SELECT ​ phplib_id as uniqueid,
 + ​username as customer_id,​
 + '​default'​ as context,
 + ​username as mailbox,
 + ​vmail_password as password,
 + ​CONCAT(first_name,'​ ',​last_name) as fullname,
 + ​email_address as email,
 + NULL as pager,
 + ​datetime_created as stamp 
 +FROM openser.subscriber ​ WHERE vmail = TRUE;
 +
 +CREATE VIEW sip AS
 +SELECT ​ username as name,
 + ​username,​
 + '​friend'​ as type,
 + NULL as secret,
 + '​dynamic'​ as host,
 + ​CONCAT(rpid,​ ' ','<',​username,'>'​) as callerid,
 + '​default'​ as context,
 + ​username as mailbox,
 + '​no'​ as nat,
 + '​no'​ as qualify,
 + NULL as fromuser,
 + NULL as authuser,
 + NULL as fromdomain,
 + NULL as insecure,
 + '​no'​ as canreinvite,​
 + NULL as disallow,
 + NULL as allow,
 + NULL as restrictcid,​
 + NULL as ipaddr,
 + NULL as port,
 + NULL as regseconds
 +FROM openser.subscriber;​
 +</​code>​
 +
 +Next, you will need to modify the asterisk code base. This is unfortunate,​ but otherwise you will be unable to update the voicemail passwords.
 +
 +In asterisk-1.2.0/​apps/​app_voicemail.c,​ struct ast_vm_user should have a uniqueid size of 128. Like this:
 +
 +<​code>​
 +struct ast_vm_user {
 +        char context[AST_MAX_CONTEXT]; ​ /*!< Voicemail context */
 +        char mailbox[AST_MAX_EXTENSION];/​*!<​ Mailbox id, unique within vm context */
 +        char password[80]; ​             /*!< Secret pin code, numbers only */
 +        char fullname[80]; ​             /*!< Full name, for directory app */
 +        char email[80]; ​                /​*!<​ E-mail address */
 +        char pager[80]; ​                /​*!<​ E-mail address to pager (no attachment) */
 +        char serveremail[80]; ​          /​*!<​ From: Mail address */
 +        char mailcmd[160]; ​             /*!< Configurable mail command */
 +        char language[MAX_LANGUAGE]; ​   /*!< Config: Language setting */
 +        char zonetag[80]; ​              /​*!<​ Time zone */
 +        char callback[80];​
 +        char dialout[80];​
 +        char uniqueid[128]; ​             /*!< Unique integer identifier */
 +        char exit[80];
 +        unsigned int flags; ​            /​*!<​ VM_ flags */
 +        int saydurationm;​
 +        int maxmsg; ​                    /​*!<​ Maximum number of msgs per folder for this mailbox */
 +        struct ast_vm_user *next;
 +};
 +</​code>​
 +
 +Now, download the latest Asterisk addons package from the website. Compile and install both asterisk packages.
 +
 +In /​etc/​asterisk/​extconfig.conf,​ you will need to have:
 +
 +<​code>​
 +[settings]
 +sipusers => mysql,​asterisk,​sip
 +sippeers => mysql,​asterisk,​sip
 +voicemail => mysql,​asterisk,​voicemail
 +</​code>​
 +
 +Now you will need to specify how to connect asterisk.
 +
 +In /​etc/​asterisk/​res_mysql.conf insert:
 +
 +<​code>​
 +[general]
 +dbhost = localhost
 +dbname = asterisk
 +dbuser = asterisk
 +dbpass = asterisk
 +dbport = 3306
 +</​code>​
 +
 +This assumes that the user asterisk@localhost with password asterisk will be allowed to access the asterisk database. The code for adding this user is: <​code>​GRANT ALL ON asterisk.* to asterisk@localhost IDENTIFIED BY '​asterisk';</​code>​
 +
 +Allow sip calls in your sip.conf file (/​etc/​asterisk/​sip.conf):​
 +
 +<​code>​
 +[general]
 +context=default ;​ Default context for incoming calls
 +allowguest=yes ;​ Allow or reject guest calls (default is yes, this can also be set to '​osp'​
 +bindport=5060 ;​ UDP Port to bind to (SIP standard port is 5060)
 +bindaddr=0.0.0.0 ;​ IP address to bind to (0.0.0.0 binds to all)
 +srvlookup=yes ;​ Enable DNS SRV lookups on outbound calls
 +;​domain=voicemail ;​ Set default domain for this host
 +;​domain=mydomain.tld,​mydomain-incoming
 +;​domain=127.0.0.1 ;​ Add IP address as local domain
 +;​allowexternalinvites=no ;​ Disable INVITE and REFER to non-local domains
 +autodomain=yes ;​ Turn this on to have Asterisk add local host
 +pedantic=yes ;​ Enable slow, pedantic checking for Pingtel
 +;​tos=184 ;​ Set IP QoS to either a keyword or numeric val
 +;​tos=lowdelay ;​ lowdelay,​throughput,​reliability,​mincost,​none
 +;​maxexpiry=3600 ;​ Max length of incoming registration we allow
 +;​defaultexpiry=120 ;​ Default length of incoming/​outoing registration
 +;​notifymimetype=text/​plain ;​ Allow overriding of mime type in MWI NOTIFY
 +checkmwi=10 ;​ Default time between mailbox checks for peers
 +vmexten=default ​     ; dialplan extension to reach mailbox sets the 
 +;​videosupport=yes ;​ Turn on support for SIP video
 +;​recordhistory=yes ;​ Record SIP history by default ​
 +disallow=all ;​ First disallow all codecs
 +allow=ulaw ;​ Allow codecs in order of preference
 +language=en ;​ Default language setting for all users/peers
 +;​rtpholdtimeout=300 ;​ Terminate call if 300 seconds of no RTP activity
 +;trustrpid = no ; If Remote-Party-ID should be trusted
 +;sendrpid = yes ; If Remote-Party-ID should be sent
 +useragent=Asterisk PBX ; Allows you to change the user agent string
 +;dtmfmode = rfc2833 ; Set default dtmfmode for sending DTMF. Default: rfc2833
 + ; Other options: ​
 + ; info : SIP INFO messages
 + ; inband : Inband audio (requires 64 kbit codec -alaw, ulaw)
 + ; auto : Use rfc2833 if offered, inband otherwise
 +
 +[openser]
 +type=friend
 +context=default
 +host=localhost
 +insecure=very
 +
 +</​code>​
 +
 +Make sure to substitute the correct host for openser where it says host=localhost,​ or, if you are running OpenSER and Asterisk on the same host, change the port setting so that these servers will not conflict.
 +
 +Edit your voicemail.conf to how you like it. You should remove all default user and other user accounts listed there.
 +
 +Now, here is a sample extensions file to send incoming calls to voicemail.
 +
 +<​code>​
 +[general]
 +static=yes
 +writeprotect=no
 +autofallthrough=yes
 +clearglobalvars=no
 +priorityjumping=no
 +
 +[globals]
 +CONSOLE=Console/​dsp ​                            ; Console interface for demo
 +
 +[default]
 +exten => _XXXXXXXXXXX,​1,​Voicemail(su${EXTEN})
 +exten => _XXXXXXXXXXX,​2,​Hangup
 +
 +exten => a,​1,​VoicemailMain(${EXTEN})
 +exten => a,​2,​Playback(Goodbye)
 +exten => a,3,Hangup
 +
 +exten => *86,​1,​VoicemailMain(${CALLERIDNUM})
 +exten => *86,​2,​Hangup
 +</​code>​
 +
 +
 +In your openser.cfg,​ you will need to have it route calls to asterisk. This is usually done with some kind of failure route. Of some importance is making sure that calls timeout sooner than the default, 200 seconds. Here is a basic route. This is very new, and seems to work, but more testing is needed. You mileage may vary.
 +
 +<​code>​
 +
 +#tm timeout for voicemail params
 +modparam("​tm",​ "​fr_timer",​ 25)
 +modparam("​tm",​ "​fr_inv_timer",​ 25)
 +modparam("​tm",​ "​noisy_ctimer",​ 1)
 +
 +# ------------------------- ​ request routing logic -------------------
 +
 +# main routing logic
 +#Routing Script
 +route {
 + #​check for old messages: could mean a problem with the DNS entries or some other loop-causer...
 + if (!mf_process_maxfwd_header("​10"​))
 + {
 +   ​xlog("​L_WARN",​ "​WARNING:​ Too many hops\n"​);​
 +   ​sl_send_reply("​483",​ "Too many hops, forward count exceeded limit\n"​);​
 +   ​return;​
 + };
 +  ​
 + #​check for extremely large messages; we don't need a sip dos attack
 + if (msg:len >= 2048)
 + {
 +   ​xlog("​L_WARN",​ "​WARNING:​ Message too large, >= 2048 bytes\n"​);​
 +   ​sl_send_reply("​513",​ "​Message too large, exceeded limit\n"​);​
 +   ​return;​
 + };
 +  ​
 + #​record everything besides registers and acks
 + ​if(method!="​REGISTER"​ && method!="​ACK"​)
 + {
 +  setflag(1);
 + ​}; ​
 +  ​
 + #do not send to voicemail if BYE or CANCEL ​
 + #is used to end call before user pickup or timeout
 + ​if(method=="​CANCEL"​ || method=="​BYE"​)
 + {
 +  setflag(10);​
 + };
 + 
 + #​grant route if route headers already present
 + if (loose_route()) ​
 + ​{  ​
 +   ​route(1);​
 +   ​return;​
 + };
 +  ​
 + #​Always require authentication,​ which could result in a PSTN, ie $$$
 + if (method=="​REGISTER"​)
 + {
 +   ​if(!www_authorize("​domain.net",​ "​subscriber"​))
 +   {
 +    www_challenge("​domain.net",​ "​0"​);​
 +    return;
 +   }
 +   else
 +   {
 +    #Save into user database, used below when checking if user is available
 +    xlog("​L_INFO",​ "​REGISTER:​ User Authenticated Correctly\n"​);​
 +    save("​location"​);​
 +    return;
 +   };
 + };
 +  ​
 + if (method=="​INVITE"​)
 + {
 +  if (uri=~"​sip:​011[0-9]+@.*"​)
 +  {
 +   #​authorize if a call is going to PSTN 
 +   ​if(!proxy_authorize("​domain.net",​ "​subscriber"​))
 +   {
 +    proxy_challenge("​domain.net",​ "​0"​);​
 +    return;
 +   };
 + 
 +   ​xlog("​L_INFO",​ "CALL: Call to international number\n"​);​
 +   ​rewritehostport("​voip_gw.domain.net:​5060"​);​
 +  }
 +  else if(uri=~"​sip:​\*86@.*"​)
 +  {
 +   #​authorize if a call is going to PSTN 
 +   ​if(!proxy_authorize("​domain.net",​ "​subscriber"​))
 +   {
 +    proxy_challenge("​domain.net",​ "​0"​);​
 +    return;
 +   };
 + 
 +   ​xlog("​L_INFO",​ "CALL: Call to check voicemail\n"​);​
 +   ​rewritehostport("​vmail.domain.net:​5060"​);​
 +  }
 +  else
 +  {
 +   if (does_uri_exist())
 +   {
 +    #Call is to sip client, so do nothing but route
 +    xlog("​L_INFO",​ "CALL: Sip client\n"​);​
 +    if (!lookup("​location"​)) ​
 +    {
 +     ​sl_send_reply("​404",​ "Not Found"​);​
 +     ​log(1,​ "​ERROR:​ User Not Found\n"​);​
 +     ​return;​
 +    };
 +   }
 +   else
 +   {
 +    #authorize if a call is going to PSTN 
 +    if(!proxy_authorize("​domain.net",​ "​subscriber"​))
 +    {
 +     ​proxy_challenge("​domain.net",​ "​0"​);​
 +     ​return;​
 +    };
 + 
 +    #Call destination is PSTN, so send it to the gateway (Net.com)
 +    xlog("​L_INFO",​ "CALL: PSTN gateway\n"​);​
 +    rewritehostport("​voip_gw.domain.net:​5060"​);​
 +   };
 +  };
 +   
 +  #Make sure that all subsequent requests go through us;
 +  record_route();​
 + }
 + else
 + {
 +  if (does_uri_exist())
 +  {
 +   #Call is to sip client, so do nothing but route
 +   ​xlog("​L_INFO",​ "CALL: Sip client\n"​);​
 +   if (!lookup("​location"​)) ​
 +   {
 +    sl_send_reply("​404",​ "Not Found"​);​
 +    log(1, "​ERROR:​ User Not Found\n"​);​
 +    return;
 +   };
 +  }
 +  else
 +  {
 +   #Call destination is PSTN, so send it to the gateway (Net.com)
 +   ​xlog("​L_INFO",​ "CALL: PSTN gateway\n"​);​
 +   ​rewritehostport("​voip_gw.domain.net:​5060"​);​
 +  };
 +  record_route();​
 + };
 + 
 + #ALL PROCESSING IS DONE, SO ROUTE
 + ​route(1);​
 +}
 +
 +
 +route[1]
 +{
 +#send the call outward
 +
 + ​if(method=="​INVITE"​ && !isflagset(10))
 + {
 +  t_on_failure("​2"​);​
 + };
 + 
 + if (!t_relay()) ​
 + {
 +  xlog("​L_WARN",​ "​ERROR:​ t_relay failed"​);​
 +  sl_reply_error();​
 + };
 +
 +}
 +
 +failure_route[2]
 +{
 + ​if(!t_was_cancelled())
 + {
 +  revert_uri();​
 +  rewritehostport("​vmail.domain.net:​5060"​);​
 +  append_branch();​
 +  #PREVENT SOME CRAZY VOICEMAIL LOOP
 +  xlog("​L_INFO",​ "INFO: CALL TO VOICEMAIL"​);​
 +  setflag(10);​
 +  route(1);
 + }
 +}
 +</​code>​
 +
 +You can contact me at mikebwilliams@gmail.com
 +
 +Good Luck!
 +