1 /*
2 Copyright (c) 2012 Martin Sustrik All rights reserved.
3 Copyright 2015 Garrett D'Amore <garrett@damore.org>
4 Copyright 2016 Franklin "Snaipe" Mathieu <franklinmathieu@gmail.com>
5
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 and/or sell copies of the Software, and to permit persons to whom
11 the Software is furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included
14 in all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 IN THE SOFTWARE.
23 */
24
25 #include "../src/nn.h"
26 #include "../src/pair.h"
27 #include "../src/pubsub.h"
28 #include "../src/tcp.h"
29
30 #include "testutil.h"
31
32 /* Tests TCP transport. */
33
34 int sc;
35
main(int argc,const char * argv[])36 int main (int argc, const char *argv[])
37 {
38 int rc;
39 int sb;
40 int i;
41 int opt;
42 size_t sz;
43 int s1, s2;
44 void * dummy_buf;
45 char addr[128];
46 char socket_address[128];
47
48 int port = get_test_port(argc, argv);
49
50 test_addr_from(socket_address, "tcp", "127.0.0.1", port);
51
52 /* Try closing bound but unconnected socket. */
53 sb = test_socket (AF_SP, NN_PAIR);
54 test_bind (sb, socket_address);
55 test_close (sb);
56
57 /* Try closing a TCP socket while it not connected. At the same time
58 test specifying the local address for the connection. */
59 sc = test_socket (AF_SP, NN_PAIR);
60 test_addr_from(addr, "tcp", "127.0.0.1;127.0.0.1", port);
61 test_connect (sc, addr);
62 test_close (sc);
63
64 /* Open the socket anew. */
65 sc = test_socket (AF_SP, NN_PAIR);
66
67 /* Check NODELAY socket option. */
68 sz = sizeof (opt);
69 rc = nn_getsockopt (sc, NN_TCP, NN_TCP_NODELAY, &opt, &sz);
70 errno_assert (rc == 0);
71 nn_assert (sz == sizeof (opt));
72 nn_assert (opt == 0);
73 opt = 2;
74 rc = nn_setsockopt (sc, NN_TCP, NN_TCP_NODELAY, &opt, sizeof (opt));
75 nn_assert (rc < 0 && nn_errno () == EINVAL);
76 opt = 1;
77 rc = nn_setsockopt (sc, NN_TCP, NN_TCP_NODELAY, &opt, sizeof (opt));
78 errno_assert (rc == 0);
79 sz = sizeof (opt);
80 rc = nn_getsockopt (sc, NN_TCP, NN_TCP_NODELAY, &opt, &sz);
81 errno_assert (rc == 0);
82 nn_assert (sz == sizeof (opt));
83 nn_assert (opt == 1);
84
85 /* Try using invalid address strings. */
86 rc = nn_connect (sc, "tcp://*:");
87 nn_assert (rc < 0);
88 errno_assert (nn_errno () == EINVAL);
89 rc = nn_connect (sc, "tcp://*:1000000");
90 nn_assert (rc < 0);
91 errno_assert (nn_errno () == EINVAL);
92 rc = nn_connect (sc, "tcp://*:some_port");
93 nn_assert (rc < 0);
94 rc = nn_connect (sc, "tcp://eth10000;127.0.0.1:5555");
95 nn_assert (rc < 0);
96 errno_assert (nn_errno () == ENODEV);
97 rc = nn_connect (sc, "tcp://127.0.0.1");
98 nn_assert (rc < 0);
99 errno_assert (nn_errno () == EINVAL);
100 rc = nn_bind (sc, "tcp://127.0.0.1:");
101 nn_assert (rc < 0);
102 errno_assert (nn_errno () == EINVAL);
103 rc = nn_bind (sc, "tcp://127.0.0.1:1000000");
104 nn_assert (rc < 0);
105 errno_assert (nn_errno () == EINVAL);
106 rc = nn_bind (sc, "tcp://eth10000:5555");
107 nn_assert (rc < 0);
108 errno_assert (nn_errno () == ENODEV);
109 rc = nn_connect (sc, "tcp://:5555");
110 nn_assert (rc < 0);
111 errno_assert (nn_errno () == EINVAL);
112 rc = nn_connect (sc, "tcp://-hostname:5555");
113 nn_assert (rc < 0);
114 errno_assert (nn_errno () == EINVAL);
115 rc = nn_connect (sc, "tcp://abc.123.---.#:5555");
116 nn_assert (rc < 0);
117 errno_assert (nn_errno () == EINVAL);
118 rc = nn_connect (sc, "tcp://[::1]:5555");
119 nn_assert (rc < 0);
120 errno_assert (nn_errno () == EINVAL);
121 rc = nn_connect (sc, "tcp://abc...123:5555");
122 nn_assert (rc < 0);
123 errno_assert (nn_errno () == EINVAL);
124 rc = nn_connect (sc, "tcp://.123:5555");
125 nn_assert (rc < 0);
126 errno_assert (nn_errno () == EINVAL);
127
128 /* Connect correctly. Do so before binding the peer socket. */
129 test_connect (sc, socket_address);
130
131 /* Leave enough time for at least on re-connect attempt. */
132 nn_sleep (200);
133
134 sb = test_socket (AF_SP, NN_PAIR);
135 test_bind (sb, socket_address);
136
137 /* Ping-pong test. */
138 for (i = 0; i != 100; ++i) {
139
140 test_send (sc, "ABC");
141 test_recv (sb, "ABC");
142
143 test_send (sb, "DEF");
144 test_recv (sc, "DEF");
145 }
146
147 /* Batch transfer test. */
148 for (i = 0; i != 100; ++i) {
149 test_send (sc, "0123456789012345678901234567890123456789");
150 }
151 for (i = 0; i != 100; ++i) {
152 test_recv (sb, "0123456789012345678901234567890123456789");
153 }
154
155 test_close (sc);
156 test_close (sb);
157
158 /* Test whether connection rejection is handled decently. */
159 sb = test_socket (AF_SP, NN_PAIR);
160 test_bind (sb, socket_address);
161 s1 = test_socket (AF_SP, NN_PAIR);
162 test_connect (s1, socket_address);
163 s2 = test_socket (AF_SP, NN_PAIR);
164 test_connect (s2, socket_address);
165 nn_sleep (100);
166 test_close (s2);
167 test_close (s1);
168 test_close (sb);
169
170 /* Test two sockets binding to the same address. */
171 sb = test_socket (AF_SP, NN_PAIR);
172 test_bind (sb, socket_address);
173 s1 = test_socket (AF_SP, NN_PAIR);
174
175 rc = nn_bind (s1, socket_address);
176 nn_assert (rc < 0);
177 errno_assert (nn_errno () == EADDRINUSE);
178
179 sc = test_socket (AF_SP, NN_PAIR);
180 test_connect (sc, socket_address);
181 nn_sleep (100);
182 test_send (sb, "ABC");
183 test_recv (sc, "ABC");
184 test_close (sb);
185 test_close (sc);
186 test_close (s1);
187
188 /* Test NN_RCVMAXSIZE limit */
189 sb = test_socket (AF_SP, NN_PAIR);
190 test_bind (sb, socket_address);
191 s1 = test_socket (AF_SP, NN_PAIR);
192 test_connect (s1, socket_address);
193 opt = 4;
194 rc = nn_setsockopt (sb, NN_SOL_SOCKET, NN_RCVMAXSIZE, &opt, sizeof (opt));
195 nn_assert (rc == 0);
196 nn_sleep (100);
197 test_send (s1, "ABC");
198 test_recv (sb, "ABC");
199 test_send (s1, "0123456789012345678901234567890123456789");
200 rc = nn_recv (sb, &dummy_buf, NN_MSG, NN_DONTWAIT);
201 nn_assert (rc < 0);
202 errno_assert (nn_errno () == EAGAIN);
203 test_close (sb);
204 test_close (s1);
205
206 /* Test that NN_RCVMAXSIZE can be -1, but not lower */
207 sb = test_socket (AF_SP, NN_PAIR);
208 opt = -1;
209 rc = nn_setsockopt (sb, NN_SOL_SOCKET, NN_RCVMAXSIZE, &opt, sizeof (opt));
210 nn_assert (rc >= 0);
211 opt = -2;
212 rc = nn_setsockopt (sb, NN_SOL_SOCKET, NN_RCVMAXSIZE, &opt, sizeof (opt));
213 nn_assert (rc < 0);
214 errno_assert (nn_errno () == EINVAL);
215 test_close (sb);
216
217 /* Test closing a socket that is waiting to connect. */
218 sc = test_socket (AF_SP, NN_PAIR);
219 test_connect (sc, socket_address);
220 nn_sleep (100);
221 test_close (sc);
222
223 return 0;
224 }
225