– Kamailio SIP Server –

Differences

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

Link to this comparison view

old-content:using_asterisk_as_a_voicemail_system [2006/08/26 02:00]
old-content:using_asterisk_as_a_voicemail_system [2006/08/26 02:00] (current)
Line 1: Line 1:
 +This is a tutorial on how to use OpenSER with Asterisk functioning as a voicemail server.
 +
 +===== Create the Database Views =====
 +
 +First, create the views described in [[OpenSER to Asterisk Realtime MySQL Views]]. This allows Asterisk to use the OpenSER's user table, so you don't have to manually replicate them.
 +
 +===== Modify Asterisk Codebase =====
 +
 +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>
 +
 +===== Install Asterisk Add-ons =====
 +
 +Now, download the latest Asterisk addons package from the website. Compile and install both asterisk packages.
 +
 +===== Configure Asterisk Realtime =====
 +
 +Now, it is time to specify where Asterisk should look for its realtime data. 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>
 +
 +===== Configure Asterisk SIP =====
 +
 +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.
 +
 +===== Configure Voicemail =====
 +
 +Edit your voicemail.conf to how you like it. You should remove all default user and other user accounts listed there.
 +
 +===== Configure Extensions =====
 +
 +This is the equivalent of OpenSER's route{}. 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>
 +
 +
 +
 +===== Set OpenSER to Route Calls to Voicemail =====
 +
 +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", 3)
 +modparam("tm", "fr_inv_timer", 35)
 +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
 +   {
 +      if (!check_to()) 
 +      {
 + sl_send_reply("401", "Unauthorized");
 + return;
 +      };
 +
 +    #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:\*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!
 +