1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "softbus_sequence_verification.h"
17 #include "comm_log.h"
18 
19 #define MAX_SEQ_BIAS 60
20 
IsDifferentSign(int32_t seqA,int32_t seqB)21 static bool IsDifferentSign(int32_t seqA, int32_t seqB)
22 {
23     if ((seqA >= 0 && seqB >= 0) || (seqA < 0 && seqB < 0)) {
24         return false;
25     }
26     return true;
27 }
28 
IsPassDuplicateCheck(SeqVerifyInfo * seqVerifyInfo,int32_t recvSeq)29 static bool IsPassDuplicateCheck(SeqVerifyInfo *seqVerifyInfo, int32_t recvSeq)
30 {
31     uint32_t offset = (uint32_t)(seqVerifyInfo->maxSeq - recvSeq);
32     uint64_t isRepeat = seqVerifyInfo->recvBitmap & (0x1UL << offset);
33     if (isRepeat) {
34         COMM_LOGI(COMM_VERIFY, "duplicated package seq. recvSeq=%{public}d", recvSeq);
35         return false;
36     }
37     seqVerifyInfo->recvBitmap |= (0x1UL << offset);
38     return true;
39 }
40 
IsPassOverMaxCheck(SeqVerifyInfo * seqVerifyInfo,int32_t recvSeq)41 static bool IsPassOverMaxCheck(SeqVerifyInfo *seqVerifyInfo, int32_t recvSeq)
42 {
43     /* consider flip */
44     if (recvSeq - seqVerifyInfo->maxSeq < 0) {
45         return false;
46     }
47 
48     if (recvSeq - seqVerifyInfo->minSeq >= MAX_SEQ_BIAS) {
49         COMM_LOGE(COMM_VERIFY, "seq bias reach max. MAX_SEQ_BIAS=%{public}d", MAX_SEQ_BIAS);
50         return false;
51     }
52     uint32_t seqOffset = (uint32_t)(recvSeq - seqVerifyInfo->maxSeq + 1);
53     seqVerifyInfo->maxSeq = ++recvSeq;
54     seqVerifyInfo->recvBitmap = seqVerifyInfo->recvBitmap << seqOffset;
55     /* 1: represent the penultimate bit of recvBitmap is 1. */
56     seqVerifyInfo->recvBitmap |= (0x1UL << 1);
57     return true;
58 }
59 
IsPassAllRangeCheck(SeqVerifyInfo * seqVerifyInfo,int32_t recvSeq)60 static bool IsPassAllRangeCheck(SeqVerifyInfo *seqVerifyInfo, int32_t recvSeq)
61 {
62     if (recvSeq == seqVerifyInfo->minSeq) {
63         seqVerifyInfo->minSeq = ++recvSeq;
64         return true;
65     }
66 
67     if (recvSeq > seqVerifyInfo->minSeq) {
68         if (recvSeq < seqVerifyInfo->maxSeq) {
69             return IsPassDuplicateCheck(seqVerifyInfo, recvSeq);
70         }
71         return IsPassOverMaxCheck(seqVerifyInfo, recvSeq);
72     }
73     return false;
74 }
75 
IsPassNormalCheck(SeqVerifyInfo * seqVerifyInfo,int32_t recvSeq)76 static bool IsPassNormalCheck(SeqVerifyInfo *seqVerifyInfo, int32_t recvSeq)
77 {
78     /* normal case */
79     if (recvSeq == seqVerifyInfo->minSeq) {
80         seqVerifyInfo->minSeq = recvSeq + 1;
81         seqVerifyInfo->maxSeq = recvSeq + 1;
82         return true;
83     }
84     /* first disorder package, recvSeq and minSeq/maxSeq are same signs. */
85     if (!IsDifferentSign(recvSeq, seqVerifyInfo->minSeq)) {
86         if (recvSeq > seqVerifyInfo->maxSeq) {
87             return IsPassOverMaxCheck(seqVerifyInfo, recvSeq);
88         }
89         return false;
90     }
91     /* first disorder package, recvSeq and minSeq/maxSeq are different signs. */
92     return IsPassOverMaxCheck(seqVerifyInfo, recvSeq);
93 }
94 
IsPassNoflipDisorderCheck(SeqVerifyInfo * seqVerifyInfo,int32_t recvSeq)95 static bool IsPassNoflipDisorderCheck(SeqVerifyInfo *seqVerifyInfo, int32_t recvSeq)
96 {
97     if (seqVerifyInfo->minSeq >= 0) {
98         if (recvSeq >= 0) {
99             return IsPassAllRangeCheck(seqVerifyInfo, recvSeq);
100         }
101         return IsPassOverMaxCheck(seqVerifyInfo, recvSeq);
102     }
103     if (seqVerifyInfo->maxSeq < 0) {
104         if (recvSeq < 0) {
105             return IsPassAllRangeCheck(seqVerifyInfo, recvSeq);
106         }
107         return IsPassOverMaxCheck(seqVerifyInfo, recvSeq);
108     }
109     /* can not reach here. */
110     return false;
111 }
112 
IsPassFlipPositiveCheck(SeqVerifyInfo * seqVerifyInfo,int32_t recvSeq)113 static bool IsPassFlipPositiveCheck(SeqVerifyInfo *seqVerifyInfo, int32_t recvSeq)
114 {
115     if (recvSeq >= 0) {
116         if (recvSeq < seqVerifyInfo->maxSeq) {
117             return IsPassDuplicateCheck(seqVerifyInfo, recvSeq);
118         }
119         return IsPassOverMaxCheck(seqVerifyInfo, recvSeq);
120     } else {
121         if (recvSeq == seqVerifyInfo->minSeq) {
122             seqVerifyInfo->minSeq = ++recvSeq;
123             return true;
124         }
125         if (recvSeq > seqVerifyInfo->minSeq) {
126             return IsPassDuplicateCheck(seqVerifyInfo, recvSeq);
127         }
128         return false;
129     }
130     /* can not reach here. */
131     return false;
132 }
133 
IsPassFlipNegativeCheck(SeqVerifyInfo * seqVerifyInfo,int32_t recvSeq)134 static bool IsPassFlipNegativeCheck(SeqVerifyInfo *seqVerifyInfo, int32_t recvSeq)
135 {
136     if (recvSeq >= 0) {
137         if (recvSeq == seqVerifyInfo->minSeq) {
138             seqVerifyInfo->minSeq = ++recvSeq;
139             return true;
140         }
141         if (recvSeq > seqVerifyInfo->minSeq) {
142             return IsPassDuplicateCheck(seqVerifyInfo, recvSeq);
143         }
144         return false;
145     } else {
146         if (recvSeq < seqVerifyInfo->maxSeq) {
147             return IsPassDuplicateCheck(seqVerifyInfo, recvSeq);
148         }
149         return IsPassOverMaxCheck(seqVerifyInfo, recvSeq);
150     }
151     /* can not reach here. */
152     return false;
153 }
154 
IsPassSeqCheck(SeqVerifyInfo * seqVerifyInfo,int32_t recvSeq)155 bool IsPassSeqCheck(SeqVerifyInfo *seqVerifyInfo, int32_t recvSeq)
156 {
157     if (seqVerifyInfo == NULL) {
158         COMM_LOGE(COMM_VERIFY, "invalid param.");
159         return false;
160     }
161     bool isDifferentSign = IsDifferentSign(seqVerifyInfo->minSeq, seqVerifyInfo->maxSeq);
162     if (seqVerifyInfo->minSeq == seqVerifyInfo->maxSeq) {
163         return IsPassNormalCheck(seqVerifyInfo, recvSeq);
164     }
165     if ((seqVerifyInfo->minSeq < seqVerifyInfo->maxSeq) && !isDifferentSign) {
166         return IsPassNoflipDisorderCheck(seqVerifyInfo, recvSeq);
167     }
168     if ((seqVerifyInfo->minSeq > seqVerifyInfo->maxSeq) && isDifferentSign) {
169         return IsPassFlipNegativeCheck(seqVerifyInfo, recvSeq);
170     }
171     if ((seqVerifyInfo->minSeq < seqVerifyInfo->maxSeq) && isDifferentSign) {
172         return IsPassFlipPositiveCheck(seqVerifyInfo, recvSeq);
173     }
174     /* can not reach here. */
175     return false;
176 }
177