libuv-svace-build
172 строки · 4.4 Кб
1/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2*
3* Permission is hereby granted, free of charge, to any person obtaining a copy
4* of this software and associated documentation files (the "Software"), to
5* deal in the Software without restriction, including without limitation the
6* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7* sell copies of the Software, and to permit persons to whom the Software is
8* furnished to do so, subject to the following conditions:
9*
10* The above copyright notice and this permission notice shall be included in
11* all copies or substantial portions of the Software.
12*
13* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19* IN THE SOFTWARE.
20*/
21
22#include "uv.h"
23#include "task.h"
24
25
26#ifndef _WIN32
27
28#include <fcntl.h>
29#include <errno.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33#include <sys/socket.h>
34#include <unistd.h>
35
36
37/* NOTE: size should be divisible by 2 */
38static uv_pipe_t incoming[4];
39static unsigned int incoming_count;
40static unsigned int close_called;
41
42
43static void set_nonblocking(uv_os_sock_t sock) {
44int r;
45#ifdef _WIN32
46unsigned long on = 1;
47r = ioctlsocket(sock, FIONBIO, &on);
48ASSERT_OK(r);
49#else
50int flags = fcntl(sock, F_GETFL, 0);
51ASSERT_GE(flags, 0);
52r = fcntl(sock, F_SETFL, flags | O_NONBLOCK);
53ASSERT_GE(r, 0);
54#endif
55}
56
57
58
59
60static void close_cb(uv_handle_t* handle) {
61close_called++;
62}
63
64
65static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) {
66static char base[1];
67
68buf->base = base;
69buf->len = sizeof(base);
70}
71
72
73static void read_cb(uv_stream_t* handle,
74ssize_t nread,
75const uv_buf_t* buf) {
76uv_pipe_t* p;
77uv_pipe_t* inc;
78uv_handle_type pending;
79unsigned int i;
80
81p = (uv_pipe_t*) handle;
82ASSERT_GE(nread, 0);
83
84while (uv_pipe_pending_count(p) != 0) {
85pending = uv_pipe_pending_type(p);
86ASSERT_EQ(pending, UV_NAMED_PIPE);
87
88ASSERT_LT(incoming_count, ARRAY_SIZE(incoming));
89inc = &incoming[incoming_count++];
90ASSERT_OK(uv_pipe_init(p->loop, inc, 0));
91ASSERT_OK(uv_accept(handle, (uv_stream_t*) inc));
92}
93
94if (incoming_count != ARRAY_SIZE(incoming))
95return;
96
97ASSERT_OK(uv_read_stop((uv_stream_t*) p));
98uv_close((uv_handle_t*) p, close_cb);
99for (i = 0; i < ARRAY_SIZE(incoming); i++)
100uv_close((uv_handle_t*) &incoming[i], close_cb);
101}
102
103
104TEST_IMPL(pipe_sendmsg) {
105#if defined(NO_SEND_HANDLE_ON_PIPE)
106RETURN_SKIP(NO_SEND_HANDLE_ON_PIPE);
107#endif
108uv_pipe_t p;
109int r;
110int fds[2];
111int send_fds[ARRAY_SIZE(incoming)];
112struct msghdr msg;
113char scratch[64];
114struct cmsghdr *cmsg;
115unsigned int i;
116uv_buf_t buf;
117
118ASSERT_OK(socketpair(AF_UNIX, SOCK_STREAM, 0, fds));
119for (i = 0; i < ARRAY_SIZE(send_fds); i += 2)
120ASSERT_OK(socketpair(AF_UNIX, SOCK_STREAM, 0, send_fds + i));
121ASSERT_EQ(i, ARRAY_SIZE(send_fds));
122ASSERT_OK(uv_pipe_init(uv_default_loop(), &p, 1));
123ASSERT_OK(uv_pipe_open(&p, fds[1]));
124
125buf = uv_buf_init("X", 1);
126memset(&msg, 0, sizeof(msg));
127msg.msg_iov = (struct iovec*) &buf;
128msg.msg_iovlen = 1;
129msg.msg_flags = 0;
130
131msg.msg_control = (void*) scratch;
132msg.msg_controllen = CMSG_LEN(sizeof(send_fds));
133ASSERT_GE(sizeof(scratch), msg.msg_controllen);
134
135cmsg = CMSG_FIRSTHDR(&msg);
136cmsg->cmsg_level = SOL_SOCKET;
137cmsg->cmsg_type = SCM_RIGHTS;
138cmsg->cmsg_len = msg.msg_controllen;
139
140/* silence aliasing warning */
141{
142void* pv = CMSG_DATA(cmsg);
143int* pi = pv;
144for (i = 0; i < ARRAY_SIZE(send_fds); i++)
145pi[i] = send_fds[i];
146}
147
148set_nonblocking(fds[1]);
149ASSERT_OK(uv_read_start((uv_stream_t*) &p, alloc_cb, read_cb));
150
151do
152r = sendmsg(fds[0], &msg, 0);
153while (r == -1 && errno == EINTR);
154ASSERT_EQ(1, r);
155
156uv_run(uv_default_loop(), UV_RUN_DEFAULT);
157ASSERT_EQ(ARRAY_SIZE(incoming), incoming_count);
158ASSERT_EQ(ARRAY_SIZE(incoming) + 1, close_called);
159close(fds[0]);
160
161MAKE_VALGRIND_HAPPY(uv_default_loop());
162return 0;
163}
164
165#else /* !_WIN32 */
166
167TEST_IMPL(pipe_sendmsg) {
168MAKE_VALGRIND_HAPPY(uv_default_loop());
169return 0;
170}
171
172#endif /* _WIN32 */
173