如何在Asterisk/FreeSWITCH环境下实现PUSH功能支持

很多手机不能支持手机APP一直在后台运行,这样的话,手机耗电相当厉害。如果APP处于休眠状态的话,电话呼入以后就会出现漏接的问题。为了保证手机app 那个正常接听呼入的呼叫,需要通过推送PUSH消息提醒来唤醒手机的SIP软电话。最近一个客户问笔者这个问题,所以为了回答客户的问题,笔者网上找到了这个比较可行的,经济的办法来解决这个问题。今天,我们就和大家分享一下这个解决方法的具体实现过程。

目前市场上的很多商业软件可以支持PUSH功能。很多手机的操作系统都支持各自Push Notification Service(PNS),例如苹果的APNS和安卓Google的FCM。

这里,我们主要分享一个如何使用zoiper结合Windows phone 8 实现的大概流程,配合开源Asterisk或者FreeSWITCH的解决办法,用户可以自己测试。这里,在SIP的数据包中发送了一个 X-PUSH-URI 拓展头,包括了一个PUSH URL。具体的SIP消息如下:

REGISTER sip:10.2.1.9:6060;transport=UDP SIP/2.0Via: SIP/2.0/UDP 10.8.3.36:52685;branch=z9hG4bK-d8754z-a48cbc16a2db2714-1---d8754z-;rportMax-Forwards: 70Contact: X-PUSH-URI=http://db3.notify.live.net/throttledthirdparty/01.00/AQEVPwmdC_zuSZiednVGrPo6AgAAAAADOwAAAAQUZm52OkE0QUNBREI0MTdBQzBCNjQFBlVTTkMwMQ>To: From: ;tag=7b68d666Call-ID: YTE4ZWZhMmEyYjk2ZDdjM2VkZTM5YzBlYmNmNGE4ZjQ.CSeq: 1 REGISTERExpires: 60Allow: INVITE, ACK, CANCEL, BYE, NOTIFY, REFER, MESSAGE, OPTIONS, INFO, SUBSCRIBESupported: replaces, norefersub, extended-refer, timer, X-cisco-serviceuriUser-Agent: Zoiper r21941Allow-Events: presence, kpmlContent-Length: 0

此URL 通过定位服务器来获取到详细其信息,然后通过HTTP POST request 发送到手机的APP上。几个几秒钟的唤醒处理,手机APP可以接受呼叫来电。以下是Asterisk 环境下的拨号规则:

exten => 1001,1,Answer;exten => 1001,n,Set(location=$)exten => 1001,n,Verbose(0, getting push info $ );exten => 1001,n,Set(regx="X-PUSH-URI=([0-9a-zA-Z\.\:\/\_]+)")exten => 1001,n,Set(push=$["$" =~ $])exten => 1001,n,System(/usr/bin/push.sh $); // 处理AGI 脚本exten => 1001,n,Wait(3);exten => 1001,n,Dial(SIP/1001); // 然后拨打1001 分机。

在此路径下保存脚本,执行执行权限设置 执行chmod。

/usr/bin/push.sh

push.sh 基本代码如下,大概处理流程是另外一个客户的示例,用户可以自己修改来做实验。这里的消息推送使用的是谷歌的FCM,用户可以选择自己国内的平台。

#!/opt/bin/php-cli -q

$db2=newSQLite3('/opt/etc/asterisk/tokens.sqlite3'); // 使用数据库

$API_ACCESS_KEY=''; 获取服务器的API访问权限。。

$f=fopen("/tmp/log.txt","w"); // 打开一个log文件。

$key="";

$k=$argv[1];

if(isset($argv[2])) { // 从拨号规则获得AGI参数

$v=$argv[2];

if(preg_match('/pn-tok=([^;]+)/i', $v,$token)) {

$v=$token[1];

$db2->query("delete from keys where key='$k'");

$db2->query("insert into keys values( '$k','$v')");

fwrite($f,"got token $v\r\n");

}

fwrite($f,"k=$k, v=$v\r\n");

}

//we read here in case we didnt get a new token so use the stored value

$results=$db2->query("SELECT value FROM keys where key = '$k'"); // 查询sql lite 数据库

if($row=$results->fetchArray())

$key=$row["value"];

if($key !="") {

fwrite($f,"key=$key\r\n");

$registrationIds =array($key) ;

$msg =array

(

'title'=>'Notification',

'body'=>'Wake Up'

);

$fields =array

(

'registration_ids'=> $registrationIds,

'data'=> $msg,

'priority'=>10

);

$headers =array

(

'Authorization: key='. $API_ACCESS_KEY,

'Content-Type: application/json'

);

$ch = curl_init();

curl_setopt( $ch,CURLOPT_URL,'https://fcm.googleapis.com/fcm/send' // 这里是一个HTTP 的服务器,提供此服务,用户可以使用其他第三方的HTTP 服务来实现。

);

curl_setopt( $ch,CURLOPT_POST,true);

curl_setopt( $ch,CURLOPT_HTTPHEADER, $headers );

curl_setopt( $ch,CURLOPT_RETURNTRANSFER,true);

curl_setopt( $ch,CURLOPT_SSL_VERIFYPEER,false);

curl_setopt( $ch,CURLOPT_POSTFIELDS, json_encode( $fields ) );

$result = curl_exec($ch );

curl_close( $ch );

fwrite($f,"$result\r\n");

}// if key

fclose($f);

如果用户使用FreeSIWTCH的话,需要修改拨号规则执行流程:

" // 设置参数 // 执行push 脚本sleep" data="2000"/> // 等待时间,然后进行下一步的呼叫流程。

以上测试方法仅限于zoiper的示例,用户可以参考此示例对其他的软电话进行测试。这里仅仅提供了一种PUSH的思路,用户可以修改代码来支持更灵活的第三方服务器。另外,此PUSH的解决方案基本上和SIP PUSH协议的技术架构非常类似,但是没有完全遵守这个草案:

Push Notification with the Session Initiation Protocol (SIP)

draft-ietf-sipcore-sip-push-11

软交换对PUSH的处理也是非常重要一步,这里涉及了消息回复的问题,时间的问题和安全机制的问题和服务器管理的问题。因此,如果用户需要部署大规模的消息推送解决方案,建议首先查阅这份草案。

官方链接和push脚本:https://www.zoiper.com/en/tutorials/push-notifications

SIP-PUSH协议:https://tools.ietf.org/html/draft-ietf-sipcore-sip-push-11

  • 发表于:
  • 原文链接:https://kuaibao.qq.com/s/20181115G08XQE00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券