Line data Source code
1 : // Snap Communicator -- classes to ease handling communication between processes
2 :
3 : // Copyright (c) 2012-2019 Made to Order Software Corp. All Rights Reserved
4 : //
5 : // This program is free software; you can redistribute it and/or modify
6 : // it under the terms of the GNU General Public License as published by
7 : // the Free Software Foundation; either version 2 of the License, or
8 : // (at your option) any later version.
9 : //
10 : // This program is distributed in the hope that it will be useful,
11 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 : // GNU General Public License for more details.
14 : //
15 : // You should have received a copy of the GNU General Public License
16 : // along with this program; if not, write to the Free Software
17 : // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 : #pragma once
19 :
20 : // self
21 : //
22 : #include "snapwebsites/snap_exception.h"
23 : #include "snapwebsites/snap_thread.h"
24 : #include "snapwebsites/tcp_client_server.h"
25 : #include "snapwebsites/udp_client_server.h"
26 : //#include "snapwebsites/log.h" -- not sensible here at this time because log.h includes snap_communicator.h -- See Jira SNAP-623
27 : #include "snapwebsites/snap_string_list.h"
28 :
29 : // snapdev lib
30 : //
31 : #include <snapdev/not_used.h>
32 :
33 : // Qt lib
34 : //
35 : #pragma GCC diagnostic push
36 : #pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
37 : #include <QMap>
38 : #pragma GCC diagnostic pop
39 :
40 : // C lib
41 : //
42 : #include <signal.h>
43 : #include <sys/signalfd.h>
44 :
45 :
46 : namespace snap
47 : {
48 :
49 0 : class snap_communicator_parameter_error : public snap_logic_exception
50 : {
51 : public:
52 0 : snap_communicator_parameter_error(char const * what_msg) : snap_logic_exception("snap_communicator", what_msg) {}
53 0 : snap_communicator_parameter_error(std::string const & what_msg) : snap_logic_exception("snap_communicator", what_msg) {}
54 0 : snap_communicator_parameter_error(QString const & what_msg) : snap_logic_exception("snap_communicator", what_msg) {}
55 : };
56 :
57 0 : class snap_communicator_implementation_error : public snap_logic_exception
58 : {
59 : public:
60 0 : snap_communicator_implementation_error(char const * what_msg) : snap_logic_exception("snap_communicator", what_msg) {}
61 : snap_communicator_implementation_error(std::string const & what_msg) : snap_logic_exception("snap_communicator", what_msg) {}
62 0 : snap_communicator_implementation_error(QString const & what_msg) : snap_logic_exception("snap_communicator", what_msg) {}
63 : };
64 :
65 0 : class snap_communicator_exception : public snap_exception
66 : {
67 : public:
68 0 : explicit snap_communicator_exception(char const * what_msg) : snap_exception("snap_communicator", what_msg) {}
69 0 : explicit snap_communicator_exception(std::string const & what_msg) : snap_exception("snap_communicator", what_msg) {}
70 0 : explicit snap_communicator_exception(QString const & what_msg) : snap_exception("snap_communicator", what_msg) {}
71 : };
72 :
73 0 : class snap_communicator_initialization_error : public snap_communicator_exception
74 : {
75 : public:
76 0 : snap_communicator_initialization_error(char const * what_msg) : snap_communicator_exception(what_msg) {}
77 : snap_communicator_initialization_error(std::string const & what_msg) : snap_communicator_exception(what_msg) {}
78 : snap_communicator_initialization_error(QString const & what_msg) : snap_communicator_exception(what_msg) {}
79 : };
80 :
81 0 : class snap_communicator_runtime_error : public snap_communicator_exception
82 : {
83 : public:
84 0 : snap_communicator_runtime_error(char const * what_msg) : snap_communicator_exception(what_msg) {}
85 0 : snap_communicator_runtime_error(std::string const & what_msg) : snap_communicator_exception(what_msg) {}
86 0 : snap_communicator_runtime_error(QString const & what_msg) : snap_communicator_exception(what_msg) {}
87 : };
88 :
89 0 : class snap_communicator_unexpected_data : public snap_communicator_exception
90 : {
91 : public:
92 0 : snap_communicator_unexpected_data(char const * what_msg) : snap_communicator_exception(what_msg) {}
93 : snap_communicator_unexpected_data(std::string const & what_msg) : snap_communicator_exception(what_msg) {}
94 : snap_communicator_unexpected_data(QString const & what_msg) : snap_communicator_exception(what_msg) {}
95 : };
96 :
97 0 : class snap_communicator_invalid_message : public snap_communicator_exception
98 : {
99 : public:
100 0 : snap_communicator_invalid_message(char const * what_msg) : snap_communicator_exception(what_msg) {}
101 : snap_communicator_invalid_message(std::string const & what_msg) : snap_communicator_exception(what_msg) {}
102 0 : snap_communicator_invalid_message(QString const & what_msg) : snap_communicator_exception(what_msg) {}
103 : };
104 :
105 :
106 :
107 0 : class snap_communicator_message
108 : {
109 : public:
110 : typedef QMap<QString, QString> parameters_t;
111 : typedef std::vector<snap_communicator_message> vector_t;
112 :
113 : bool from_message(QString const & message);
114 : QString to_message() const;
115 :
116 : QString const & get_sent_from_server() const;
117 : void set_sent_from_server(QString const & server);
118 : QString const & get_sent_from_service() const;
119 : void set_sent_from_service(QString const & service);
120 : QString const & get_server() const;
121 : void set_server(QString const & server);
122 : QString const & get_service() const;
123 : void set_service(QString const & service);
124 : void reply_to(snap_communicator_message const & message);
125 : QString const & get_command() const;
126 : void set_command(QString const & command);
127 : void add_parameter(QString const & name, char const * value);
128 : void add_parameter(QString const & name, std::string const & value);
129 : void add_parameter(QString const & name, QString const & value);
130 : void add_parameter(QString const & name, int32_t value);
131 : void add_parameter(QString const & name, uint32_t value);
132 : void add_parameter(QString const & name, int64_t value);
133 : void add_parameter(QString const & name, uint64_t value);
134 : bool has_parameter(QString const & name) const;
135 : QString const get_parameter(QString const & name) const;
136 : int64_t get_integer_parameter(QString const & name) const;
137 : parameters_t const & get_all_parameters() const;
138 :
139 : static void verify_name(QString const & name, bool can_be_empty = false, bool can_be_lowercase = true);
140 :
141 : private:
142 : QString f_sent_from_server = QString();
143 : QString f_sent_from_service = QString();
144 : QString f_server = QString();
145 : QString f_service = QString();
146 : QString f_command = QString();
147 : parameters_t f_parameters = parameters_t();
148 : mutable QString f_cached_message = QString();
149 : };
150 :
151 :
152 :
153 0 : class dispatcher_base
154 : {
155 : public:
156 : typedef std::shared_ptr<dispatcher_base> pointer_t;
157 : typedef std::weak_ptr<dispatcher_base> weak_t;
158 :
159 : virtual ~dispatcher_base();
160 :
161 : virtual bool get_commands(snap_string_list & commands) = 0;
162 : virtual bool dispatch(snap::snap_communicator_message & msg) = 0;
163 :
164 : private:
165 : };
166 :
167 :
168 :
169 :
170 :
171 :
172 :
173 : // forward class declaration
174 : class snap_tcp_client_permanent_message_connection_impl;
175 :
176 :
177 :
178 : // WARNING: a snap_communicator object must be allocated and held in a shared pointer (see pointer_t)
179 : #pragma GCC diagnostic push
180 : #pragma GCC diagnostic ignored "-Weffc++"
181 : #pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
182 0 : class snap_communicator
183 : : public std::enable_shared_from_this<snap_communicator>
184 : {
185 : public:
186 : typedef std::shared_ptr<snap_communicator> pointer_t;
187 :
188 : // this version defines the protocol version, it should really rarely
189 : // change if ever
190 : static int const VERSION = 1;
191 :
192 : typedef int priority_t;
193 :
194 : static priority_t const EVENT_MAX_PRIORITY = 255;
195 :
196 0 : class snap_dispatcher_support
197 : {
198 : public:
199 : virtual ~snap_dispatcher_support();
200 :
201 : void set_dispatcher(dispatcher_base::pointer_t d);
202 : dispatcher_base::pointer_t get_dispatcher() const;
203 : bool dispatch_message(snap::snap_communicator_message & msg);
204 :
205 : // new callback
206 : virtual void process_message(snap_communicator_message const & message);
207 :
208 : private:
209 : dispatcher_base::weak_t f_dispatcher = dispatcher_base::weak_t();
210 : };
211 :
212 : class snap_connection
213 : : public std::enable_shared_from_this<snap_connection>
214 : {
215 : public:
216 : typedef std::shared_ptr<snap_connection> pointer_t;
217 : typedef std::vector<pointer_t> vector_t;
218 :
219 : snap_connection();
220 :
221 : // prevent copies
222 : snap_connection(snap_connection const & connection) = delete;
223 : snap_connection & operator = (snap_connection const & connection) = delete;
224 :
225 : // virtual classes must have a virtual destructor
226 : virtual ~snap_connection();
227 :
228 : void remove_from_communicator();
229 :
230 : QString const & get_name() const;
231 : void set_name(QString const & name);
232 :
233 : virtual bool is_listener() const;
234 : virtual bool is_signal() const;
235 : virtual bool is_reader() const;
236 : virtual bool is_writer() const;
237 : virtual int get_socket() const = 0;
238 : virtual bool valid_socket() const;
239 :
240 : bool is_enabled() const;
241 : virtual void set_enable(bool enabled);
242 :
243 : int get_priority() const;
244 : void set_priority(priority_t priority);
245 : static bool compare(pointer_t const & lhs, pointer_t const & rhs);
246 :
247 : uint16_t get_event_limit() const;
248 : void set_event_limit(uint16_t event_limit);
249 : uint16_t get_processing_time_limit() const;
250 : void set_processing_time_limit(int32_t processing_time_limit);
251 :
252 : int64_t get_timeout_delay() const;
253 : void set_timeout_delay(int64_t timeout_us);
254 : void calculate_next_tick();
255 : int64_t get_timeout_date() const;
256 : void set_timeout_date(int64_t date_us);
257 : int64_t get_timeout_timestamp() const;
258 :
259 : void non_blocking() const;
260 : void keep_alive() const;
261 :
262 : bool is_done() const;
263 : void mark_done();
264 : void mark_not_done();
265 :
266 : // callbacks
267 : virtual void process_timeout();
268 : virtual void process_signal();
269 : virtual void process_read();
270 : virtual void process_write();
271 : virtual void process_empty_buffer();
272 : virtual void process_accept();
273 : virtual void process_error();
274 : virtual void process_hup();
275 : virtual void process_invalid();
276 : virtual void connection_added();
277 : virtual void connection_removed();
278 :
279 : private:
280 : friend snap_communicator;
281 :
282 : int64_t save_timeout_timestamp();
283 : int64_t get_saved_timeout_timestamp() const;
284 :
285 : QString f_name = QString();
286 : bool f_enabled = true;
287 : bool f_done = false;
288 : uint16_t f_event_limit = 5; // limit before giving other events a chance
289 : priority_t f_priority = 100;
290 : int64_t f_timeout_delay = -1; // in microseconds
291 : int64_t f_timeout_next_date = -1; // in microseconds, when we use the f_timeout_delay
292 : int64_t f_timeout_date = -1; // in microseconds
293 : int64_t f_saved_timeout_stamp = -1; // in microseconds
294 : int32_t f_processing_time_limit = 500000; // in microseconds
295 : int f_fds_position = -1;
296 : };
297 :
298 0 : class connection_with_send_message
299 : {
300 : public:
301 : virtual ~connection_with_send_message();
302 :
303 : // new callback
304 : virtual bool send_message(snap_communicator_message const & message, bool cache = false) = 0;
305 :
306 : virtual void msg_help(snap_communicator_message & message);
307 : virtual void msg_alive(snap_communicator_message & message);
308 : virtual void msg_log(snap_communicator_message & message);
309 : virtual void msg_quitting(snap_communicator_message & message);
310 : virtual void msg_ready(snap_communicator_message & message);
311 : virtual void msg_stop(snap_communicator_message & message);
312 : virtual void msg_log_unknown(snap_communicator_message & message);
313 : virtual void msg_reply_with_unknown(snap_communicator_message & message);
314 :
315 : virtual void help(snap_string_list & commands);
316 : virtual void ready(snap_communicator_message & message);
317 : virtual void stop(bool quitting);
318 : };
319 :
320 0 : class snap_timer
321 : : public snap_connection
322 : {
323 : public:
324 : // timer is implemented using the timeout value on poll().
325 : // we could have another implementation that makes use of
326 : // the timerfd_create() function (in which case we'd be
327 : // limited to a date timeout, although an interval would
328 : // work too but require a little bit of work.)
329 : //
330 : typedef std::shared_ptr<snap_timer> pointer_t;
331 :
332 : snap_timer(int64_t timeout_us);
333 :
334 : // snap_connection implementation
335 : virtual int get_socket() const override;
336 : virtual bool valid_socket() const override;
337 : };
338 :
339 : class snap_signal
340 : : public snap_connection
341 : {
342 : public:
343 : typedef std::shared_ptr<snap_signal> pointer_t;
344 :
345 : snap_signal(int posix_signal);
346 : virtual ~snap_signal() override;
347 :
348 : void close();
349 : void unblock_signal_on_destruction();
350 :
351 : // snap_connection implementation
352 : virtual bool is_signal() const override;
353 : virtual int get_socket() const override;
354 :
355 : pid_t get_child_pid() const;
356 :
357 : private:
358 : friend snap_communicator;
359 :
360 : void process();
361 :
362 : int f_signal = 0; // i.e. SIGHUP, SIGTERM...
363 : int f_socket = -1; // output of signalfd()
364 : struct signalfd_siginfo f_signal_info = signalfd_siginfo();
365 : bool f_unblock = false;
366 : };
367 :
368 : class snap_thread_done_signal
369 : : public snap_connection
370 : {
371 : public:
372 : typedef std::shared_ptr<snap_thread_done_signal> pointer_t;
373 :
374 : snap_thread_done_signal();
375 : virtual ~snap_thread_done_signal() override;
376 :
377 : // snap_connection implementation
378 : virtual bool is_reader() const override;
379 : virtual int get_socket() const override;
380 : virtual void process_read() override;
381 :
382 : void thread_done();
383 :
384 : private:
385 : int f_pipe[2] = { -1, -1 }; // pipes
386 : };
387 :
388 : class snap_inter_thread_message_connection
389 : : public snap_connection
390 : , public connection_with_send_message
391 : {
392 : public:
393 : typedef std::shared_ptr<snap_inter_thread_message_connection> pointer_t;
394 :
395 : snap_inter_thread_message_connection();
396 : virtual ~snap_inter_thread_message_connection() override;
397 :
398 : void close();
399 :
400 : // the child cannot have its own snap_communicator object, so...
401 : int poll(int timeout);
402 :
403 : // snap_connection implementation
404 : virtual bool is_reader() const override;
405 : //virtual bool is_writer() const override;
406 : virtual int get_socket() const override;
407 : virtual void process_read() override;
408 :
409 : // connection_with_send_message
410 : virtual bool send_message(snap_communicator_message const & message, bool cache = false) override;
411 :
412 : // new callback
413 : virtual void process_message_a(snap_communicator_message const & message) = 0;
414 : virtual void process_message_b(snap_communicator_message const & message) = 0;
415 :
416 : private:
417 : pid_t f_creator_id = -1;
418 :
419 : std::shared_ptr<int> f_thread_a = std::shared_ptr<int>();
420 : snap::snap_thread::snap_fifo<snap_communicator_message>
421 : f_message_a = snap::snap_thread::snap_fifo<snap_communicator_message>();
422 :
423 : std::shared_ptr<int> f_thread_b = std::shared_ptr<int>();
424 : snap::snap_thread::snap_fifo<snap_communicator_message>
425 : f_message_b = snap::snap_thread::snap_fifo<snap_communicator_message>();
426 : };
427 :
428 : class snap_pipe_connection
429 : : public snap_connection
430 : {
431 : public:
432 : typedef std::shared_ptr<snap_pipe_connection> pointer_t;
433 :
434 : snap_pipe_connection();
435 : virtual ~snap_pipe_connection() override;
436 :
437 : void close();
438 :
439 : // snap_connection implementation
440 : virtual bool is_reader() const override;
441 : virtual int get_socket() const override;
442 :
443 : // new callbacks
444 : virtual ssize_t read(void * buf, size_t count);
445 : virtual ssize_t write(void const * buf, size_t count);
446 :
447 : private:
448 : pid_t f_parent = -1; // the process that created these pipes (read/write to 0 if getpid() == f_parent, read/write to 1 if getpid() != f_parent)
449 : int f_socket[2] = { -1, -1 }; // socket pair
450 : };
451 :
452 0 : class snap_pipe_buffer_connection
453 : : public snap_pipe_connection
454 : {
455 : public:
456 : typedef std::shared_ptr<snap_pipe_buffer_connection> pointer_t;
457 :
458 : // snap::snap_communicator::snap_connection
459 : virtual bool is_writer() const override;
460 :
461 : // snap::snap_communicator::snap_pipe_connection implementation
462 : virtual ssize_t write(void const * data, size_t length) override;
463 : virtual void process_read() override;
464 : virtual void process_write() override;
465 : virtual void process_hup() override;
466 :
467 : // new callback
468 : virtual void process_line(QString const & line) = 0;
469 :
470 : private:
471 : std::string f_line = std::string(); // do NOT use QString because UTF-8 would break often... (since we may only receive part of messages)
472 : std::vector<char> f_output = std::vector<char>();
473 : size_t f_position = 0;
474 : };
475 :
476 0 : class snap_pipe_message_connection
477 : : public snap_pipe_buffer_connection
478 : , public snap_dispatcher_support
479 : , public connection_with_send_message
480 : {
481 : public:
482 : typedef std::shared_ptr<snap_pipe_message_connection> pointer_t;
483 :
484 : // connection_with_send_message
485 : virtual bool send_message(snap_communicator_message const & message, bool cache = false) override;
486 :
487 : // snap_tcp_server_client_buffer_connection implementation
488 : virtual void process_line(QString const & line) override;
489 : };
490 :
491 : class snap_file_changed
492 : : public snap_connection
493 : {
494 : public:
495 : typedef std::shared_ptr<snap_file_changed> pointer_t;
496 : typedef uint32_t event_mask_t;
497 :
498 : static event_mask_t const SNAP_FILE_CHANGED_EVENT_NO_EVENTS = 0x0000;
499 :
500 : // bits added to watch_...() functions
501 : //
502 : static event_mask_t const SNAP_FILE_CHANGED_EVENT_ATTRIBUTES = 0x0001; // chmod, chown (timestamp, link count, user/group, etc.)
503 : static event_mask_t const SNAP_FILE_CHANGED_EVENT_READ = 0x0002; // read, execve
504 : static event_mask_t const SNAP_FILE_CHANGED_EVENT_WRITE = 0x0004; // write, truncate
505 : static event_mask_t const SNAP_FILE_CHANGED_EVENT_CREATED = 0x0008; // open & O_CREAT, rename, mkdir, link, symlink, bind
506 : static event_mask_t const SNAP_FILE_CHANGED_EVENT_DELETED = 0x0010; // unlink, rename
507 : static event_mask_t const SNAP_FILE_CHANGED_EVENT_ACCESS = 0x0020; // open, close
508 :
509 : static event_mask_t const SNAP_FILE_CHANGED_EVENT_IO = SNAP_FILE_CHANGED_EVENT_READ
510 : | SNAP_FILE_CHANGED_EVENT_WRITE;
511 :
512 : static event_mask_t const SNAP_FILE_CHANGED_EVENT_ALL = SNAP_FILE_CHANGED_EVENT_ATTRIBUTES
513 : | SNAP_FILE_CHANGED_EVENT_IO
514 : | SNAP_FILE_CHANGED_EVENT_CREATED
515 : | SNAP_FILE_CHANGED_EVENT_DELETED
516 : | SNAP_FILE_CHANGED_EVENT_ACCESS;
517 :
518 : // flags added in event_t objects
519 : //
520 : static event_mask_t const SNAP_FILE_CHANGED_EVENT_DIRECTORY = 0x1000; // object is a directory
521 : static event_mask_t const SNAP_FILE_CHANGED_EVENT_GONE = 0x2000; // removed
522 : static event_mask_t const SNAP_FILE_CHANGED_EVENT_UNMOUNTED = 0x4000; // unmounted
523 :
524 0 : class event_t
525 : {
526 : public:
527 : event_t(std::string const & watched_path
528 : , event_mask_t events
529 : , std::string const & filename);
530 :
531 : std::string const & get_watched_path() const;
532 : event_mask_t get_events() const;
533 : std::string const & get_filename() const;
534 :
535 : bool operator < (event_t const & rhs) const;
536 :
537 : private:
538 : std::string f_watched_path = std::string();
539 : event_mask_t f_events = 0;
540 : std::string f_filename = std::string();
541 : };
542 :
543 : snap_file_changed();
544 : virtual ~snap_file_changed() override;
545 :
546 : void watch_file(std::string const & watched_path, event_mask_t const events);
547 : void watch_symlink(std::string const & watched_path, event_mask_t const events);
548 : void watch_directory(std::string const & watched_path, event_mask_t const events);
549 :
550 : void stop_watch(std::string const & watched_path);
551 :
552 : // snap_connection implementation
553 : virtual bool is_reader() const override;
554 : virtual int get_socket() const override;
555 : virtual void set_enable(bool enabled);
556 : virtual void process_read() override;
557 :
558 : // new callback
559 : virtual void process_event(event_t const & watch_event) = 0;
560 :
561 : private:
562 : // TODO: RAII would be great with an impl and a counter...
563 : // (i.e. we make copies at the moment.)
564 0 : struct watch_t
565 : {
566 : typedef std::map<int, watch_t> map_t;
567 :
568 : watch_t();
569 : watch_t(std::string const & watched_path, event_mask_t events, uint32_t add_flags);
570 :
571 : void add_watch(int inotify);
572 : void merge_watch(int inotify, event_mask_t const events);
573 : void remove_watch(int inotify);
574 :
575 : std::string f_watched_path = std::string();
576 : event_mask_t f_events = SNAP_FILE_CHANGED_EVENT_NO_EVENTS;
577 : uint32_t f_mask = 0;
578 : int f_watch = -1;
579 : };
580 :
581 : bool merge_watch(std::string const & watched_path, event_mask_t const events);
582 : static uint32_t events_to_mask(event_mask_t const events);
583 : static event_mask_t mask_to_events(uint32_t const mask);
584 :
585 : int f_inotify = -1;
586 : watch_t::map_t f_watches = watch_t::map_t();
587 : };
588 :
589 0 : class snap_fd_connection
590 : : public snap_connection
591 : {
592 : public:
593 : typedef std::shared_ptr<snap_fd_connection> pointer_t;
594 :
595 : enum class mode_t
596 : {
597 : FD_MODE_READ,
598 : FD_MODE_WRITE,
599 : FD_MODE_RW
600 : };
601 :
602 : snap_fd_connection(int fd, mode_t mode);
603 :
604 : void close();
605 : void mark_closed();
606 :
607 : // snap_connection implementation
608 : virtual bool is_reader() const override;
609 : virtual bool is_writer() const override;
610 : virtual int get_socket() const override;
611 :
612 : // new callbacks
613 : virtual ssize_t read(void * buf, size_t count);
614 : virtual ssize_t write(void const * buf, size_t count);
615 :
616 : private:
617 : int f_fd = -1;
618 : mode_t f_mode = mode_t::FD_MODE_RW;
619 : };
620 :
621 0 : class snap_fd_buffer_connection
622 : : public snap_fd_connection
623 : {
624 : public:
625 : typedef std::shared_ptr<snap_fd_buffer_connection> pointer_t;
626 :
627 : snap_fd_buffer_connection(int fd, mode_t mode);
628 :
629 : bool has_input() const;
630 : bool has_output() const;
631 : virtual bool is_writer() const override;
632 :
633 : // snap_fd_connection implementation
634 : virtual ssize_t write(void const * data, size_t const length) override;
635 :
636 : // snap_connection implementation
637 : virtual void process_read() override;
638 : virtual void process_write() override;
639 : virtual void process_hup() override;
640 :
641 : // new callback
642 : virtual void process_line(QString const & line) = 0;
643 :
644 : private:
645 : std::string f_line = std::string(); // input -- do NOT use QString because UTF-8 would break often... (since we may only receive part of messages)
646 : std::vector<char> f_output = std::vector<char>();
647 : size_t f_position = 0;
648 : };
649 :
650 0 : class snap_tcp_client_connection
651 : : public snap_connection
652 : , public tcp_client_server::bio_client
653 : {
654 : public:
655 : typedef std::shared_ptr<snap_tcp_client_connection> pointer_t;
656 :
657 : snap_tcp_client_connection(std::string const & addr, int port, mode_t mode = mode_t::MODE_PLAIN);
658 :
659 : QString const & get_remote_address() const;
660 :
661 : // snap_connection implementation
662 : virtual bool is_reader() const override;
663 : virtual int get_socket() const override;
664 :
665 : // new callbacks
666 : virtual ssize_t read(void * buf, size_t count);
667 : virtual ssize_t write(void const * buf, size_t count);
668 :
669 : private:
670 : QString const f_remote_address = QString();
671 : };
672 :
673 0 : class snap_tcp_server_connection
674 : : public snap_connection
675 : , public tcp_client_server::bio_server
676 : {
677 : public:
678 : typedef std::shared_ptr<snap_tcp_server_connection> pointer_t;
679 :
680 : snap_tcp_server_connection(std::string const & addr, int port, std::string const & certificate, std::string const & private_key, mode_t mode = mode_t::MODE_PLAIN, int max_connections = -1, bool reuse_addr = false);
681 :
682 : // snap_connection implementation
683 : virtual bool is_listener() const override;
684 : virtual int get_socket() const override;
685 : };
686 :
687 : class snap_tcp_server_client_connection
688 : : public snap_connection
689 : //, public tcp_client_server::tcp_client -- this will not work without some serious re-engineering of the tcp_client class
690 : {
691 : public:
692 : typedef std::shared_ptr<snap_tcp_server_client_connection> pointer_t;
693 :
694 : snap_tcp_server_client_connection(tcp_client_server::bio_client::pointer_t client);
695 : virtual ~snap_tcp_server_client_connection() override;
696 :
697 : void close();
698 : size_t get_client_address(struct sockaddr_storage & address) const;
699 : std::string get_client_addr() const;
700 : int get_client_port() const;
701 : std::string get_client_addr_port() const;
702 :
703 : // snap_connection implementation
704 : virtual bool is_reader() const override;
705 : virtual int get_socket() const override;
706 :
707 : // new callbacks
708 : virtual ssize_t read(void * buf, size_t count);
709 : virtual ssize_t write(void const * buf, size_t count);
710 :
711 : private:
712 : bool define_address();
713 :
714 : tcp_client_server::bio_client::pointer_t
715 : f_client = tcp_client_server::bio_client::pointer_t();
716 : struct sockaddr_storage f_address = sockaddr_storage();
717 : socklen_t f_length = 0;
718 : };
719 :
720 0 : class snap_tcp_server_client_buffer_connection
721 : : public snap_tcp_server_client_connection
722 : {
723 : public:
724 : typedef std::shared_ptr<snap_tcp_server_client_buffer_connection> pointer_t;
725 :
726 : snap_tcp_server_client_buffer_connection(tcp_client_server::bio_client::pointer_t client);
727 :
728 : bool has_input() const;
729 : bool has_output() const;
730 :
731 : // snap::snap_communicator::snap_connection
732 : virtual bool is_writer() const override;
733 :
734 : // snap::snap_communicator::snap_tcp_server_client_connection implementation
735 : virtual ssize_t write(void const * data, size_t const length) override;
736 : virtual void process_read() override;
737 : virtual void process_write() override;
738 : virtual void process_hup() override;
739 :
740 : // new callback
741 : virtual void process_line(QString const & line) = 0;
742 :
743 : private:
744 : std::string f_line = std::string(); // input -- do NOT use QString because UTF-8 would break often... (since we may only receive part of messages)
745 : std::vector<char> f_output = std::vector<char>();
746 : size_t f_position = 0;
747 : };
748 :
749 0 : class snap_tcp_server_client_message_connection
750 : : public snap_tcp_server_client_buffer_connection
751 : , public snap_dispatcher_support
752 : , public connection_with_send_message
753 : {
754 : public:
755 : typedef std::shared_ptr<snap_tcp_server_client_message_connection> pointer_t;
756 :
757 : snap_tcp_server_client_message_connection(tcp_client_server::bio_client::pointer_t client);
758 :
759 : QString const & get_remote_address() const;
760 :
761 : // connection_with_send_message
762 : virtual bool send_message(snap_communicator_message const & message, bool cache = false) override;
763 :
764 : // snap_tcp_server_client_buffer_connection implementation
765 : virtual void process_line(QString const & line) override;
766 :
767 : private:
768 : QString f_remote_address = QString();
769 : };
770 :
771 0 : class snap_tcp_client_buffer_connection
772 : : public snap_tcp_client_connection
773 : {
774 : public:
775 : typedef std::shared_ptr<snap_tcp_client_buffer_connection> pointer_t;
776 :
777 : snap_tcp_client_buffer_connection(std::string const & addr, int port, mode_t const mode = mode_t::MODE_PLAIN, bool const blocking = false);
778 :
779 : bool has_input() const;
780 : bool has_output() const;
781 :
782 : // snap::snap_communicator::snap_tcp_client_connection implementation
783 : virtual ssize_t write(void const * data, size_t length) override;
784 : virtual bool is_writer() const override;
785 : virtual void process_read() override;
786 : virtual void process_write() override;
787 : virtual void process_hup() override;
788 :
789 : // new callback
790 : virtual void process_line(QString const & line) = 0;
791 :
792 : private:
793 : std::string f_line = std::string(); // input -- do NOT use QString because UTF-8 would break often... (since we may only receive part of messages)
794 : std::vector<char> f_output = std::vector<char>();
795 : size_t f_position = 0;
796 : };
797 :
798 0 : class snap_tcp_client_message_connection
799 : : public snap_tcp_client_buffer_connection
800 : , public snap_dispatcher_support
801 : , public connection_with_send_message
802 : {
803 : public:
804 : typedef std::shared_ptr<snap_tcp_client_message_connection> pointer_t;
805 :
806 : snap_tcp_client_message_connection(std::string const & addr, int port, mode_t const mode = mode_t::MODE_PLAIN, bool const blocking = false);
807 :
808 : // connection_with_send_message
809 : virtual bool send_message(snap_communicator_message const & message, bool cache = false) override;
810 :
811 : // snap_tcp_client_reader_connection implementation
812 : virtual void process_line(QString const & line) override;
813 : };
814 :
815 : class snap_tcp_client_permanent_message_connection
816 : : public snap_timer
817 : , public snap_dispatcher_support
818 : , public connection_with_send_message
819 : {
820 : public:
821 : typedef std::shared_ptr<snap_tcp_client_permanent_message_connection> pointer_t;
822 :
823 : static int64_t const DEFAULT_PAUSE_BEFORE_RECONNECTING = 60LL * 1000000LL; // 1 minute
824 :
825 : snap_tcp_client_permanent_message_connection(std::string const & address, int port, tcp_client_server::bio_client::mode_t mode = tcp_client_server::bio_client::mode_t::MODE_PLAIN, int64_t const pause = DEFAULT_PAUSE_BEFORE_RECONNECTING, bool const use_thread = true);
826 : virtual ~snap_tcp_client_permanent_message_connection() override;
827 :
828 : bool is_connected() const;
829 : void disconnect();
830 : void mark_done();
831 : void mark_done(bool messenger);
832 : size_t get_client_address(struct sockaddr_storage & address) const;
833 : std::string get_client_addr() const;
834 :
835 : // connection_with_send_message
836 : virtual bool send_message(snap_communicator_message const & message, bool cache = false) override;
837 :
838 : // snap_connection implementation
839 : virtual void process_timeout() override;
840 : virtual void process_error() override;
841 : virtual void process_hup() override;
842 : virtual void process_invalid() override;
843 : virtual void connection_removed() override;
844 :
845 : // new callbacks
846 : virtual void process_connection_failed(std::string const & error_message);
847 : virtual void process_connected();
848 :
849 : private:
850 : std::shared_ptr<snap_tcp_client_permanent_message_connection_impl>
851 : f_impl = std::shared_ptr<snap_tcp_client_permanent_message_connection_impl>();
852 : int64_t f_pause = 0;
853 : bool const f_use_thread = true;
854 : };
855 :
856 0 : class snap_udp_server_connection
857 : : public snap_connection
858 : , public udp_client_server::udp_server
859 : {
860 : public:
861 : typedef std::shared_ptr<snap_udp_server_connection> pointer_t;
862 :
863 : snap_udp_server_connection(std::string const & addr, int port);
864 :
865 : // snap_connection implementation
866 : virtual bool is_reader() const override;
867 : virtual int get_socket() const override;
868 :
869 : void set_secret_code(std::string const & secret_code);
870 : std::string const & get_secret_code() const;
871 :
872 : private:
873 : std::string f_secret_code = std::string();
874 : };
875 :
876 0 : class snap_udp_server_message_connection
877 : : public snap_udp_server_connection
878 : , public snap_dispatcher_support
879 : {
880 : public:
881 : typedef std::shared_ptr<snap_udp_server_message_connection> pointer_t;
882 :
883 : static size_t const DATAGRAM_MAX_SIZE = 1024;
884 :
885 : snap_udp_server_message_connection(std::string const & addr, int port);
886 :
887 : static bool send_message(std::string const & addr
888 : , int port
889 : , snap_communicator_message const & message
890 : , std::string const & secret_code = std::string());
891 :
892 : // snap_connection implementation
893 : virtual void process_read() override;
894 :
895 : private:
896 : };
897 :
898 0 : class snap_tcp_blocking_client_message_connection
899 : : public snap_tcp_client_message_connection
900 : {
901 : public:
902 : snap_tcp_blocking_client_message_connection(std::string const & addr, int port, mode_t mode = mode_t::MODE_PLAIN);
903 :
904 : void run();
905 : void peek();
906 :
907 : // connection_with_send_message
908 : virtual bool send_message(snap_communicator_message const & message, bool cache = false) override;
909 :
910 : // snap_connection callback
911 : virtual void process_error() override;
912 :
913 : private:
914 : std::string f_line = std::string();
915 : };
916 :
917 : static pointer_t instance();
918 :
919 : // prevent copies
920 : snap_communicator(snap_communicator const & communicator) = delete;
921 : snap_communicator & operator = (snap_communicator const & communicator) = delete;
922 :
923 : snap_connection::vector_t const & get_connections() const;
924 : bool add_connection(snap_connection::pointer_t connection);
925 : bool remove_connection(snap_connection::pointer_t connection);
926 : virtual bool run();
927 :
928 : static int64_t get_current_date();
929 :
930 : private:
931 : snap_communicator();
932 :
933 : snap_connection::vector_t f_connections = snap_connection::vector_t();
934 : bool f_force_sort = true;
935 : };
936 : #pragma GCC diagnostic pop
937 :
938 :
939 : } // namespace snap
940 : // vim: ts=4 sw=4 et
|