• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (C) 2014 The Android Open Source Project
3   *
4   * Licensed under the Apache License, Version 2.0 (the "License");
5   * you may not use this file except in compliance with the License.
6   * You may obtain a copy of the License at
7   *
8   *      http://www.apache.org/licenses/LICENSE-2.0
9   *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  #include <gtest/gtest.h>
18  
19  #include <errno.h>
20  #include <sys/types.h>
21  #include <sys/socket.h>
22  #include <sys/un.h>
23  #include <fcntl.h>
24  
25  #include "utils.h"
26  
27  struct ConnectData {
28    bool (*callback_fn)(int);
29    const char* sock_path;
ConnectDataConnectData30    ConnectData(bool (*callback_func)(int), const char* socket_path)
31     : callback_fn(callback_func), sock_path(socket_path) {}
32  };
33  
ConnectFn(void * data)34  static void* ConnectFn(void* data) {
35    ConnectData* pdata = reinterpret_cast<ConnectData*>(data);
36    bool (*callback_fn)(int) = pdata->callback_fn;
37    void* return_value = nullptr;
38  
39    int fd = socket(PF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
40    if (fd < 0) {
41      GTEST_LOG_(ERROR) << "socket call failed: " << strerror(errno);
42      return reinterpret_cast<void*>(-1);
43    }
44  
45    struct sockaddr_un addr;
46    memset(&addr, 0, sizeof(addr));
47    addr.sun_family = AF_UNIX;
48    addr.sun_path[0] = '\0';
49    strcpy(addr.sun_path + 1, pdata->sock_path);
50  
51    if (connect(fd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) < 0) {
52      GTEST_LOG_(ERROR) << "connect call failed: " << strerror(errno);
53      return_value = reinterpret_cast<void*>(-1);
54    }
55    else if (callback_fn != nullptr && !callback_fn(fd)) {
56      return_value = reinterpret_cast<void*>(-1);
57    }
58  
59    close(fd);
60  
61    return return_value;
62  }
63  
RunTest(void (* test_fn)(struct sockaddr_un *,int),bool (* callback_fn)(int fd),const char * sock_path)64  static void RunTest(void (*test_fn)(struct sockaddr_un*, int),
65                      bool (*callback_fn)(int fd), const char* sock_path) {
66    int fd = socket(PF_UNIX, SOCK_SEQPACKET, 0);
67    ASSERT_NE(fd, -1) << strerror(errno);
68  
69    struct sockaddr_un addr;
70    memset(&addr, 0, sizeof(addr));
71    addr.sun_family = AF_UNIX;
72    addr.sun_path[0] = '\0';
73    strcpy(addr.sun_path + 1, sock_path);
74  
75    ASSERT_NE(-1, bind(fd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr))) << strerror(errno);
76  
77    ASSERT_NE(-1, listen(fd, 1)) << strerror(errno);
78  
79    ConnectData connect_data(callback_fn, sock_path);
80  
81    pthread_t thread;
82    ASSERT_EQ(0, pthread_create(&thread, nullptr, ConnectFn, &connect_data));
83  
84    fd_set read_set;
85    FD_ZERO(&read_set);
86    FD_SET(fd, &read_set);
87    timeval tv;
88    tv.tv_sec = 5;
89    tv.tv_usec = 0;
90    ASSERT_LT(0, select(fd+1, &read_set, nullptr, nullptr, &tv));
91  
92    test_fn(&addr, fd);
93  
94    void* ret_val;
95    ASSERT_EQ(0, pthread_join(thread, &ret_val));
96    ASSERT_EQ(nullptr, ret_val);
97  
98    close(fd);
99  }
100  
TEST(sys_socket,accept4_error)101  TEST(sys_socket, accept4_error) {
102    ASSERT_EQ(-1, accept4(-1, nullptr, nullptr, 0));
103    ASSERT_EQ(EBADF, errno);
104  }
105  
TestAccept4(struct sockaddr_un * addr,int fd)106  static void TestAccept4(struct sockaddr_un* addr, int fd) {
107    socklen_t len = sizeof(*addr);
108    int fd_acc = accept4(fd, reinterpret_cast<struct sockaddr*>(addr), &len, SOCK_CLOEXEC);
109    ASSERT_NE(fd_acc, -1) << strerror(errno);
110  
111    // Check that SOCK_CLOEXEC was set properly.
112    ASSERT_TRUE(CloseOnExec(fd_acc));
113  
114    close(fd_acc);
115  }
116  
TEST(sys_socket,accept4_smoke)117  TEST(sys_socket, accept4_smoke) {
118    RunTest(TestAccept4, nullptr, "test_accept");
119  }
120  
121  const char* g_RecvMsgs[] = {
122    "RECVMMSG_ONE",
123    "RECVMMSG_TWO",
124    "RECVMMSG_THREE",
125  };
126  #define NUM_RECV_MSGS (sizeof(g_RecvMsgs)/sizeof(const char*))
127  
SendMultiple(int fd)128  static bool SendMultiple(int fd) {
129    for (size_t i = 0; i < NUM_RECV_MSGS; i++) {
130      if (send(fd, g_RecvMsgs[i], strlen(g_RecvMsgs[i]) + 1, 0) < 0) {
131        GTEST_LOG_(ERROR) << "send call failed: " << strerror(errno);
132        return false;
133      }
134    }
135  
136    return true;
137  }
138  
TestRecvMMsg(struct sockaddr_un * addr,int fd)139  static void TestRecvMMsg(struct sockaddr_un *addr, int fd) {
140    socklen_t len = sizeof(*addr);
141    int fd_acc = accept(fd, reinterpret_cast<struct sockaddr*>(addr), &len);
142    ASSERT_NE(fd_acc, -1) << strerror(errno);
143  
144    struct mmsghdr msgs[NUM_RECV_MSGS];
145    memset(msgs, 0, sizeof(struct mmsghdr)*NUM_RECV_MSGS);
146  
147    struct iovec io[NUM_RECV_MSGS];
148    char bufs[NUM_RECV_MSGS][100];
149    for (size_t i = 0; i < NUM_RECV_MSGS; i++) {
150      io[i].iov_base = reinterpret_cast<void*>(bufs[i]);
151      io[i].iov_len = strlen(g_RecvMsgs[i]) + 1;
152  
153      msgs[i].msg_hdr.msg_iov = &io[i];
154      msgs[i].msg_hdr.msg_iovlen = 1;
155      msgs[i].msg_len = sizeof(struct msghdr);
156    }
157  
158    struct timespec ts;
159    memset(&ts, 0, sizeof(ts));
160    ts.tv_sec = 5;
161    ts.tv_nsec = 0;
162    ASSERT_EQ(NUM_RECV_MSGS,
163              static_cast<size_t>(recvmmsg(fd_acc, msgs, NUM_RECV_MSGS, 0, &ts)))
164             << strerror(errno);
165    for (size_t i = 0; i < NUM_RECV_MSGS; i++) {
166      ASSERT_STREQ(g_RecvMsgs[i], bufs[i]);
167    }
168  
169    close(fd_acc);
170  }
171  
TEST(sys_socket,recvmmsg_smoke)172  TEST(sys_socket, recvmmsg_smoke) {
173    RunTest(TestRecvMMsg, SendMultiple, "test_revmmsg");
174  }
175  
TEST(sys_socket,recvmmsg_error)176  TEST(sys_socket, recvmmsg_error) {
177    ASSERT_EQ(-1, recvmmsg(-1, nullptr, 0, 0, nullptr));
178    ASSERT_EQ(EBADF, errno);
179  }
180  
181  const char* g_SendMsgs[] = {
182    "MSG_ONE",
183    "MSG_TWO",
184    "MSG_THREE"
185  };
186  #define NUM_SEND_MSGS (sizeof(g_SendMsgs)/sizeof(const char*))
187  
SendMMsg(int fd)188  static bool SendMMsg(int fd) {
189    struct mmsghdr msgs[NUM_SEND_MSGS];
190    memset(msgs, 0, sizeof(struct mmsghdr)*NUM_SEND_MSGS);
191    struct iovec io[NUM_SEND_MSGS];
192    for (size_t i = 0; i < NUM_SEND_MSGS; i++) {
193      io[i].iov_base = reinterpret_cast<void*>(const_cast<char*>(g_SendMsgs[i]));
194      io[i].iov_len = strlen(g_SendMsgs[i]) + 1;
195      msgs[i].msg_hdr.msg_iov = &io[i];
196      msgs[i].msg_hdr.msg_iovlen = 1;
197      msgs[i].msg_len = sizeof(struct msghdr);
198    }
199  
200    if (sendmmsg(fd, msgs, NUM_SEND_MSGS, 0) < 0) {
201      GTEST_LOG_(ERROR) << "sendmmsg call failed: " << strerror(errno);
202      return false;
203    }
204    return true;
205  }
206  
TestSendMMsg(struct sockaddr_un * addr,int fd)207  static void TestSendMMsg(struct sockaddr_un *addr, int fd) {
208    socklen_t len = sizeof(*addr);
209    int fd_acc = accept(fd, reinterpret_cast<struct sockaddr*>(addr), &len);
210    ASSERT_NE(fd_acc, -1) << strerror(errno);
211  
212    fd_set read_set;
213    FD_ZERO(&read_set);
214    FD_SET(fd_acc, &read_set);
215  
216    for (size_t i = 0; i < NUM_SEND_MSGS; i++) {
217      timeval tv;
218      tv.tv_sec = 5;
219      tv.tv_usec = 0;
220      ASSERT_LT(0, select(fd_acc+1, &read_set, nullptr, nullptr, &tv));
221      char buffer[100];
222      ASSERT_EQ(strlen(g_SendMsgs[i]) + 1,
223                static_cast<size_t>(recv(fd_acc, buffer, sizeof(buffer), 0)));
224      ASSERT_STREQ(g_SendMsgs[i], buffer);
225    }
226  
227    close(fd_acc);
228  }
229  
TEST(sys_socket,sendmmsg_smoke)230  TEST(sys_socket, sendmmsg_smoke) {
231    RunTest(TestSendMMsg, SendMMsg, "test_sendmmsg");
232  }
233  
TEST(sys_socket,sendmmsg_error)234  TEST(sys_socket, sendmmsg_error) {
235    ASSERT_EQ(-1, sendmmsg(-1, nullptr, 0, 0));
236    ASSERT_EQ(EBADF, errno);
237  }
238