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