Line data Source code
1 : // Copyright (c) 2012-2024 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/eventdispatcher
4 : // contact@m2osw.com
5 : //
6 : // This program is free software; you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation; either version 2 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License along
17 : // with this program; if not, write to the Free Software Foundation, Inc.,
18 : // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 :
20 : // self
21 : //
22 : #include "catch_main.h"
23 :
24 :
25 : // eventdispatcher
26 : //
27 : #include <eventdispatcher/communicator.h>
28 : #include <eventdispatcher/local_stream_client_permanent_message_connection.h>
29 : #include <eventdispatcher/local_stream_server_client_message_connection.h>
30 : #include <eventdispatcher/local_stream_server_connection.h>
31 : #include <eventdispatcher/dispatcher.h>
32 :
33 :
34 : // C
35 : //
36 : #include <unistd.h>
37 :
38 :
39 : // last include
40 : //
41 : #include <snapdev/poison.h>
42 :
43 :
44 :
45 : namespace
46 : {
47 :
48 :
49 :
50 : class unix_server;
51 :
52 :
53 :
54 : class unix_client
55 : : public ed::local_stream_client_permanent_message_connection
56 : {
57 : public:
58 : typedef std::shared_ptr<unix_client> pointer_t;
59 :
60 : unix_client(addr::addr_unix const & address);
61 :
62 : void send_hello();
63 : void msg_hi(ed::message & msg);
64 :
65 : private:
66 : ed::dispatcher::pointer_t
67 : f_dispatcher = ed::dispatcher::pointer_t();
68 : };
69 :
70 :
71 : class unix_server_client
72 : : public ed::local_stream_server_client_message_connection
73 : {
74 : public:
75 : typedef std::shared_ptr<unix_server_client> pointer_t;
76 :
77 : unix_server_client(snapdev::raii_fd_t s, unix_server * server);
78 : unix_server_client(unix_server_client const & rhs) = delete;
79 : unix_server_client & operator = (unix_server_client const & rhs) = delete;
80 :
81 : void msg_hello(ed::message & msg);
82 : void msg_down(ed::message & msg);
83 :
84 : // connection implementation
85 : //
86 : void process_hup();
87 :
88 : private:
89 : unix_server * f_server = nullptr;
90 : ed::dispatcher::pointer_t
91 : f_dispatcher = ed::dispatcher::pointer_t();
92 : };
93 :
94 :
95 : class unix_server
96 : : public ed::local_stream_server_connection
97 : {
98 : public:
99 : typedef std::shared_ptr<unix_server> pointer_t;
100 :
101 : unix_server(addr::addr_unix const & address);
102 : ~unix_server();
103 :
104 : void done();
105 :
106 : // connection implementation
107 : //
108 : virtual void process_accept() override;
109 :
110 : private:
111 : };
112 :
113 :
114 :
115 :
116 :
117 :
118 :
119 :
120 :
121 :
122 :
123 1 : unix_client::unix_client(addr::addr_unix const & address)
124 : : local_stream_client_permanent_message_connection(address)
125 1 : , f_dispatcher(std::make_shared<ed::dispatcher>(this))
126 : {
127 3 : set_name("unix-client");
128 : #ifdef _DEBUG
129 1 : f_dispatcher->set_trace();
130 : #endif
131 1 : set_dispatcher(f_dispatcher);
132 :
133 6 : f_dispatcher->add_matches({
134 2 : DISPATCHER_MATCH("HI", &unix_client::msg_hi),
135 :
136 : // ALWAYS LAST
137 2 : DISPATCHER_CATCH_ALL()
138 : });
139 5 : }
140 :
141 :
142 1 : void unix_client::send_hello()
143 : {
144 : // send the HELLO message, since we're not going to be connected yet
145 : // we ask for the permanent connection to cache the message
146 : //
147 1 : ed::message hello;
148 3 : hello.set_command("HELLO");
149 1 : send_message(hello, true);
150 2 : }
151 :
152 :
153 1 : void unix_client::msg_hi(ed::message & msg)
154 : {
155 1 : CATCH_REQUIRE(msg.get_command() == "HI");
156 :
157 1 : ed::message down;
158 3 : down.set_command("DOWN");
159 1 : send_message(down);
160 :
161 1 : mark_done(true);
162 : //ed::communicator::instance()->remove_connection(shared_from_this());
163 2 : }
164 :
165 :
166 :
167 :
168 :
169 1 : unix_server_client::unix_server_client(snapdev::raii_fd_t s, unix_server * server)
170 1 : : local_stream_server_client_message_connection(std::move(s))
171 1 : , f_server(server)
172 2 : , f_dispatcher(std::make_shared<ed::dispatcher>(this))
173 : {
174 3 : set_name("unix-server-client");
175 : #ifdef _DEBUG
176 1 : f_dispatcher->set_trace();
177 : #endif
178 1 : set_dispatcher(f_dispatcher);
179 :
180 7 : f_dispatcher->add_matches({
181 2 : DISPATCHER_MATCH("HELLO", &unix_server_client::msg_hello),
182 2 : DISPATCHER_MATCH("DOWN", &unix_server_client::msg_down),
183 :
184 : // ALWAYS LAST
185 2 : DISPATCHER_CATCH_ALL()
186 : });
187 7 : }
188 :
189 :
190 1 : void unix_server_client::msg_hello(ed::message & msg)
191 : {
192 1 : CATCH_REQUIRE(msg.get_command() == "HELLO");
193 1 : snapdev::NOT_USED(msg);
194 :
195 1 : ed::message hi;
196 3 : hi.set_command("HI");
197 1 : send_message(hi);
198 2 : }
199 :
200 :
201 1 : void unix_server_client::msg_down(ed::message & msg)
202 : {
203 1 : CATCH_REQUIRE(msg.get_command() == "DOWN");
204 :
205 1 : ed::communicator::instance()->remove_connection(shared_from_this());
206 1 : }
207 :
208 :
209 1 : void unix_server_client::process_hup()
210 : {
211 : // make sure the server is gone too
212 1 : f_server->done();
213 1 : }
214 :
215 :
216 :
217 :
218 :
219 :
220 :
221 :
222 1 : unix_server::unix_server(addr::addr_unix const & address)
223 1 : : local_stream_server_connection(address)
224 : {
225 1 : }
226 :
227 :
228 1 : unix_server::~unix_server()
229 : {
230 1 : }
231 :
232 :
233 1 : void unix_server::done()
234 : {
235 1 : ed::communicator::instance()->remove_connection(shared_from_this());
236 1 : }
237 :
238 :
239 1 : void unix_server::process_accept()
240 : {
241 1 : snapdev::raii_fd_t s(accept());
242 1 : CATCH_REQUIRE(s != nullptr);
243 :
244 1 : unix_server_client::pointer_t server_client(std::make_shared<unix_server_client>(std::move(s), this));
245 1 : CATCH_REQUIRE(server_client != nullptr);
246 :
247 1 : ed::communicator::instance()->add_connection(server_client);
248 2 : }
249 :
250 :
251 :
252 :
253 :
254 :
255 : } // no name namespace
256 :
257 :
258 :
259 1 : CATCH_TEST_CASE("local_stream_messaging", "[local-stream]")
260 : {
261 1 : CATCH_START_SECTION("Create a Server, Client, Connect & Send Messages")
262 : {
263 1 : ed::communicator::pointer_t communicator(ed::communicator::instance());
264 :
265 3 : std::string name("test-unix-stream");
266 1 : unlink(name.c_str());
267 1 : addr::addr_unix server_address(name);
268 1 : unix_server::pointer_t server(std::make_shared<unix_server>(server_address));
269 1 : communicator->add_connection(server);
270 :
271 1 : addr::addr_unix client_address(name);
272 1 : unix_client::pointer_t client(std::make_shared<unix_client>(client_address));
273 1 : communicator->add_connection(client);
274 :
275 1 : client->send_hello();
276 :
277 1 : communicator->run();
278 1 : }
279 1 : CATCH_END_SECTION()
280 1 : }
281 :
282 :
283 : // vim: ts=4 sw=4 et
|