1 /*
2  * Copyright (c) 2024 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 <cinttypes>
17 #include <map>
18 #include <gtest/gtest.h>
19 #include "common.h"
20 #include "session.h"
21 #include "tmessenger.h"
22 
23 #define WAIT_TIMEOUT 5
24 
25 using namespace testing::ext;
26 
27 namespace OHOS {
28 class StreamEncryptClientMt : public testing::Test {
29 public:
StreamEncryptClientMt()30     StreamEncryptClientMt() { }
~StreamEncryptClientMt()31     ~StreamEncryptClientMt() { }
32     static void SetUpTestCase(void);
33     static void TearDownTestCase(void);
SetUp()34     void SetUp() override { }
TearDown()35     void TearDown() override { }
36 };
37 
SetUpTestCase(void)38 void StreamEncryptClientMt::SetUpTestCase(void)
39 {
40     int32_t ret = TestInit();
41     ASSERT_EQ(ret, SOFTBUS_OK);
42 
43     ret = TMessenger::GetInstance().Open(PKG_NAME, TEST_NOTIFY_NAME, TEST_NOTIFY_SRV_NAME, false);
44     ASSERT_EQ(ret, SOFTBUS_OK);
45 }
46 
TearDownTestCase(void)47 void StreamEncryptClientMt::TearDownTestCase(void)
48 {
49     int32_t ret = TestDeInit();
50     ASSERT_EQ(ret, SOFTBUS_OK);
51     TMessenger::GetInstance().Close();
52 }
53 
OnShutdownClient(int32_t socket,ShutdownReason reason)54 void OnShutdownClient(int32_t socket, ShutdownReason reason)
55 {
56     LOGI(">> OnShutdownClient {socket:%d, reason:%d}", socket, reason);
57 }
58 
59 static ISocketListener g_listener = {
60     .OnBind = nullptr,
61     .OnShutdown = OnShutdownClient,
62     .OnBytes = nullptr,
63     .OnMessage = nullptr,
64     .OnStream = nullptr,
65     .OnFile = nullptr,
66     .OnQos = nullptr,
67 };
68 
IsTestOk(bool isLocalEncrypt,const std::string sendData,const std::shared_ptr<Response> & resp)69 bool IsTestOk(bool isLocalEncrypt, const std::string sendData, const std::shared_ptr<Response> &resp)
70 {
71     if (resp == nullptr) {
72         LOGE("the response is null");
73         return false;
74     }
75 
76     bool isPeerEncrypt = resp->isEncrypt_;
77     std::string recvData = resp->recvData_;
78 
79     LOGI("isLocalEncrypt:%d, sendData:%s", isLocalEncrypt, sendData.c_str());
80     LOGI("isPeerEncrypt:%d, recvData:%s", isPeerEncrypt, recvData.c_str());
81     if (isLocalEncrypt == isPeerEncrypt) {
82         return sendData == recvData;
83     } else {
84         return sendData != recvData;
85     }
86 }
87 
SendStreamExt(int32_t socket)88 static int32_t SendStreamExt(int32_t socket)
89 {
90     std::string src = TEST_STREAM_DATA;
91     StreamData data = {
92         .buf = (char *)(src.c_str()),
93         .bufLen = src.size(),
94     };
95     StreamData ext = { 0 };
96     StreamFrameInfo param = { 0 };
97     return SendStream(socket, &data, &ext, &param);
98 }
99 
100 /*
101  * @tc.name: RawStreamEncryptTest001
102  * @tc.desc: Unencrypted raw stream data transmission test
103  * @tc.type: FUNC
104  * @tc.require:
105  */
106 HWTEST_F(StreamEncryptClientMt, RawStreamEncryptTest001, TestSize.Level1)
107 {
108     /**
109      * @tc.steps: step 1. set dataType is DATA_TYPE_RAW_STREAM and create socket by 'Socket' function.
110      * @tc.expect: socket greater zero.
111      */
112     SocketInfo info = {
113         .name = (char *)TEST_SESSION_NAME,
114         .pkgName = (char *)PKG_NAME,
115         .peerName = (char *)TEST_SESSION_NAME_SRV,
116         .peerNetworkId = NULL,
117         .dataType = DATA_TYPE_RAW_STREAM,
118     };
119     info.peerNetworkId = WaitOnLineAndGetNetWorkId();
120     int32_t socket = Socket(info);
121     ASSERT_GT(socket, 0);
122 
123     /**
124      * @tc.steps: step 2. set Qos data and call 'Bind' function.
125      * @tc.expect: 'Bind' function return SOFTBUS_OK.
126      */
127     QosTV qosInfo[] = {
128         {.qos = QOS_TYPE_MIN_BW,       .value = 80  },
129         { .qos = QOS_TYPE_MAX_LATENCY, .value = 4000},
130         { .qos = QOS_TYPE_MIN_LATENCY, .value = 2000},
131         { .qos = QOS_TYPE_RTT_LEVEL, .value = RTT_LEVEL_LOW},
132     };
133     int32_t ret = Bind(socket, qosInfo, sizeof(qosInfo) / sizeof(qosInfo[0]), &g_listener);
134     ASSERT_EQ(ret, SOFTBUS_OK);
135 
136     /**
137      * @tc.steps: step 3. call 'SendStream' to send unencrypted raw stream data.
138      * @tc.expect: 'SendStream' function return SOFTBUS_OK.
139      */
140     ret = SendStreamExt(socket);
141     ASSERT_EQ(ret, SOFTBUS_OK);
142 
143     /**
144      * @tc.steps: step 4. call 'Wait' function to get test results returned by server side.
145      * @tc.expect: 'IsTestOk' function return true.
146      */
147     std::shared_ptr<Response> resp = TMessenger::GetInstance().QueryResult(WAIT_TIMEOUT);
148     bool testResult = IsTestOk(false, TEST_STREAM_DATA, resp);
149     ASSERT_TRUE(testResult);
150 
151     Shutdown(socket);
152 }
153 
154 /*
155  * @tc.name: RawStreamEncryptTest002
156  * @tc.desc: Encrypted raw stream data transmission test
157  * @tc.type: FUNC
158  * @tc.require:
159  */
160 HWTEST_F(StreamEncryptClientMt, RawStreamEncryptTest002, TestSize.Level1)
161 {
162     /**
163      * @tc.steps: step 1. set dataType is DATA_TYPE_RAW_STREAM_ENCRYPED and create socket by 'Socket' function.
164      * @tc.expect: socket greater zero.
165      */
166     SocketInfo info = {
167         .name = (char *)TEST_SESSION_NAME,
168         .pkgName = (char *)PKG_NAME,
169         .peerName = (char *)TEST_SESSION_NAME_SRV,
170         .peerNetworkId = nullptr,
171         .dataType = DATA_TYPE_RAW_STREAM_ENCRYPED,
172     };
173     info.peerNetworkId = WaitOnLineAndGetNetWorkId();
174     int32_t socket = Socket(info);
175     ASSERT_GT(socket, 0);
176 
177     /**
178      * @tc.steps: step 2. set Qos data and call 'Bind' function.
179      * @tc.expect: 'Bind' function return SOFTBUS_OK.
180      */
181     QosTV qosInfo[] = {
182         {.qos = QOS_TYPE_MIN_BW,       .value = 80  },
183         { .qos = QOS_TYPE_MAX_LATENCY, .value = 4000},
184         { .qos = QOS_TYPE_MIN_LATENCY, .value = 2000},
185     };
186     int32_t ret = Bind(socket, qosInfo, sizeof(qosInfo) / sizeof(qosInfo[0]), &g_listener);
187     ASSERT_EQ(ret, SOFTBUS_OK);
188 
189     /**
190      * @tc.steps: step 3. call 'SendStream' to send encrypted raw stream data.
191      * @tc.expect: 'SendStream' function return SOFTBUS_OK.
192      */
193     ret = SendStreamExt(socket);
194     ASSERT_EQ(ret, SOFTBUS_OK);
195 
196     /**
197      * @tc.steps: step 4. call 'Wait' function to get test results returned by server side.
198      * @tc.expect: 'IsTestOk' function return true.
199      */
200     std::shared_ptr<Response> resp = TMessenger::GetInstance().QueryResult(WAIT_TIMEOUT);
201     bool testResult = IsTestOk(true, TEST_STREAM_DATA, resp);
202     ASSERT_TRUE(testResult);
203 
204     Shutdown(socket);
205 }
206 
207 class SessionStateManager {
208 public:
GetInstance()209     static SessionStateManager &GetInstance()
210     {
211         static SessionStateManager instance;
212         return instance;
213     }
214 
EnableSessionId(int32_t sessionId)215     void EnableSessionId(int32_t sessionId)
216     {
217         if (sessionId <= 0) {
218             return;
219         }
220 
221         std::unique_lock<std::mutex> lock(sessionIdMutex_);
222         sessionIdMap_.insert({ sessionId, true });
223         lock.unlock();
224         sessionIdCond_.notify_one();
225     }
226 
UnenableSessionId(int32_t sessionId)227     void UnenableSessionId(int32_t sessionId)
228     {
229         if (sessionId <= 0) {
230             return;
231         }
232 
233         std::unique_lock<std::mutex> lock(sessionIdMutex_);
234         sessionIdMap_.erase(sessionId);
235     }
236 
WaitEnableSession(int32_t sessionId,uint32_t timeout)237     bool WaitEnableSession(int32_t sessionId, uint32_t timeout)
238     {
239         bool isEnable = false;
240         std::unique_lock<std::mutex> lock(sessionIdMutex_);
241         sessionIdCond_.wait_for(lock, std::chrono::seconds(timeout), [&] {
242             auto it = sessionIdMap_.find(sessionId);
243             if (it == sessionIdMap_.end()) {
244                 isEnable = false;
245             } else {
246                 isEnable = it->second;
247             }
248             return isEnable;
249         });
250         return isEnable;
251     }
252 
253 private:
254     SessionStateManager() = default;
255     SessionStateManager(const SessionStateManager &other) = delete;
256     SessionStateManager(const SessionStateManager &&other) = delete;
257     SessionStateManager &operator=(const SessionStateManager &other) = delete;
258     SessionStateManager &operator=(const SessionStateManager &&other) = delete;
259 
260     std::mutex sessionIdMutex_;
261     std::condition_variable sessionIdCond_;
262     std::map<int32_t, bool> sessionIdMap_;
263 };
264 
OnSessionOpened(int sessionId,int result)265 static int OnSessionOpened(int sessionId, int result)
266 {
267     LOGI(">> OnSessionOpenedServer {sessionId:%d, result=%d", sessionId, result);
268     if (sessionId <= 0 || result != SOFTBUS_OK) {
269         LOGE(">> OnSessionOpenedServer, session open failed");
270         return result;
271     }
272 
273     SessionStateManager::GetInstance().EnableSessionId(sessionId);
274     return SOFTBUS_OK;
275 }
276 
OnSessionClosed(int sessionId)277 static void OnSessionClosed(int sessionId)
278 {
279     LOGI(">> OnSessionClosedServer {sessionId:%d", sessionId);
280     SessionStateManager::GetInstance().EnableSessionId(sessionId);
281 }
282 
283 /*
284  * @tc.name: RawStreamEncryptTest003
285  * @tc.desc: Encrypted raw stream data transmission test
286  * @tc.type: FUNC
287  * @tc.require:
288  */
289 HWTEST_F(StreamEncryptClientMt, RawStreamEncryptTest003, TestSize.Level1)
290 {
291     /**
292      * @tc.steps: step 1. call 'CreateSessionServer' function to create session server.
293      * @tc.expect: 'CreateSessionServer' function return SOFTBUS_OK.
294      */
295     ISessionListener sessionListener = {
296         .OnSessionOpened = OnSessionOpened,
297         .OnSessionClosed = OnSessionClosed,
298     };
299 
300     int32_t ret = CreateSessionServer(PKG_NAME, TEST_SESSION_NAME, &sessionListener);
301     ASSERT_EQ(ret, SOFTBUS_OK);
302 
303     SessionAttribute attr = { 0 };
304     attr.dataType = TYPE_STREAM;
305     attr.attr.streamAttr.streamType = RAW_STREAM;
306     attr.linkTypeNum = 4;
307     attr.linkType[0] = LINK_TYPE_WIFI_WLAN_5G;
308     attr.linkType[1] = LINK_TYPE_WIFI_WLAN_2G;
309     attr.linkType[2] = LINK_TYPE_BR;
310     attr.linkType[3] = LINK_TYPE_BLE;
311     attr.fastTransData = nullptr;
312     attr.fastTransDataSize = 0;
313 
314     /**
315      * @tc.steps: step 2. call 'OpenSession' function to create session.
316      * @tc.expect: 'OpenSession' function return SOFTBUS_OK.
317      */
318     int32_t sessionId = OpenSession(TEST_SESSION_NAME, TEST_SESSION_NAME_SRV, WaitOnLineAndGetNetWorkId(), "reserved",
319         &attr);
320     ASSERT_GT(sessionId, 0) << "failed to OpenSession, ret=" << sessionId;
321 
322     /**
323      * @tc.steps: step 3. call 'WaitEnableSession' function to wait for the session to be opened.
324      * @tc.expect: 'WaitEnableSession' function return true.
325      */
326     bool isEnable = SessionStateManager::GetInstance().WaitEnableSession(sessionId, 10);
327     ASSERT_TRUE(isEnable) << "failed to enable session, sessionId" << sessionId;
328 
329 
330     /**
331      * @tc.steps: step 4. call 'SendStream' function to send unencrypted raw stream data.
332      * @tc.expect: 'SendStream' function return SOFTBUS_OK.
333      */
334     ret = SendStreamExt(sessionId);
335     ASSERT_EQ(ret, SOFTBUS_OK);
336 
337     /**
338      * @tc.steps: step 5. call 'Wait' function to get test results returned by server side.
339      * @tc.expect: 'IsTestOk' function return true.
340      */
341     std::shared_ptr<Response> resp = TMessenger::GetInstance().QueryResult(WAIT_TIMEOUT);
342     bool testResult = IsTestOk(false, TEST_STREAM_DATA, resp);
343     ASSERT_TRUE(testResult);
344 
345     CloseSession(sessionId);
346     RemoveSessionServer(PKG_NAME, TEST_SESSION_NAME);
347 }
348 } // namespace OHOS