1 //
2 // Copyright 2018 Capitar IT Group BV <info@capitar.com>
3 // Copyright 2021 Staysail Systems, Inc. <info@staysail.tech>
4 //
5 // This software is supplied under the terms of the MIT License, a
6 // copy of which should be located in the distribution where this
7 // file was obtained (LICENSE.txt). A copy of the license may also be
8 // found online at https://opensource.org/licenses/MIT.
9 //
10
11 // TLS tests.
12
13 #ifndef _WIN32
14 #include <arpa/inet.h>
15 #endif
16
17 #include <nng/nng.h>
18 #include <nng/protocol/pair1/pair.h>
19 #include <nng/supplemental/tls/tls.h>
20 #include <nng/transport/tls/tls.h>
21
22 #include "convey.h"
23 #include "stubs.h"
24 #include "trantest.h"
25
26 // These keys are for demonstration purposes ONLY. DO NOT USE.
27 // The certificate is valid for 100 years, because I don't want to
28 // have to regenerate it ever again. The CN is 127.0.0.1, and self-signed.
29 //
30
31 static const char cert[] =
32 "-----BEGIN CERTIFICATE-----\n"
33 "MIIDRzCCAi8CFCOIJGs6plMawgBYdDuCRV7UuJuyMA0GCSqGSIb3DQEBCwUAMF8x\n"
34 "CzAJBgNVBAYTAlhYMQ8wDQYDVQQIDAZVdG9waWExETAPBgNVBAcMCFBhcmFkaXNl\n"
35 "MRgwFgYDVQQKDA9OTkcgVGVzdHMsIEluYy4xEjAQBgNVBAMMCWxvY2FsaG9zdDAg\n"
36 "Fw0yMDA1MjMyMzMxMTlaGA8yMTIwMDQyOTIzMzExOVowXzELMAkGA1UEBhMCWFgx\n"
37 "DzANBgNVBAgMBlV0b3BpYTERMA8GA1UEBwwIUGFyYWRpc2UxGDAWBgNVBAoMD05O\n"
38 "RyBUZXN0cywgSW5jLjESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0B\n"
39 "AQEFAAOCAQ8AMIIBCgKCAQEAyPdnRbMrQj9902TGQsmMbG6xTSl9XKbJr55BcnyZ\n"
40 "ifsrqA7BbNSkndVw9Qq+OJQIDBTfRhGdG+o9j3h6SDVvIb62fWtwJ5Fe0eUmeYwP\n"
41 "c1PKQzOmMFlMYekXiZsx60yu5LeuUhGlb84+csImH+m3NbutInPJcStSq0WfSV6V\n"
42 "Nk6DN3535ex66zV2Ms6ikys1vCC434YqIpe1VxUh+IC2widJcLDCxmmJt3TOlx5f\n"
43 "9OcKMkxuH4fMAzgjIEpIrUjdb19CGNVvsNrEEB2CShBMgBdqMaAnKFxpKgfzS0JF\n"
44 "ulxRGNtpsrweki+j+a4sJXTv40kELkRQS6uB6wWZNjcPywIDAQABMA0GCSqGSIb3\n"
45 "DQEBCwUAA4IBAQA86Fqrd4aiih6R3fwiMLwV6IQJv+u5rQeqA4D0xu6v6siP42SJ\n"
46 "YMaI2DkNGrWdSFVSHUK/efceCrhnMlW7VM8I1cyl2F/qKMfnT72cxqqquiKtQKdT\n"
47 "NDTzv61QMUP9n86HxMzGS7jg0Pknu55BsIRNK6ndDvI3D/K/rzZs4xbqWSSfNfQs\n"
48 "fNFBbOuDrkS6/1h3p8SY1uPM18WLVv3GO2T3aeNMHn7YJAKSn+sfaxzAPyPIK3UT\n"
49 "W8ecGQSHOqBJJQELyUfMu7lx/FCYKUhN7/1uhU5Qf1pCR8hkIMegtqr64yVBNMOn\n"
50 "248fuiHbs9BRknuA/PqjxIDDZTwtDrfVSO/S\n"
51 "-----END CERTIFICATE-----\n";
52
53 static const char key[] =
54 "-----BEGIN RSA PRIVATE KEY-----\n"
55 "MIIEowIBAAKCAQEAyPdnRbMrQj9902TGQsmMbG6xTSl9XKbJr55BcnyZifsrqA7B\n"
56 "bNSkndVw9Qq+OJQIDBTfRhGdG+o9j3h6SDVvIb62fWtwJ5Fe0eUmeYwPc1PKQzOm\n"
57 "MFlMYekXiZsx60yu5LeuUhGlb84+csImH+m3NbutInPJcStSq0WfSV6VNk6DN353\n"
58 "5ex66zV2Ms6ikys1vCC434YqIpe1VxUh+IC2widJcLDCxmmJt3TOlx5f9OcKMkxu\n"
59 "H4fMAzgjIEpIrUjdb19CGNVvsNrEEB2CShBMgBdqMaAnKFxpKgfzS0JFulxRGNtp\n"
60 "srweki+j+a4sJXTv40kELkRQS6uB6wWZNjcPywIDAQABAoIBAQCGSUsot+BgFCzv\n"
61 "5JbWafb7Pbwb421xS8HZJ9Zzue6e1McHNVTqc+zLyqQAGX2iMMhvykKnf32L+anJ\n"
62 "BKgxOANaeSVYCUKYLfs+JfDfp0druMGexhR2mjT/99FSkfF5WXREQLiq/j+dxiLU\n"
63 "bActq+5QaWf3bYddp6VF7O/TBvCNqBfD0+S0o0wtBdvxXItrKPTD5iKr9JfLWdAt\n"
64 "YNAk2QgFywFtY5zc2wt4queghF9GHeBzzZCuVj9QvPA4WdVq0mePaPTmvTYQUD0j\n"
65 "GT6X5j9JhqCwfh7trb/HfkmLHwwc62zPDFps+Dxao80+vss5b/EYZ4zY3S/K3vpG\n"
66 "f/e42S2BAoGBAP51HQYFJGC/wsNtOcX8RtXnRo8eYmyboH6MtBFrZxWl6ERigKCN\n"
67 "5Tjni7EI3nwi3ONg0ENPFkoQ8h0bcVFS7iW5kz5te73WaOFtpkU9rmuFDUz37eLP\n"
68 "d+JLZ5Kwfn2FM9HoiSAZAHowE0MIlmmIEXSnFtqA2zzorPQLO/4QlR+VAoGBAMov\n"
69 "R0yaHg3qPlxmCNyLXKiGaGNzvsvWjYw825uCGmVZfhzDhOiCFMaMb51BS5Uw/gwm\n"
70 "zHxmJjoqak8JjxaQ1qKPoeY1TJ5ps1+TRq9Wzm2/zGqJHOXnRPlqwBQ6AFllAMgt\n"
71 "Rlp5uqb8QJ+YEo6/1kdGhw9kZWCZEEue6MNQjxnfAoGARLkUkZ+p54di7qz9QX+V\n"
72 "EghYgibOpk6R1hviNiIvwSUByhZgbvxjwC6pB7NBg31W8wIevU8K0g4plbrnq/Md\n"
73 "5opsPhwLo4XY5albkq/J/7f7k6ISWYN2+WMsIe4Q+42SJUsMXeLiwh1h1mTnWrEp\n"
74 "JbxK69CJZbXhoDe4iDGqVNECgYAjlgS3n9ywWE1XmAHxR3osk1OmRYYMfJv3VfLV\n"
75 "QSYCNqkyyNsIzXR4qdkvVYHHJZNhcibFsnkB/dsuRCFyOFX+0McPLMxqiXIv3U0w\n"
76 "qVe2C28gRTfX40fJmpdqN/c9xMBJe2aJoClRIM8DCBIkG/HMI8a719DcGrS6iqKv\n"
77 "VeuKAwKBgEgD+KWW1KtoSjCBlS0NP8HjC/Rq7j99YhKE6b9h2slIa7JTO8RZKCa0\n"
78 "qbuomdUeJA3R8h+5CFkEKWqO2/0+dUdLNOjG+CaTFHaUJevzHOzIjpn+VsfCLV13\n"
79 "yupGzHG+tGtdrWgLn9Dzdp67cDfSnsSh+KODPECAAFfo+wPvD8DS\n"
80 "-----END RSA PRIVATE KEY-----\n";
81
82 static int
check_props_v4(nng_msg * msg)83 check_props_v4(nng_msg *msg)
84 {
85 nng_pipe p;
86 size_t z;
87 bool b;
88 nng_sockaddr la;
89 nng_sockaddr ra;
90
91 p = nng_msg_get_pipe(msg);
92 So(nng_pipe_id(p) > 0);
93
94 // Typed access
95 So(nng_pipe_getopt_sockaddr(p, NNG_OPT_LOCADDR, &la) == 0);
96 So(la.s_family == NNG_AF_INET);
97 So(la.s_in.sa_port == htons(trantest_port - 1));
98 So(la.s_in.sa_port != 0);
99 So(la.s_in.sa_addr == htonl(0x7f000001));
100
101 // Untyped access
102 z = sizeof(nng_sockaddr);
103 So(nng_pipe_getopt(p, NNG_OPT_REMADDR, &ra, &z) == 0);
104 So(z == sizeof(ra));
105 So(ra.s_family == NNG_AF_INET);
106 So(ra.s_in.sa_port != 0);
107 So(ra.s_in.sa_addr == htonl(0x7f000001));
108
109 So(nng_pipe_getopt_bool(p, NNG_OPT_TCP_KEEPALIVE, &b) == 0);
110 So(b == false); // default
111
112 So(nng_pipe_getopt_bool(p, NNG_OPT_TCP_NODELAY, &b) == 0);
113 So(b == true); // default
114
115 // Check for type enforcement
116 int i;
117 So(nng_pipe_getopt_int(p, NNG_OPT_REMADDR, &i) == NNG_EBADTYPE);
118
119 z = 1;
120 So(nng_pipe_getopt(p, NNG_OPT_REMADDR, &ra, &z) == NNG_EINVAL);
121
122 return (0);
123 }
124
125 static int
init_dialer_tls_ex(nng_dialer d,bool own_cert)126 init_dialer_tls_ex(nng_dialer d, bool own_cert)
127 {
128 nng_tls_config *cfg;
129 int rv;
130
131 if ((rv = nng_tls_config_alloc(&cfg, NNG_TLS_MODE_CLIENT)) != 0) {
132 return (rv);
133 }
134
135 if ((rv = nng_tls_config_ca_chain(cfg, cert, NULL)) != 0) {
136 goto out;
137 }
138
139 if ((rv = nng_tls_config_server_name(cfg, "localhost")) != 0) {
140 goto out;
141 }
142 nng_tls_config_auth_mode(cfg, NNG_TLS_AUTH_MODE_REQUIRED);
143
144 if (own_cert) {
145 if ((rv = nng_tls_config_own_cert(cfg, cert, key, NULL)) !=
146 0) {
147 goto out;
148 }
149 }
150
151 rv = nng_dialer_setopt_ptr(d, NNG_OPT_TLS_CONFIG, cfg);
152
153 out:
154 nng_tls_config_free(cfg);
155 return (rv);
156 }
157
158 static int
init_dialer_tls(nng_dialer d)159 init_dialer_tls(nng_dialer d)
160 {
161 return (init_dialer_tls_ex(d, false));
162 }
163
164 static int
init_listener_tls_ex(nng_listener l,int auth_mode)165 init_listener_tls_ex(nng_listener l, int auth_mode)
166 {
167 nng_tls_config *cfg;
168 int rv;
169
170 if ((rv = nng_tls_config_alloc(&cfg, NNG_TLS_MODE_SERVER)) != 0) {
171 return (rv);
172 }
173 if ((rv = nng_tls_config_own_cert(cfg, cert, key, NULL)) != 0) {
174 goto out;
175 }
176 if ((rv = nng_listener_setopt_ptr(l, NNG_OPT_TLS_CONFIG, cfg)) != 0) {
177 goto out;
178 }
179 switch (auth_mode) {
180 case NNG_TLS_AUTH_MODE_REQUIRED:
181 case NNG_TLS_AUTH_MODE_OPTIONAL:
182 if ((rv = nng_tls_config_ca_chain(cfg, cert, NULL)) != 0) {
183 goto out;
184 }
185 break;
186 default:
187 break;
188 }
189 if ((rv = nng_tls_config_auth_mode(cfg, auth_mode)) != 0) {
190 goto out;
191 }
192 out:
193 nng_tls_config_free(cfg);
194 return (0);
195 }
196
197 static int
init_listener_tls(nng_listener l)198 init_listener_tls(nng_listener l)
199 {
200 return (init_listener_tls_ex(l, NNG_TLS_AUTH_MODE_NONE));
201 }
202
203 static int
init_dialer_tls_file(nng_dialer d)204 init_dialer_tls_file(nng_dialer d)
205 {
206 int rv;
207 char *tmpdir;
208 char *pth;
209
210 if ((tmpdir = nni_plat_temp_dir()) == NULL) {
211 return (NNG_ENOTSUP);
212 }
213 if ((pth = nni_file_join(tmpdir, "tls_test_cacert.pem")) == NULL) {
214 nni_strfree(tmpdir);
215 return (NNG_ENOMEM);
216 }
217 nni_strfree(tmpdir);
218
219 if ((rv = nni_file_put(pth, cert, strlen(cert))) != 0) {
220 nni_strfree(pth);
221 return (rv);
222 }
223
224 rv = nng_dialer_setopt_string(d, NNG_OPT_TLS_CA_FILE, pth);
225 nni_file_delete(pth);
226 nni_strfree(pth);
227
228 return (rv);
229 }
230
231 static int
init_listener_tls_file(nng_listener l)232 init_listener_tls_file(nng_listener l)
233 {
234 int rv;
235 char *tmpdir;
236 char *pth;
237 char *certkey;
238
239 if ((tmpdir = nni_plat_temp_dir()) == NULL) {
240 return (NNG_ENOTSUP);
241 }
242
243 if ((pth = nni_file_join(tmpdir, "tls_test_certkey.pem")) == NULL) {
244 nni_strfree(tmpdir);
245 return (NNG_ENOMEM);
246 }
247 nni_strfree(tmpdir);
248
249 if ((rv = nni_asprintf(&certkey, "%s\r\n%s\r\n", cert, key)) != 0) {
250 nni_strfree(pth);
251 return (rv);
252 }
253
254 rv = nni_file_put(pth, certkey, strlen(certkey));
255 nni_strfree(certkey);
256 if (rv != 0) {
257 nni_strfree(pth);
258 return (rv);
259 }
260
261 rv = nng_listener_setopt_string(l, NNG_OPT_TLS_CERT_KEY_FILE, pth);
262 if (rv != 0) {
263 // We can wind up with EBUSY from the server already
264 // running.
265 if (rv == NNG_EBUSY) {
266 rv = 0;
267 }
268 }
269
270 nni_file_delete(pth);
271 nni_strfree(pth);
272 return (rv);
273 }
274
275 TestMain("TLS Transport", {
276 static trantest tt;
277
278 if (strcmp(nng_tls_engine_name(), "none") == 0) {
279 Skip("TLS not enabled");
280 }
281
282 tt.dialer_init = init_dialer_tls;
283 tt.listener_init = init_listener_tls;
284 tt.tmpl = "tls+tcp://127.0.0.1:%u";
285 tt.proptest = check_props_v4;
286
287 trantest_test(&tt);
288
289 Convey("We can register the TLS transport",
290 { So(nng_tls_register() == 0); });
291
292 Convey("We cannot connect to wild cards", {
293 nng_socket s;
294 char addr[NNG_MAXADDRLEN];
295
296 So(nng_tls_register() == 0);
297 So(nng_pair_open(&s) == 0);
298 Reset({ nng_close(s); });
299 trantest_next_address(addr, "tls+tcp://*:%u");
300 So(nng_dial(s, addr, NULL, 0) == NNG_EADDRINVAL);
301 });
302
303 Convey("We can bind to wild card", {
304 nng_socket s1;
305 nng_socket s2;
306 char addr[NNG_MAXADDRLEN];
307 nng_listener l;
308 nng_dialer d;
309
310 So(nng_tls_register() == 0);
311 So(nng_pair_open(&s1) == 0);
312 So(nng_pair_open(&s2) == 0);
313 Reset({
314 nng_close(s2);
315 nng_close(s1);
316 });
317 trantest_next_address(addr, "tls+tcp://*:%u");
318 So(nng_listener_create(&l, s1, addr) == 0);
319 So(init_listener_tls(l) == 0);
320 // reset port back one
321 trantest_prev_address(addr, "tls+tcp://127.0.0.1:%u");
322 So(nng_dialer_create(&d, s2, addr) == 0);
323 So(init_dialer_tls(d) == 0);
324 So(nng_dialer_setopt_int(
325 d, NNG_OPT_TLS_AUTH_MODE, NNG_TLS_AUTH_MODE_NONE) == 0);
326 So(nng_listener_start(l, 0) == 0);
327 So(nng_dialer_start(d, 0) == 0);
328 });
329
330 SkipConvey("We can bind to port zero", {
331 nng_socket s1;
332 nng_socket s2;
333 nng_listener l;
334 nng_dialer d;
335 char * addr;
336
337 So(nng_tls_register() == 0);
338 So(nng_pair_open(&s1) == 0);
339 So(nng_pair_open(&s2) == 0);
340 Reset({
341 nng_close(s2);
342 nng_close(s1);
343 });
344 So(nng_listener_create(&l, s1, "tls+tcp://127.0.0.1:0") == 0);
345 So(init_listener_tls(l) == 0);
346 So(nng_listener_start(l, 0) == 0);
347 So(nng_listener_getopt_string(l, NNG_OPT_URL, &addr) == 0);
348 So(nng_dialer_create(&d, s2, addr) == 0);
349 So(init_dialer_tls(d) == 0);
350 So(nng_dialer_setopt_int(
351 d, NNG_OPT_TLS_AUTH_MODE, NNG_TLS_AUTH_MODE_NONE) == 0);
352 So(nng_dialer_start(d, 0) == 0);
353 nng_strfree(addr);
354 });
355
356 Convey("Malformed TLS addresses do not panic", {
357 nng_socket s1;
358
359 So(nng_tls_register() == 0);
360 So(nng_pair_open(&s1) == 0);
361 Reset({ nng_close(s1); });
362
363 // Note that if we listen to an unspecified port, then we
364 // get a random port. So we don't look at that. This allows
365 // a user to obtain a port at random and then query to see
366 // which one was chosen.
367
368 So(nng_dial(s1, "tls+tcp://127.0.0.1", NULL, 0) ==
369 NNG_EADDRINVAL);
370 So(nng_dial(s1, "tls+tcp://127.0.0.1.32", NULL, 0) ==
371 NNG_EADDRINVAL);
372 So(nng_dial(s1, "tls+tcp://127.0.x.1.32", NULL, 0) ==
373 NNG_EADDRINVAL);
374 So(nng_listen(s1, "tls+tcp://127.0.0.1.32", NULL, 0) ==
375 NNG_EADDRINVAL);
376 So(nng_listen(s1, "tls+tcp://127.0.x.1.32", NULL, 0) ==
377 NNG_EADDRINVAL);
378 });
379
380 Convey("We can use local interface to connect", {
381 nng_socket s1;
382 nng_socket s2;
383 nng_listener l;
384 nng_dialer d;
385 char addr[NNG_MAXADDRLEN];
386
387 So(nng_pair_open(&s1) == 0);
388 So(nng_pair_open(&s2) == 0);
389 Reset({
390 nng_close(s2);
391 nng_close(s1);
392 });
393 trantest_next_address(addr, "tls+tcp://127.0.0.1:%u");
394 So(nng_listener_create(&l, s1, addr) == 0);
395 So(init_listener_tls(l) == 0);
396 So(nng_listener_start(l, 0) == 0);
397 // reset port back one
398 trantest_prev_address(
399 addr, "tls+tcp://127.0.0.1;127.0.0.1:%u");
400 So(nng_dialer_create(&d, s2, addr) == 0);
401 So(init_dialer_tls(d) == 0);
402 So(nng_dialer_start(d, 0) == 0);
403 });
404
405 Convey("Botched local interfaces fail reasonably", {
406 nng_socket s1;
407
408 So(nng_pair_open(&s1) == 0);
409 Reset({ nng_close(s1); });
410 So(nng_dial(s1, "tcp://1x.2;127.0.0.1:80", NULL, 0) ==
411 NNG_EADDRINVAL);
412 });
413
414 Convey("Can't specify address that isn't ours", {
415 nng_socket s1;
416
417 So(nng_pair_open(&s1) == 0);
418 Reset({ nng_close(s1); });
419 So(nng_dial(s1, "tcp://8.8.8.8;127.0.0.1:80", NULL, 0) ==
420 NNG_EADDRINVAL);
421 });
422
423 // We really need to have pipe start/negotiate as one of the key steps
424 // during connect establish. Until that happens, we cannot verify the
425 // peer. See bug #208.
426 SkipConvey("Verify works", {
427 nng_socket s1;
428 nng_socket s2;
429 nng_listener l;
430 size_t sz;
431 char addr[NNG_MAXADDRLEN];
432
433 So(nng_pair_open(&s1) == 0);
434 So(nng_pair_open(&s2) == 0);
435 Reset({
436 nng_close(s2);
437 nng_close(s1);
438 });
439 trantest_next_address(addr, "tls+tcp://:%u");
440 So(nng_listener_create(&l, s1, addr) == 0);
441 So(init_listener_tls_file(NULL, l) == 0);
442 So(nng_listener_start(l, 0) == 0);
443 nng_msleep(100);
444
445 // reset port back one
446 trantest_prev_address(addr, "tls+tcp://127.0.0.1:%u");
447 So(nng_setopt_int(s2, NNG_OPT_TLS_AUTH_MODE,
448 NNG_TLS_AUTH_MODE_REQUIRED) == 0);
449
450 So(nng_dial(s2, addr, NULL, 0) == NNG_EPEERAUTH);
451 });
452
453 Convey("No verify works", {
454 nng_socket s1; // server
455 nng_socket s2; // client
456 nng_listener l;
457 char addr[NNG_MAXADDRLEN];
458 nng_msg * msg;
459 nng_pipe p;
460 bool b;
461 nng_dialer d;
462
463 So(nng_pair_open(&s1) == 0);
464 So(nng_pair_open(&s2) == 0);
465 Reset({
466 nng_close(s2);
467 nng_close(s1);
468 });
469 trantest_next_address(addr, "tls+tcp://*:%u");
470 So(nng_listener_create(&l, s1, addr) == 0);
471 So(init_listener_tls_file(l) == 0);
472 So(nng_listener_setopt_int(l, NNG_OPT_TLS_AUTH_MODE,
473 NNG_TLS_AUTH_MODE_OPTIONAL) == 0);
474 So(nng_listener_start(l, 0) == 0);
475 nng_msleep(100);
476
477 // reset port back one
478 trantest_prev_address(addr, "tls+tcp://127.0.0.1:%u");
479 So(nng_setopt_ms(s2, NNG_OPT_RECVTIMEO, 200) == 0);
480 So(nng_dialer_create(&d, s2, addr) == 0);
481 So(init_dialer_tls_file(d) == 0);
482 So(nng_dialer_setopt_string(
483 d, NNG_OPT_TLS_SERVER_NAME, "localhost") == 0);
484 So(nng_dialer_start(d, 0) == 0);
485
486 So(nng_send(s2, "hello", 6, 0) == 0);
487 So(nng_recvmsg(s1, &msg, 0) == 0);
488 So(msg != NULL);
489 So(nng_msg_len(msg) == 6);
490 So(strcmp(nng_msg_body(msg), "hello") == 0);
491 p = nng_msg_get_pipe(msg);
492 So(nng_pipe_id(p) > 0);
493 So(nng_pipe_getopt_bool(p, NNG_OPT_TLS_VERIFIED, &b) == 0);
494 So(b == false);
495 nng_msg_free(msg);
496 });
497
498 Convey("Valid verify works", {
499 nng_socket s1;
500 nng_socket s2;
501 nng_listener l;
502 nng_dialer d;
503 char addr[NNG_MAXADDRLEN];
504 nng_msg * msg;
505 nng_pipe p;
506 bool b;
507
508 So(nng_pair_open(&s1) == 0);
509 So(nng_pair_open(&s2) == 0);
510 Reset({
511 nng_close(s2);
512 nng_close(s1);
513 });
514 trantest_next_address(addr, "tls+tcp4://*:%u");
515 So(nng_listener_create(&l, s1, addr) == 0);
516 So(init_listener_tls_ex(l, NNG_TLS_AUTH_MODE_REQUIRED) == 0);
517 So(nng_listener_start(l, 0) == 0);
518
519 nng_msleep(100);
520
521 // reset port back one
522 trantest_prev_address(addr, "tls+tcp4://localhost:%u");
523 So(nng_dialer_create(&d, s2, addr) == 0);
524 So(init_dialer_tls_ex(d, true) == 0);
525
526 So(nng_setopt_ms(s2, NNG_OPT_RECVTIMEO, 200) == 0);
527 So(nng_dialer_start(d, 0) == 0);
528 nng_msleep(100);
529
530 // send from the server to the client-- the client always
531 // verifies the server.
532 So(nng_send(s2, "hello", 6, 0) == 0);
533 So(nng_recvmsg(s1, &msg, 0) == 0);
534 So(msg != NULL);
535 So(nng_msg_len(msg) == 6);
536 So(strcmp(nng_msg_body(msg), "hello") == 0);
537 p = nng_msg_get_pipe(msg);
538 So(nng_pipe_id(p) > 0);
539 So(nng_pipe_getopt_bool(p, NNG_OPT_TLS_VERIFIED, &b) == 0);
540 So(b == true);
541 int i;
542 So(nng_pipe_getopt_int(p, NNG_OPT_TLS_VERIFIED, &i) ==
543 NNG_EBADTYPE);
544 nng_msg_free(msg);
545 });
546
547 Convey("No delay option", {
548 nng_socket s;
549 nng_dialer d;
550 nng_listener l;
551 bool v;
552 int x;
553
554 So(nng_pair_open(&s) == 0);
555 Reset({ nng_close(s); });
556 So(nng_getopt_bool(s, NNG_OPT_TCP_NODELAY, &v) == 0);
557 So(v == true);
558 So(nng_dialer_create(&d, s, "tcp://127.0.0.1:4999") == 0);
559 So(nng_dialer_getopt_bool(d, NNG_OPT_TCP_NODELAY, &v) == 0);
560 So(v == true);
561 So(nng_dialer_setopt_bool(d, NNG_OPT_TCP_NODELAY, false) == 0);
562 So(nng_dialer_getopt_bool(d, NNG_OPT_TCP_NODELAY, &v) == 0);
563 So(v == false);
564 So(nng_dialer_getopt_int(d, NNG_OPT_TCP_NODELAY, &x) ==
565 NNG_EBADTYPE);
566 x = 0;
567 So(nng_dialer_setopt_int(d, NNG_OPT_TCP_NODELAY, x) ==
568 NNG_EBADTYPE);
569 // This assumes sizeof (bool) != sizeof (int)
570 So(nng_dialer_setopt(d, NNG_OPT_TCP_NODELAY, &x, sizeof(x)) ==
571 NNG_EINVAL);
572
573 So(nng_listener_create(&l, s, "tcp://127.0.0.1:4999") == 0);
574 So(nng_listener_getopt_bool(l, NNG_OPT_TCP_NODELAY, &v) == 0);
575 So(v == true);
576 x = 0;
577 So(nng_listener_setopt_int(l, NNG_OPT_TCP_NODELAY, x) ==
578 NNG_EBADTYPE);
579 // This assumes sizeof (bool) != sizeof (int)
580 So(nng_listener_setopt(
581 l, NNG_OPT_TCP_NODELAY, &x, sizeof(x)) == NNG_EINVAL);
582
583 nng_dialer_close(d);
584 nng_listener_close(l);
585
586 // Make sure socket wide defaults apply.
587 So(nng_setopt_bool(s, NNG_OPT_TCP_NODELAY, true) == 0);
588 v = false;
589 So(nng_getopt_bool(s, NNG_OPT_TCP_NODELAY, &v) == 0);
590 So(v == true);
591 So(nng_setopt_bool(s, NNG_OPT_TCP_NODELAY, false) == 0);
592 So(nng_dialer_create(&d, s, "tcp://127.0.0.1:4999") == 0);
593 So(nng_dialer_getopt_bool(d, NNG_OPT_TCP_NODELAY, &v) == 0);
594 So(v == false);
595 });
596
597 Convey("Keepalive option", {
598 nng_socket s;
599 nng_dialer d;
600 nng_listener l;
601 bool v;
602 int x;
603
604 So(nng_pair_open(&s) == 0);
605 Reset({ nng_close(s); });
606 So(nng_getopt_bool(s, NNG_OPT_TCP_KEEPALIVE, &v) == 0);
607 So(v == false);
608 So(nng_dialer_create(&d, s, "tcp://127.0.0.1:4999") == 0);
609 So(nng_dialer_getopt_bool(d, NNG_OPT_TCP_KEEPALIVE, &v) == 0);
610 So(v == false);
611 So(nng_dialer_setopt_bool(d, NNG_OPT_TCP_KEEPALIVE, true) ==
612 0);
613 So(nng_dialer_getopt_bool(d, NNG_OPT_TCP_KEEPALIVE, &v) == 0);
614 So(v == true);
615 So(nng_dialer_getopt_int(d, NNG_OPT_TCP_KEEPALIVE, &x) ==
616 NNG_EBADTYPE);
617 x = 1;
618 So(nng_dialer_setopt_int(d, NNG_OPT_TCP_KEEPALIVE, x) ==
619 NNG_EBADTYPE);
620
621 So(nng_listener_create(&l, s, "tcp://127.0.0.1:4999") == 0);
622 So(nng_listener_getopt_bool(l, NNG_OPT_TCP_KEEPALIVE, &v) ==
623 0);
624 So(v == false);
625 x = 1;
626 So(nng_listener_setopt_int(l, NNG_OPT_TCP_KEEPALIVE, x) ==
627 NNG_EBADTYPE);
628
629 nng_dialer_close(d);
630 nng_listener_close(l);
631
632 // Make sure socket wide defaults apply.
633 So(nng_setopt_bool(s, NNG_OPT_TCP_KEEPALIVE, false) == 0);
634 v = true;
635 So(nng_getopt_bool(s, NNG_OPT_TCP_KEEPALIVE, &v) == 0);
636 So(v == false);
637 So(nng_setopt_bool(s, NNG_OPT_TCP_KEEPALIVE, true) == 0);
638 So(nng_dialer_create(&d, s, "tcp://127.0.0.1:4999") == 0);
639 So(nng_dialer_getopt_bool(d, NNG_OPT_TCP_KEEPALIVE, &v) == 0);
640 So(v == true);
641 });
642 })
643