1/*
2 Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
3
4 This file is part of libzmq, the ZeroMQ core engine in C++.
5
6 libzmq is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License (LGPL) as published
8 by the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 As a special exception, the Contributors give you permission to link
12 this library with independent modules to produce an executable,
13 regardless of the license terms of these independent modules, and to
14 copy and distribute the resulting executable under terms of your choice,
15 provided that you also meet, for each linked independent module, the
16 terms and conditions of the license of that module. An independent
17 module is a module which is not derived from or based on this library.
18 If you modify this library, you must extend this exception to your
19 version of the library.
20
21 libzmq is distributed in the hope that it will be useful, but WITHOUT
22 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
24 License for more details.
25
26 You should have received a copy of the GNU Lesser General Public License
27 along with this program. If not, see <http://www.gnu.org/licenses/>.
28*/
29
30#include "testutil.hpp"
31#include "testutil_unity.hpp"
32
33#include <string.h>
34
35#if defined _WIN32
36#include "../src/windows.hpp"
37#endif
38
39SETUP_TEARDOWN_TESTCONTEXT
40
41typedef void (*extra_func_t) (void *socket_);
42
43#ifdef ZMQ_BUILD_DRAFT
44void set_sockopt_fastpath (void *socket)
45{
46 int value = 1;
47 int rc =
48 zmq_setsockopt (socket, ZMQ_LOOPBACK_FASTPATH, &value, sizeof value);
49 assert (rc == 0);
50}
51#endif
52
53void test_pair_tcp (extra_func_t extra_func_ = NULL)
54{
55 void *sb = test_context_socket (ZMQ_PAIR);
56
57 if (extra_func_)
58 extra_func_ (sb);
59
60 char my_endpoint[MAX_SOCKET_STRING];
61 bind_loopback_ipv4 (sb, my_endpoint, sizeof my_endpoint);
62
63 void *sc = test_context_socket (ZMQ_PAIR);
64 if (extra_func_)
65 extra_func_ (sc);
66
67 TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, my_endpoint));
68
69 bounce (sb, sc);
70
71 test_context_socket_close (sc);
72 test_context_socket_close (sb);
73}
74
75void test_pair_tcp_regular ()
76{
77 test_pair_tcp ();
78}
79
80void test_pair_tcp_connect_by_name ()
81{
82 // all other tcp test cases bind to a loopback wildcard address, then
83 // retrieve the bound endpoint, which is numerical, and use that to
84 // connect. this test cases specifically uses "localhost" to connect
85 // to ensure that names are correctly resolved
86 void *sb = test_context_socket (ZMQ_PAIR);
87
88 char bound_endpoint[MAX_SOCKET_STRING];
89 bind_loopback_ipv4 (sb, bound_endpoint, sizeof bound_endpoint);
90
91 // extract the bound port number
92 const char *pos = strrchr (bound_endpoint, ':');
93 TEST_ASSERT_NOT_NULL (pos);
94 const char connect_endpoint_prefix[] = "tcp://localhost";
95 char connect_endpoint[MAX_SOCKET_STRING];
96 strcpy (connect_endpoint, connect_endpoint_prefix);
97 strcat (connect_endpoint, pos);
98
99 void *sc = test_context_socket (ZMQ_PAIR);
100
101 TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, connect_endpoint));
102
103 bounce (sb, sc);
104
105 test_context_socket_close (sc);
106 test_context_socket_close (sb);
107}
108
109
110#ifdef ZMQ_BUILD_DRAFT
111void test_pair_tcp_fastpath ()
112{
113 test_pair_tcp (set_sockopt_fastpath);
114}
115#endif
116
117#ifdef _WIN32
118void test_io_completion_port ()
119{
120 void *const s = test_context_socket (ZMQ_PAIR);
121 SOCKET fd;
122 size_t fd_size = sizeof fd;
123 TEST_ASSERT_SUCCESS_ERRNO (zmq_getsockopt (s, ZMQ_FD, &fd, &fd_size));
124
125 ::WSAPROTOCOL_INFO pi;
126 TEST_ASSERT_SUCCESS_RAW_ERRNO (
127 ::WSADuplicateSocket (fd, ::GetCurrentProcessId (), &pi));
128 const SOCKET socket = ::WSASocket (pi.iAddressFamily /*AF_INET*/,
129 pi.iSocketType /*SOCK_STREAM*/,
130 pi.iProtocol /*IPPROTO_TCP*/, &pi, 0, 0);
131
132 const HANDLE iocp =
133 ::CreateIoCompletionPort (INVALID_HANDLE_VALUE, NULL, 0, 0);
134 TEST_ASSERT_NOT_EQUAL (NULL, iocp);
135 const HANDLE res =
136 ::CreateIoCompletionPort (reinterpret_cast<HANDLE> (socket), iocp, 0, 0);
137 TEST_ASSERT_NOT_EQUAL (NULL, res);
138
139 TEST_ASSERT_SUCCESS_RAW_ERRNO (closesocket (socket));
140 TEST_ASSERT_TRUE (CloseHandle (iocp));
141
142 test_context_socket_close (s);
143}
144#endif
145
146int main ()
147{
148 setup_test_environment ();
149
150 UNITY_BEGIN ();
151 RUN_TEST (test_pair_tcp_regular);
152 RUN_TEST (test_pair_tcp_connect_by_name);
153#ifdef ZMQ_BUILD_DRAFT
154 RUN_TEST (test_pair_tcp_fastpath);
155#endif
156#ifdef _WIN32
157 RUN_TEST (test_io_completion_port);
158#endif
159
160 return UNITY_END ();
161}
162