• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2025 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 <cerrno>
17 #include <cstdio>
18 #include <cstdlib>
19 #include <string>
20 #include <vector>
21 #include <fcntl.h>
22 #include <pthread.h>
23 #include <unistd.h>
24 #include <arpa/inet.h>
25 #include <gtest/gtest.h>
26 #include <netinet/in.h>
27 #include <sys/stat.h>
28 #include <sys/socket.h>
29 #include <sys/types.h>
30 #include "securec.h"
31 
32 using namespace testing::ext;
33 
34 static const int BUFFER_SIZE = 1024;
35 static const int TEST_PORT = 22354;
36 static const char *TEST_LOCAL_IP = "127.0.0.1";
37 static int g_serviceFd = -1;
38 
39 class HatsSendmsgTest : public testing::Test {
40 public:
41     static void SetUpTestCase();
42     static void TearDownTestCase();
43     void SetUp();
44     void TearDown();
45 private:
46 };
SetUp()47 void HatsSendmsgTest::SetUp()
48 {
49     int ret;
50     int socketFd = -1;
51     int32_t optVal = 1;
52     struct sockaddr_in serAddr = {
53         .sin_family = AF_INET,
54         .sin_port = htons(TEST_PORT),
55         .sin_addr = {
56             .s_addr = inet_addr(TEST_LOCAL_IP),
57         }
58     };
59 
60     socketFd = socket(AF_INET, SOCK_STREAM, 0);
61     EXPECT_TRUE(socketFd > 0);
62 
63     ret = setsockopt(socketFd, SOL_SOCKET, SO_REUSEADDR, &optVal, sizeof(optVal));
64     EXPECT_EQ(ret, 0);
65 
66     ret = bind(socketFd, reinterpret_cast<struct sockaddr *>(&serAddr), sizeof(serAddr));
67     EXPECT_EQ(ret, 0);
68 
69     g_serviceFd = socketFd;
70 }
TearDown()71 void HatsSendmsgTest::TearDown()
72 {
73     close(g_serviceFd);
74     g_serviceFd = -1;
75 }
SetUpTestCase()76 void HatsSendmsgTest::SetUpTestCase()
77 {
78 }
TearDownTestCase()79 void HatsSendmsgTest::TearDownTestCase()
80 {
81 }
82 
ClientConnect(void * args)83 static void *ClientConnect(void *args)
84 {
85     int ret;
86     ssize_t size;
87     int clientFd = -1;
88     char buffer[BUFFER_SIZE] = { 0 };
89     struct sockaddr_in addr;
90     socklen_t addrlen = sizeof(addr);
91     struct sockaddr_in serAddr = {
92         .sin_family = AF_INET,
93         .sin_port = htons(TEST_PORT),
94         .sin_addr = {
95             .s_addr = inet_addr(TEST_LOCAL_IP),
96         }
97     };
98 
99     clientFd = socket(AF_INET, SOCK_STREAM, 0);
100     EXPECT_TRUE(clientFd > 0);
101 
102     ret = connect(clientFd, reinterpret_cast<struct sockaddr *>(&serAddr), sizeof(struct sockaddr_in));
103     EXPECT_EQ(ret, 0);
104 
105     struct msghdr msg = {0};
106     struct iovec iov = {buffer, sizeof(buffer)};
107     msg.msg_iov = &iov;
108     msg.msg_iovlen = 1;
109     msg.msg_name = reinterpret_cast<struct sockaddr *>(&addr);
110     msg.msg_namelen = addrlen;
111 
112     size = recvmsg(clientFd, &msg, 0);
113     EXPECT_TRUE(size >= 0);
114 
115     close(clientFd);
116     return nullptr;
117 }
118 
119 /*
120  * @tc.number : SUB_KERNEL_SYSCALL_SENDMSG_0100
121  * @tc.name   : SendmsgSuccess_0001
122  * @tc.desc   : Sendmsg test success.
123  * @tc.size   : MediumTest
124  * @tc.type   : Function
125  * @tc.level  : Level 1
126  */
127 HWTEST_F(HatsSendmsgTest, SendmsgSuccess_0001, Function | MediumTest | Level1)
128 {
129     int ret;
130     ssize_t size;
131     pthread_t thread;
132     int acceptFd = -1;
133     int32_t backLog = 5;
134     struct sockaddr_in dstAddr = { 0 };
135     struct sockaddr_in peerAddr;
136     socklen_t addrLen = sizeof(struct sockaddr_in);
137     socklen_t peerLen = sizeof(struct sockaddr_in);
138 
139     ret = listen(g_serviceFd, backLog);
140     EXPECT_EQ(ret, 0);
141 
142     pthread_create(&thread, nullptr, ClientConnect, nullptr);
143 
144     acceptFd = accept4(g_serviceFd, reinterpret_cast<struct sockaddr *>(&dstAddr), &addrLen, 0);
145     EXPECT_TRUE(acceptFd > 0);
146 
147     ret = getpeername(acceptFd, reinterpret_cast<struct sockaddr *>(&peerAddr), &peerLen);
148     EXPECT_EQ(ret, 0);
149 
150     EXPECT_STREQ(inet_ntoa(peerAddr.sin_addr), TEST_LOCAL_IP);
151     EXPECT_EQ(peerLen, sizeof(struct sockaddr));
152 
153     struct msghdr msg;
154     struct iovec iov;
155     char buffer[BUFFER_SIZE];
156     iov.iov_base = buffer;
157     iov.iov_len = sizeof(buffer);
158     msg.msg_name = nullptr; // 不需要目标地址
159     msg.msg_namelen = 0;
160     msg.msg_iov = &iov;
161     msg.msg_iovlen = 1;
162     msg.msg_control = nullptr;
163     msg.msg_controllen = 0;
164 
165     size = sendmsg(acceptFd, &msg, 0);
166     EXPECT_TRUE(size >= 0);
167 
168     close(acceptFd);
169     pthread_join(thread, nullptr);
170 }
171 
172 /*
173  * @tc.number : SUB_KERNEL_SYSCALL_SENDMSG_0200
174  * @tc.name   : SendmsgSuccess_0002
175  * @tc.desc   : Sendmsg test success by MSG_MORE.
176  * @tc.size   : MediumTest
177  * @tc.type   : Function
178  * @tc.level  : Level 2
179  */
180 HWTEST_F(HatsSendmsgTest, SendmsgSuccess_0002, Function | MediumTest | Level2)
181 {
182     int ret;
183     ssize_t size;
184     pthread_t thread;
185     int acceptFd = -1;
186     int32_t backLog = 5;
187     struct sockaddr_in dstAddr = { 0 };
188     socklen_t addrLen = sizeof(struct sockaddr_in);
189 
190     ret = listen(g_serviceFd, backLog);
191     EXPECT_EQ(ret, 0);
192 
193     pthread_create(&thread, nullptr, ClientConnect, nullptr);
194     acceptFd = accept4(g_serviceFd, reinterpret_cast<struct sockaddr *>(&dstAddr), &addrLen, 0);
195     EXPECT_TRUE(acceptFd > 0);
196 
197     char buf1[] = "Hello, ";
198     char buf2[] = "world!";
199 
200     struct iovec iov[2];
201     iov[0].iov_base = buf1;
202     iov[0].iov_len = sizeof(buf1) - 1;
203     iov[1].iov_base = buf2;
204     iov[1].iov_len = sizeof(buf2) - 1;
205 
206     struct msghdr message;
207     memset_s(&message, sizeof(message), 0, sizeof(message));
208     message.msg_iov = iov;
209     message.msg_iovlen = 2;
210 
211     size = sendmsg(acceptFd, &message, MSG_MORE);
212     EXPECT_TRUE(size >= 0);
213 
214     size = sendmsg(acceptFd, &message, 0);
215     EXPECT_TRUE(size >= 0);
216 
217     close(acceptFd);
218     pthread_join(thread, nullptr);
219 }
220 
221 /*
222  * @tc.number : SUB_KERNEL_SYSCALL_SENDMSG_0300
223  * @tc.name   : SendmsgSuccess_0003
224  * @tc.desc   : Sendmsg test success by MSG_NOSIGNAL.
225  * @tc.size   : MediumTest
226  * @tc.type   : Function
227  * @tc.level  : Level 2
228  */
229 HWTEST_F(HatsSendmsgTest, SendmsgSuccess_0003, Function | MediumTest | Level2)
230 {
231     int ret;
232     ssize_t size;
233     pthread_t thread;
234     int acceptFd = -1;
235     int32_t backLog = 5;
236     struct sockaddr_in dstAddr = { 0 };
237     socklen_t addrLen = sizeof(struct sockaddr_in);
238 
239     ret = listen(g_serviceFd, backLog);
240     EXPECT_EQ(ret, 0);
241 
242     pthread_create(&thread, nullptr, ClientConnect, nullptr);
243     acceptFd = accept4(g_serviceFd, reinterpret_cast<struct sockaddr *>(&dstAddr), &addrLen, 0);
244     EXPECT_TRUE(acceptFd > 0);
245 
246     char buf[] = "Hello, world!";
247     struct iovec iov;
248     iov.iov_base = buf;
249     iov.iov_len = sizeof(buf) - 1;
250 
251     struct msghdr message;
252     memset_s(&message, sizeof(message), 0, sizeof(message));
253     message.msg_iov = &iov;
254     message.msg_iovlen = 1;
255 
256     size = sendmsg(acceptFd, &message, MSG_NOSIGNAL);
257     EXPECT_TRUE(size >= 0);
258 
259     close(acceptFd);
260     pthread_join(thread, nullptr);
261 }
262 
263 /*
264  * @tc.number : SUB_KERNEL_SYSCALL_SENDMSG_0400
265  * @tc.name   : SendmsgSuccess_0004
266  * @tc.desc   : Sendmsg test success by MSG_OOB.
267  * @tc.size   : MediumTest
268  * @tc.type   : Function
269  * @tc.level  : Level 2
270  */
271 HWTEST_F(HatsSendmsgTest, SendmsgSuccess_0004, Function | MediumTest | Level2)
272 {
273     int ret;
274     ssize_t size;
275     pthread_t thread;
276     int acceptFd = -1;
277     int32_t backLog = 5;
278     struct sockaddr_in dstAddr = { 0 };
279     socklen_t addrLen = sizeof(struct sockaddr_in);
280 
281     ret = listen(g_serviceFd, backLog);
282     EXPECT_EQ(ret, 0);
283 
284     pthread_create(&thread, nullptr, ClientConnect, nullptr);
285     acceptFd = accept4(g_serviceFd, reinterpret_cast<struct sockaddr *>(&dstAddr), &addrLen, 0);
286     EXPECT_TRUE(acceptFd > 0);
287 
288     char oobData = '!';
289     struct iovec iov;
290     iov.iov_base = &oobData;
291     iov.iov_len = sizeof(oobData);
292 
293     struct msghdr message;
294     memset_s(&message, sizeof(message), 0, sizeof(message));
295     message.msg_iov = &iov;
296     message.msg_iovlen = 1;
297 
298     size = sendmsg(acceptFd, &message, MSG_OOB);
299     EXPECT_TRUE(size >= 0);
300 
301     char normalData[] = "Hello, world!";
302     iov.iov_base = normalData;
303     iov.iov_len = sizeof(normalData) - 1;
304 
305     size = sendmsg(acceptFd, &message, 0);
306     EXPECT_TRUE(size >= 0);
307 
308     close(acceptFd);
309     pthread_join(thread, nullptr);
310 }