Hi Greger,
Any conclusions or progress you have made after the discussion on the mailing list? I learned a few things :-) Tried to summarize my understanding of the different issues and how I understood the "recommended" approach, but didn't see any response from you.
There was a lot that had to be done in the meanwhile, sorry ;o)
But here's my current (not perfect but perfectly working) solution:
Locations are replicated on SIP-layer using forward_tcp(...) (thanks to Juha for the hint) on one side and save_noreply(...) on the other side. This works very reliable with three SERs although it wouldn't scale much, so this has to be improved in the future.
The config looks like:
if(method == "REGISTER") { if(src_ip==<IP of peer1> || src_ip==<IP of peer2>) { save_noreply("location"); } else { if(!www_authorize("<my domain>", "subscriber")) { www_challenge("<my domain>", "0"); break; } if(!check_to()) { sl_send_reply("403", "Use To=username next time"); break; } if(!save("location")) { sl_reply_error(); break; } forward_tcp("<IP of peer1", 5060); forward_tcp("<IP of peer2", 5060); } break; }
The usrloc modules operates in write-through-mode so locations are always synched to the db.
When a SER goes down, I've a script for recovering the location tables, and it looks like:
mysqldump -h${SER_PEER} -u${DB_RUSER} -p${DB_RPASS} -Q \ --extended-insert --add-drop-table ser ${SER_LOCATIONS} \ | mysql -u${DB_LUSER} -p${DB_LPASS} ser /usr/local/ser/sbin/ser.sh start
where $SER_LOCATIONS holds the location tables like "location", "aliases" and so on.
What still has to be done is replicating the nonce value so UAs with DNS-SRV implementations which change the server on each request and SERs behind load balancers will work too.
It's not as nifty as using diameter or something like that but it grants me some reprieve ;o)
For distributing FIFO commands to provision call forwards and read SER's status etc I wrote an XML-RPC server which communicates with SER's unixsocket-FIFO-interface. So a simple PHP script communicating with a SER looks like this:
$url = "http://my.server:5080/xmlrpc"; $method = "fifo.execute"; $fifocmd = "ul_show_contact"; $fifoparams = array("location", "012345");
$ar = array("cmdname"=>$fifocmd,"cmdparams"=>$fifoparams); $request = xmlrpc_encode_request($method, $ar);
$ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
$response = curl_exec($ch); $xmlar = xmlrpc_decode($response); if(xmlrpc_is_fault($xmlar)) { /* fault processing, print the error */ } else { /* normal processing, print the response parameters etc */ }
The XML-RPC solution seems to be more flexible to me than the TCP-interface for SER because it can not only execute FIFO commands but can easily be extended to communicate with the mediaproxy for example. But this opinion may depend on one's needs.
The licensing question of the XML-RPC server is still not clear (chiefs, you know), but I hope I get it licensed as GPL.
Cheers, Andy
Hi Andreas, Thank you for sharing your setup with the list! It is one more of several interesting reference designs/implementations that would be very useful to index and provide access to from the iptel.org site. I don't know who controls the iptel.org website? It could be as simple as a FAQ page where each FAQ item is a link to a specific post on mail.iptel.org (to keep the work down). I'm sure many basic questions on the list could be avoided with such a FAQ page.
See inline comments.
But here's my current (not perfect but perfectly working) solution:
Locations are replicated on SIP-layer using forward_tcp(...) (thanks to Juha for the hint) on one side and save_noreply(...) on the other side. This works very reliable with three SERs although it wouldn't scale much, so this has to be improved in the future.
The config looks like:
if(method == "REGISTER") { if(src_ip==<IP of peer1> || src_ip==<IP of peer2>) { save_noreply("location"); } else { if(!www_authorize("<my domain>", "subscriber")) { www_challenge("<my domain>", "0"); break; } if(!check_to()) { sl_send_reply("403", "Use To=username next time"); break; } if(!save("location")) { sl_reply_error(); break; } forward_tcp("<IP of peer1", 5060); forward_tcp("<IP of peer2", 5060); } break; }
The usrloc modules operates in write-through-mode so locations are always synched to the db.
I think the above is a good description of a simple, but generic replication setup.
When a SER goes down, I've a script for recovering the location tables, and it looks like:
mysqldump -h${SER_PEER} -u${DB_RUSER} -p${DB_RPASS} -Q \ --extended-insert --add-drop-table ser ${SER_LOCATIONS} \ | mysql -u${DB_LUSER} -p${DB_LPASS} ser /usr/local/ser/sbin/ser.sh start
where $SER_LOCATIONS holds the location tables like "location", "aliases" and so on.
If I understand you correctly, you dump on one server (one that is up) and load on the one that was down? Is this an automatic operation?
What still has to be done is replicating the nonce value so UAs with DNS-SRV implementations which change the server on each request and SERs behind load balancers will work too.
It's not as nifty as using diameter or something like that but it grants me some reprieve ;o)
Yes, this is where a DB setup gets complicated. However, maybe you could to reduce the time for the nonce to go stale? There is a variable for setting that value, I think the default is 300 seconds. The result would be many more authentications. I'm not completely sure how this works for sql, as we only use RADIUS auths, but I would imagine a new request to a new server where the nonce is wrong would result in a new auth? Or is the response a NAK and that's why you need replication? It seems to me that the messages in a single authentication (REGISTER, auth required, new REGISTER, ok) should go to the same server regardless of UA SRV implementation The next auth will be an INVITE probably and the nonce will probably be stale (300 secs) and result in a new auth. Also, a load balancer should (with reference to previous serusers discussions) probably make sure that all messages from one UA goes to the same server. At least is that true for an application level balancer, so that NAT problems are handled correctly. If the load balancer is a TCP/IP-level balancer, you should probably distribute on src_ip and thus avoid your nonce problem.
Sorry if this is not relevant to SQL auths... ;-)
For distributing FIFO commands to provision call forwards and read SER's status etc I wrote an XML-RPC server which communicates with SER's unixsocket-FIFO-interface. So a simple PHP script communicating with a SER looks like this:
$url = "http://my.server:5080/xmlrpc"; $method = "fifo.execute"; $fifocmd = "ul_show_contact"; $fifoparams = array("location", "012345");
$ar = array("cmdname"=>$fifocmd,"cmdparams"=>$fifoparams); $request = xmlrpc_encode_request($method, $ar);
$ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
$response = curl_exec($ch); $xmlar = xmlrpc_decode($response); if(xmlrpc_is_fault($xmlar)) { /* fault processing, print the error */ } else { /* normal processing, print the response parameters etc */ }
The XML-RPC solution seems to be more flexible to me than the TCP-interface for SER because it can not only execute FIFO commands but can easily be extended to communicate with the mediaproxy for example. But this opinion may depend on one's needs.
The licensing question of the XML-RPC server is still not clear (chiefs, you know), but I hope I get it licensed as GPL.
I agree with you, a pure TCP-interface is too low-level. I also agree with Juha in that an XML-RPC/SOAP implementation should be done as an extension to the current unix socket interface and be an integrated part of ser. Have you coded it in C? If so, maybe the code be used as a starting point (dependent on GPL from your chiefs)?
g-)