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