[OpenSIPS-Users] Calculate the nearest destination based on GeoIP

Dmitry netaskd at gmail.com
Wed Mar 20 06:34:34 EDT 2019

in addition, for now I use logic like this:

route[GEOIP_DST] {
  # lookup by IP
  if (!mmg_lookup("lon:lat","$avp(upstreamip)","$avp(lat_lon)")) {
    xlog("L_INFO", "[GEOIP_DST] $rm $avp(upstreamip) - is not external IP address\n");

  xlog("L_INFO", "[GEOIP_DST] $C(gx)$rm - $avp(upstreamip) is external. will calculate the nearest destination$C(xx)\n");
  xlog("L_NOTICE","[GEOIP_DST] $rm - source IP=$avp(upstreamip) latitude:$(avp(lat_lon)[0]) and longitude:$(avp(lat_lon)[1])\n");

  # set default vars
  $var(rad) = 6372; # len earth in km
  $var(min) = $var(rad); # min len between the client and candidate in km
  $var(pi) = "3.141492";
  $var(id) = 0; # start search from this id position in dispatcher table from attrs column
  $var(maxid) = 50; # finish to this position

  # coordinates client's in rad
  math_eval("$(avp(lat_lon)[0]) * $var(pi) / 180", "$var(lat1)");
  math_eval("$(avp(lat_lon)[1]) * $var(pi) / 180", "$var(lon1)");

  while ( $var(id) < $var(maxid) ) {
    $var(dst) = $sql_cached_value(id:destination:$var(id));
    $var(coo) = $sql_cached_value(id:attrs:$var(id));
    if ($var(coo)) {
      # coordinates candidates in rad
      math_eval("$(var(coo){s.select,0,,}) * $var(pi) / 180","$var(lat2)");
      math_eval("$(var(coo){s.select,1,,}) * $var(pi) / 180","$var(lon2)");
      # calculate trigonometry
      math_eval("sin($var(lat1))", "$var(slat1)");
      math_eval("sin($var(lat2))", "$var(slat2)");
      math_eval("cos($var(lat1))", "$var(clat1)");
      math_eval("cos($var(lat2))", "$var(clat2)");
      math_eval("$var(lon2) - $var(lon1)", "$var(delta)");
      math_eval("cos($var(delta))", "$var(cdelta)");
      math_eval("$var(slat1) * $var(slat2) + $var(clat1) * $var(clat2) * $var(cdelta)", "$var(cdw)");
      math_round("$var(cdw)", "$var(cd)", "4");
      math_eval("acos($var(cd))", "$var(d)");
      math_eval("$var(d) * $var(rad)", "$var(len)");
      # or just use linear algebra
      #math_eval("sqrt((($(avp(lat_lon)[0]) - $(avp(g:coo){s.select,0,,})) ^ 2) + (($(avp(lat_lon)[1]) - $(avp(g:coo){s.select,1,,})) ^ 2))", "$var(len)");
      # cut float pont, use decimal
      $var(len) = $(var(len){s.select,0,.}{s.int});
      # calculate minimal destination
      if ( $var(len) < $var(min) ) {
        xlog("L_INFO", "===== dst=$var(dst) len=$var(len) min=$var(min) id=$var(id) =====\n");
        $var(min) = $var(len);
        $avp(media_dst) = $var(dst);
    # counter item
    $var(id) = $var(id) + 1;
  xlog("L_NOTICE", "[GEOIP_DST] $rm - selected destination $C(gx)$avp(media_dst)$C(xx)\n");

-----Original Message-----
From: Dmitry <netaskd at gmail.com> 
Sent: Wednesday, March 20, 2019 1:00 PM
To: 'users at lists.opensips.org' <users at lists.opensips.org>
Subject: Calculate the nearest destination based on GeoIP

Hi there,
Maybe you know the best way to calculate the nearest routing point based on geoip data?
an example:
I have 3 rtpengine relays on a different country, and I can set its geo-coordinate in DB and set id for each of them via rtpengine_use_set() function in the routing script.
Also, I have goip lookup via mmg_lookup() function that can give me a coordinate a caller by IP address.
A caller comes from the country that _doesn't have_ rtpengine relay and I need to calculate the nearest rtpengine id for set it as prefer based on its IP address Any advice is appreciated.

More information about the Users mailing list