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 1 : 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 1 : } 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 1 : 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 1 : 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 1 : set_name("unix-server-client"); 175 : #ifdef _DEBUG 176 1 : f_dispatcher->set_trace(); 177 : #endif 178 1 : set_dispatcher(f_dispatcher); 179 : 180 9 : 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 1 : } 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 1 : 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 2 : 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