Push Notification with Kamailio

This brief tutorial shows how to “freeze” SIP transaction to the moment the subscriber wakes up. The logic is simple here:

  • Asterisk sends SIP INVITE to Kamailio SIP Proxy
  • Kamailio detects device type by specific X-header and freezes incoming SIP transaction
  • Kamailio sends “push” via http request to PHP script
  • Once Kamailio detects new REGISTER from device, it resumes transaction
  • Kamailio sends SIP INVITE to the subscriber

Module settings:

#htable module setting. vtp keeps transaction details.modparam("htable", "htable", "vtp=>size=10;autoexpire=120;")

Kamailio script building blocks:

#Detecting device type via custom SIP header X-phone.if ( (is_method("INVITE")) && (!has_totag()) && ($(hdr(X-phone) =~ "iphone") ) {
  send_reply("100", "Suspending");
  route(SUSPEND);
}#Suspending transaction and store index and label in vtp for the future needs.route[SUSPEND] {
  if ( !t_suspend() ) {
    xlog("L_ERROR","[SUSPEND]  failed suspending trasaction [$T(id_index):$T(id_label)]\n");
    send_reply("501", "Suspending error");
    exit;
  } else {
    xlog("L_INFO","[SUSPEND]  suspended transaction [$T(id_index):$T(id_label)] $fU=> $rU\n");
    $sht(vtp=>id_index::$rU) = $T(id_index);
    $sht(vtp=>id_label::$rU) = $T(id_label);
    xlog("L_INFO","[SUSPEND] htable key value [$sht(vtp=>id_index::$rU)   --   $sht(vtp=>id_label::$rU)]\n");
    route(SENDPUSH);
    exit;
  }

In my case Kamailio runs the intermediate PHP script (push.php) with needed parameters for sending request to APN. You might use app_luamodule to push directly from Kamailio.

#Below is a pushing service. It calls push.php script with parameters. Htable $sht(tokens=>$rU) keeps needed token. And after PHP script connects to APN.route[SENDPUSH] {
  ...
  http_client_query("http://url/push.php", "user=$rU\r\npn-tok=$sht(tokens=>$rU)\r\n","Content-Type: text/plain", "$var(result)");
  ...
  sl_send_reply("100", "Pushing");
}

Here we are detecting incoming REGISTER message from pushed device:

#Unfreezing by new incoming REGISTER message. if ( (is_method("REGISTER")) && (($hdr(Expires) != "0") || ($hdr(Contact) !~ "expires=0")) && ($sht(vtp=>id_index::$tU) != $null) ) {
  xlog("L_INFO", "New $rm ru=$ru tu=$tu \n");
  route(JOIN);
}

Resuming SIP transaction using stored label and index:

#Resuming transaction.route[JOIN] {
  xlog("L_INFO","[JOIN] htable key value [$sht(vtp=>id_index::$tU)   --   $sht(vtp=>id_label::$tU)]\n");
  t_continue("$sht(vtp=>id_index::$tU)", "$sht(vtp=>id_label::$tU)", "RESUME");
}#Lookup into location database and relaying.route[RESUME] {
  lookup("location");
  xlog("L_INFO","[RESUME] rm=$rm ru=$ru du=$du \n");
  t_relay();
  exit;
}

你可能感兴趣的:(Push Notification with Kamailio)