1 /*
2 * Copyright (c) 2012 Martin Sustrik All rights reserved.
3 * Copyright (c) 2013 GoPivotal, Inc. All rights reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include <nng/compat/nanomsg/nn.h>
25 #include <nng/compat/nanomsg/bus.h>
26 #include <nng/compat/nanomsg/pair.h>
27 #include <nng/compat/nanomsg/pipeline.h>
28 #include <nng/compat/nanomsg/inproc.h>
29 #include "compat_testutil.h"
30
31 #define SOCKET_ADDRESS_A "inproc://a"
32 #define SOCKET_ADDRESS_B "inproc://b"
33 #define SOCKET_ADDRESS_C "inproc://c"
34 #define SOCKET_ADDRESS_D "inproc://d"
35 #define SOCKET_ADDRESS_E "inproc://e"
36
37 int deva = -1;
38 int devb = -1;
39 int devc = -1;
40 int devd = -1;
41 int deve = -1;
42
device1(NN_UNUSED void * arg)43 void device1(NN_UNUSED void *arg)
44 {
45 int rc;
46
47 /* Intialise the device sockets. */
48 deva = test_socket(AF_SP_RAW, NN_PAIR);
49 test_bind(deva, SOCKET_ADDRESS_A);
50 devb = test_socket(AF_SP_RAW, NN_PAIR);
51 test_bind(devb, SOCKET_ADDRESS_B);
52
53 /* Run the device. */
54 rc = nn_device(deva, devb);
55 nn_assert(rc < 0 && (nn_errno() == EBADF));
56 }
57
58
device2(NN_UNUSED void * arg)59 void device2(NN_UNUSED void *arg)
60 {
61 int rc;
62
63 /* Intialise the device sockets. */
64 devc = test_socket(AF_SP_RAW, NN_PULL);
65 test_bind(devc, SOCKET_ADDRESS_C);
66 devd = test_socket(AF_SP_RAW, NN_PUSH);
67 test_bind(devd, SOCKET_ADDRESS_D);
68
69 /* Run the device. */
70 rc = nn_device(devc, devd);
71 nn_assert(rc < 0 && nn_errno() == EBADF);
72 }
73
74
device3(NN_UNUSED void * arg)75 void device3(NN_UNUSED void *arg)
76 {
77 int rc;
78
79 /* Intialise the device socket. */
80 deve = test_socket(AF_SP_RAW, NN_BUS);
81 test_bind(deve, SOCKET_ADDRESS_E);
82
83 /* Run the device. */
84 rc = nn_device(deve, -1);
85 nn_assert(rc < 0 && nn_errno() == EBADF);
86 }
87
88
main()89 int main()
90 {
91 int enda;
92 int endb;
93 int endc;
94 int endd;
95 int ende1;
96 int ende2;
97 struct nn_thread thread1;
98 struct nn_thread thread2;
99 struct nn_thread thread3;
100 int timeo;
101
102 /* Test the bi-directional device. */
103
104 /* Start the device. */
105 nn_thread_init(&thread1, device1, NULL);
106
107 /* Create two sockets to connect to the device. */
108 enda = test_socket(AF_SP, NN_PAIR);
109 test_connect(enda, SOCKET_ADDRESS_A);
110 endb = test_socket(AF_SP, NN_PAIR);
111 test_connect(endb, SOCKET_ADDRESS_B);
112
113 nn_sleep(100);
114
115 /* Pass a pair of messages between endpoints. */
116 test_send(enda, "ABC");
117 test_recv(endb, "ABC");
118 test_send(endb, "ABC");
119 test_recv(enda, "ABC");
120
121 /* Clean up. */
122 test_close(endb);
123 test_close(enda);
124 test_close(deva);
125 test_close(devb);
126
127 /* Test the uni-directional device. */
128
129 /* Start the device. */
130 nn_thread_init(&thread2, device2, NULL);
131
132 nn_sleep(100);
133
134 /* Create two sockets to connect to the device. */
135 endc = test_socket(AF_SP, NN_PUSH);
136 test_connect(endc, SOCKET_ADDRESS_C);
137 endd = test_socket(AF_SP, NN_PULL);
138 test_connect(endd, SOCKET_ADDRESS_D);
139
140
141 /* Pass a message between endpoints. */
142 test_send(endc, "XYZ");
143 test_recv(endd, "XYZ");
144
145 /* Clean up. */
146 test_close(endd);
147 test_close(endc);
148 test_close(devc);
149 test_close(devd);
150
151 /* Test the loopback device. */
152
153 /* Start the device. */
154 nn_thread_init(&thread3, device3, NULL);
155 nn_sleep(100);
156
157 /* Create two sockets to connect to the device. */
158 ende1 = test_socket(AF_SP, NN_BUS);
159 test_connect(ende1, SOCKET_ADDRESS_E);
160 ende2 = test_socket(AF_SP, NN_BUS);
161 test_connect(ende2, SOCKET_ADDRESS_E);
162
163 /* BUS is unreliable so wait a bit for connections to be established. */
164 nn_sleep(200);
165
166 /* Pass a message to the bus. */
167 test_send(ende1, "KLM");
168 test_recv(ende2, "KLM");
169
170 /* Make sure that the message doesn't arrive at the socket it was
171 * originally sent to. */
172 timeo = 100;
173 test_setsockopt(ende1, NN_SOL_SOCKET, NN_RCVTIMEO,
174 &timeo, sizeof (timeo));
175 test_drop(ende1, ETIMEDOUT);
176
177 /* Clean up. */
178 test_close(ende2);
179 test_close(ende1);
180 test_close(deve);
181
182 /* Shut down the devices. */
183 nn_term();
184 nn_thread_term(&thread1);
185 nn_thread_term(&thread2);
186 nn_thread_term(&thread3);
187
188 return (0);
189 }
190