×

【转】smslib-3.5.4&长短信BUG修复及原理讲解

woxigouadmin woxigouadmin 发表于2020-06-03 12:08:37 浏览612 评论0

抢沙发发表评论

背景:


       项目中使用了开源库smslib-3.5.4与GSM-Modem通信实现短信收发(包括使用长短信)。使用中发现该开源库对长短信的处理存在BUG,如:


       1、当长短信的REF值为0时,会当作是普通单条短信,不作拼接;


       2、当收到多个手机端过来的长短信时,拼接内容会乱,或接收不到部分短信,或手机卡短信塞满;




原因:


       1、org.smslib.modem.ModemGateway.readMessagesPDU()中判断是否为长短信息使用了如下逻辑:


if (msg.getMpRefNo() == 0)
{
// single message
msgList.add(msg);
incInboundMessageCount();
}
else
{
// multi-part message
...
}

              因为在标准(《GSM 03.40 V7.2.0》 “9.2.3.24.1 Concatenated Short Messages”)里REF的值的取值范围为[0,255],故此处按REF值为0来判断是单条短信是错误的;


       2、org.smslib.modem.ModemGateway.readMessagesPDU()中判断长短信分块是否属于同一长短信时使用了如下逻辑:


// check if current message list is for this message
if (listMsg.getMpRefNo() == msg.getMpRefNo())

              这逻辑只根据短信的REF值相同就认为是属于同一长短信,这是不合理的,因为这个REF值是发送方自己选择的,当多个发送端时,很有可能存在某些发送端同时选择了同一个REF值作为它们所发长短信的REF值,服务端此时接收到这些长短信时,若按上述原逻辑,则会认为这些不同发送端过来的长短信分块都是同一长短信的分块,最后导致同分块号的分块拼接到其他发送者,或不被处理(进而产生孤儿短信)




解决:


       1、修改该逻辑源码为:


if (msg.getMpMaxNo() == 0)
{
// single message
msgList.add(msg);
incInboundMessageCount();
}
else
{
// multi-part message
...
}


       2、修改该逻辑源码为:

// check if current message list is for this message
if (listMsg.getMpRefNo() == msg.getMpRefNo() && listMsg.getMpMaxNo() == msg.getMpMaxNo() && listMsg.getOriginator().equals(msg.getOriginator()) && (distanceOfDate(listMsg.getDate(), msg.getDate()) < 1000*60*30))

              该逻辑加入了分块必须满足以下条件才认为是属于同一长短信:


              1) 标识值相等;


              2) 总分块数相等;


              3) 发送者相同;


              4) 发送时间间隔不超过30秒(这个可以根据自己的场景定义分块间最大间隔时间)


————————————————

版权声明:本文为CSDN博主「RdaOniCelK」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/rdaonicelk/article/details/47998147