1 /*
2 * Copyright (c) 2022 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 <arpa/inet.h>
17 #include <netinet/ip.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <sys/select.h>
22 #include <sys/socket.h>
23 #include <sys/wait.h>
24 #include <time.h>
25 #include "functionalext.h"
26
27 #define TEST_MSG_PORT 7788
28 #define TEST_BUF_SIZE 256
29 #define TEST_TIMEOUT 5
30
31 const char *text = "This is a simple test case.";
32
fill_socket_addr(struct sockaddr_in * addr)33 void fill_socket_addr(struct sockaddr_in *addr)
34 {
35 if (addr) {
36 bzero(addr, sizeof(struct sockaddr_in));
37 addr->sin_family = AF_INET;
38 inet_pton(AF_INET, "127.0.0.1", &addr->sin_addr);
39 addr->sin_port = htons(TEST_MSG_PORT);
40 }
41 }
42
check_recv_message(int sockfd)43 int check_recv_message(int sockfd)
44 {
45 struct timeval t;
46 fd_set rset;
47
48 int timeout = TEST_TIMEOUT;
49 int ret;
50 while (timeout > 0) {
51 FD_ZERO(&rset);
52 FD_SET(sockfd, &rset);
53 t.tv_sec = 1;
54 t.tv_usec = 0;
55
56 ret = select(sockfd + 1, &rset, NULL, NULL, &t);
57 if (ret == 0) {
58 timeout--;
59 } else if (ret < 0) {
60 return ret;
61 } else {
62 if (FD_ISSET(sockfd, &rset)) {
63 return ret;
64 }
65 }
66 }
67 return -1;
68 }
69
send_message(int flag,const char * msg)70 void send_message(int flag, const char *msg)
71 {
72 int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
73 if (sockfd == -1) {
74 t_error("[%s] failed\n", msg);
75 return;
76 }
77
78 struct sockaddr_in addr;
79 struct msghdr msg_send;
80 struct iovec iov_send;
81 char buf[TEST_BUF_SIZE];
82
83 fill_socket_addr(&addr);
84 memset(&msg_send, 0x0, sizeof(struct msghdr));
85 memset(&iov_send, 0x0, sizeof(struct iovec));
86
87 iov_send.iov_base = buf;
88 iov_send.iov_len = TEST_BUF_SIZE;
89
90 msg_send.msg_iovlen = 1;
91 msg_send.msg_iov = &iov_send;
92 msg_send.msg_control = 0;
93 msg_send.msg_controllen = 0;
94
95 if (connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
96 close(sockfd);
97 t_error("[%s] failed\n", msg);
98 return;
99 }
100
101 int ret = sendmsg(sockfd, &msg_send, flag);
102 close(sockfd);
103 EXPECT_TRUE(msg, ret > 0);
104 }
105
recv_message(int flag,const char * msg)106 int recv_message(int flag, const char *msg)
107 {
108 int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
109 if (sockfd == -1) {
110 t_error("[%s] failed\n", msg);
111 exit(1);
112 }
113
114 struct sockaddr_in addr;
115 struct msghdr msg_recv;
116 struct iovec iov_recv;
117 char buf[TEST_BUF_SIZE];
118 char control[TEST_BUF_SIZE];
119
120 fill_socket_addr(&addr);
121 memset(&msg_recv, 0x0, sizeof(struct msghdr));
122 memset(&iov_recv, 0x0, sizeof(struct iovec));
123 memset(buf, 0x0, sizeof(buf));
124
125 iov_recv.iov_base = (void *)buf;
126 iov_recv.iov_len = TEST_BUF_SIZE;
127
128 msg_recv.msg_name = &addr;
129 msg_recv.msg_iovlen = 1;
130 msg_recv.msg_iov = &iov_recv;
131 msg_recv.msg_control = control;
132 msg_recv.msg_controllen = TEST_BUF_SIZE;
133 msg_recv.msg_flags = 0;
134
135 if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
136 close(sockfd);
137 t_error("[%s] failed\n", msg);
138 exit(1);
139 }
140
141 int ret = check_recv_message(sockfd);
142 EXPECT_TRUE(msg, ret > 0);
143 if (ret > 0) {
144 ret = recvmsg(sockfd, &msg_recv, flag);
145 EXPECT_TRUE(msg, ret > 0);
146 EXPECT_STREQ(msg, iov_recv.iov_base, text);
147 }
148 close(sockfd);
149 exit(0);
150 }
151
152 /**
153 * @tc.name : recvmsg_0100
154 * @tc.desc : Test recvmsg to recv messages through socket
155 * @tc.level : Level 0
156 */
recvmsg_0100(void)157 void recvmsg_0100(void)
158 {
159 pid_t pid = fork();
160 if (pid == 0) {
161 recv_message(0, "recvmsg_0100");
162 } else if (pid > 0) {
163 sleep(1);
164 send_message(0, "recvmsg_0100");
165 wait(NULL);
166 } else {
167 t_error("recvmsg_0100 fork error");
168 }
169 }
170
main(void)171 int main(void)
172 {
173 recvmsg_0100();
174 return t_status;
175 }