Line data Source code
1 : // Copyright (c) 2012-2021 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 lib
26 : //
27 : #include <eventdispatcher/local_stream_client_permanent_message_connection.h>
28 : #include <eventdispatcher/local_stream_server_client_message_connection.h>
29 : #include <eventdispatcher/local_stream_server_connection.h>
30 : #include <eventdispatcher/dispatcher.h>
31 :
32 :
33 : // C lib
34 : //
35 : #include <unistd.h>
36 :
37 :
38 : namespace
39 : {
40 :
41 :
42 :
43 : class unix_server;
44 :
45 :
46 :
47 1 : class unix_client
48 : : public ed::local_stream_client_permanent_message_connection
49 : {
50 : public:
51 : typedef std::shared_ptr<unix_client> pointer_t;
52 :
53 : unix_client(addr::unix const & address);
54 :
55 : void send_hello();
56 : void msg_hi(ed::message & msg);
57 :
58 : private:
59 : ed::dispatcher<unix_client>::pointer_t
60 : f_dispatcher = ed::dispatcher<unix_client>::pointer_t();
61 : };
62 :
63 :
64 1 : class unix_server_client
65 : : public ed::local_stream_server_client_message_connection
66 : {
67 : public:
68 : typedef std::shared_ptr<unix_server_client> pointer_t;
69 :
70 : unix_server_client(snap::raii_fd_t s, unix_server * server);
71 : unix_server_client(unix_server_client const & rhs) = delete;
72 : unix_server_client & operator = (unix_server_client const & rhs) = delete;
73 :
74 : void msg_hello(ed::message & msg);
75 : void msg_down(ed::message & msg);
76 :
77 : // connection implementation
78 : //
79 : void process_hup();
80 :
81 : private:
82 : unix_server * f_server = nullptr;
83 : ed::dispatcher<unix_server_client>::pointer_t
84 : f_dispatcher = ed::dispatcher<unix_server_client>::pointer_t();
85 : };
86 :
87 :
88 : class unix_server
89 : : public ed::local_stream_server_connection
90 : {
91 : public:
92 : typedef std::shared_ptr<unix_server> pointer_t;
93 :
94 : unix_server(addr::unix const & address);
95 : ~unix_server();
96 :
97 : void done();
98 :
99 : // connection implementation
100 : //
101 : virtual void process_accept() override;
102 :
103 : private:
104 : };
105 :
106 :
107 :
108 :
109 :
110 2 : ed::dispatcher<unix_client>::dispatcher_match::vector_t const g_unix_client_messages =
111 : {
112 : {
113 : "HI"
114 : , &unix_client::msg_hi
115 : },
116 :
117 : // ALWAYS LAST
118 : {
119 : nullptr
120 : , &unix_client::msg_reply_with_unknown
121 : , &ed::dispatcher<unix_client>::dispatcher_match::always_match
122 : }
123 : };
124 :
125 2 : ed::dispatcher<unix_server_client>::dispatcher_match::vector_t const g_unix_server_client_messages =
126 : {
127 : {
128 : "HELLO"
129 : , &unix_server_client::msg_hello
130 : },
131 : {
132 : "DOWN"
133 : , &unix_server_client::msg_down
134 : },
135 :
136 : // ALWAYS LAST
137 : {
138 : nullptr
139 : , &unix_client::msg_reply_with_unknown
140 : , &ed::dispatcher<unix_server_client>::dispatcher_match::always_match
141 : }
142 : };
143 :
144 :
145 :
146 :
147 :
148 1 : unix_client::unix_client(addr::unix const & address)
149 : : local_stream_client_permanent_message_connection(address)
150 : , f_dispatcher(new ed::dispatcher<unix_client>(
151 : this
152 1 : , g_unix_client_messages))
153 : {
154 1 : set_name("unix-client");
155 : #ifdef _DEBUG
156 1 : f_dispatcher->set_trace();
157 : #endif
158 1 : set_dispatcher(f_dispatcher);
159 1 : }
160 :
161 :
162 1 : void unix_client::send_hello()
163 : {
164 : // send the HELLO message, since we're not going to be connected yet
165 : // we ask for the permanent connection to cache the message
166 : //
167 2 : ed::message hello;
168 1 : hello.set_command("HELLO");
169 1 : send_message(hello, true);
170 1 : }
171 :
172 :
173 1 : void unix_client::msg_hi(ed::message & msg)
174 : {
175 1 : CATCH_REQUIRE(msg.get_command() == "HI");
176 :
177 2 : ed::message down;
178 1 : down.set_command("DOWN");
179 1 : send_message(down);
180 :
181 1 : mark_done(true);
182 : //ed::communicator::instance()->remove_connection(shared_from_this());
183 1 : }
184 :
185 :
186 :
187 :
188 :
189 1 : unix_server_client::unix_server_client(snap::raii_fd_t s, unix_server * server)
190 1 : : local_stream_server_client_message_connection(std::move(s))
191 : , f_server(server)
192 : , f_dispatcher(new ed::dispatcher<unix_server_client>(
193 : this
194 2 : , g_unix_server_client_messages))
195 : {
196 1 : set_name("unix-server-client");
197 : #ifdef _DEBUG
198 1 : f_dispatcher->set_trace();
199 : #endif
200 1 : set_dispatcher(f_dispatcher);
201 1 : }
202 :
203 :
204 1 : void unix_server_client::msg_hello(ed::message & msg)
205 : {
206 1 : CATCH_REQUIRE(msg.get_command() == "HELLO");
207 1 : snap::NOT_USED(msg);
208 :
209 2 : ed::message hi;
210 1 : hi.set_command("HI");
211 1 : send_message(hi);
212 1 : }
213 :
214 :
215 1 : void unix_server_client::msg_down(ed::message & msg)
216 : {
217 1 : CATCH_REQUIRE(msg.get_command() == "DOWN");
218 :
219 1 : ed::communicator::instance()->remove_connection(shared_from_this());
220 1 : }
221 :
222 :
223 1 : void unix_server_client::process_hup()
224 : {
225 : // make sure the server is gone too
226 1 : f_server->done();
227 1 : }
228 :
229 :
230 :
231 :
232 :
233 :
234 :
235 :
236 1 : unix_server::unix_server(addr::unix const & address)
237 1 : : local_stream_server_connection(address)
238 : {
239 1 : }
240 :
241 :
242 1 : unix_server::~unix_server()
243 : {
244 1 : }
245 :
246 :
247 1 : void unix_server::done()
248 : {
249 1 : ed::communicator::instance()->remove_connection(shared_from_this());
250 1 : }
251 :
252 :
253 1 : void unix_server::process_accept()
254 : {
255 2 : snap::raii_fd_t s(accept());
256 1 : CATCH_REQUIRE(s != nullptr);
257 :
258 2 : unix_server_client::pointer_t server_client(std::make_shared<unix_server_client>(std::move(s), this));
259 1 : CATCH_REQUIRE(server_client != nullptr);
260 :
261 1 : ed::communicator::instance()->add_connection(server_client);
262 1 : }
263 :
264 :
265 :
266 :
267 :
268 :
269 : } // no name namespace
270 :
271 :
272 :
273 3 : CATCH_TEST_CASE("local_stream_messaging", "[local-stream]")
274 : {
275 2 : CATCH_START_SECTION("Create a Server, Client, Connect & Send Messages")
276 : {
277 2 : ed::communicator::pointer_t communicator(ed::communicator::instance());
278 :
279 2 : std::string name("test-unix-stream");
280 1 : unlink(name.c_str());
281 1 : addr::unix server_address(name);
282 2 : unix_server::pointer_t server(std::make_shared<unix_server>(server_address));
283 1 : communicator->add_connection(server);
284 :
285 1 : addr::unix client_address(name);
286 2 : unix_client::pointer_t client(std::make_shared<unix_client>(client_address));
287 1 : communicator->add_connection(client);
288 :
289 1 : client->send_hello();
290 :
291 1 : communicator->run();
292 : }
293 : CATCH_END_SECTION()
294 7 : }
295 :
296 :
297 : // vim: ts=4 sw=4 et
|