Line data Source code
1 : // Copyright (c) 2012-2019 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
17 : // along with this program; if not, write to the Free Software
18 : // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 :
20 : /** \file
21 : * \brief Implementation of the Snap Communicator class.
22 : *
23 : * This class wraps the C poll() interface in a C++ object with many types
24 : * of objects:
25 : *
26 : * \li Server Connections; for software that want to offer a port to
27 : * which clients can connect to; the server will call accept()
28 : * once a new client connection is ready; this results in a
29 : * Server/Client connection object
30 : * \li Client Connections; for software that want to connect to
31 : * a server; these expect the IP address and port to connect to
32 : * \li Server/Client Connections; for the server when it accepts a new
33 : * connection; in this case the server gets a socket from accept()
34 : * and creates one of these objects to handle the connection
35 : *
36 : * Using the poll() function is the easiest and allows us to listen
37 : * on pretty much any number of sockets (on my server it is limited
38 : * at 16,768 and frankly over 1,000 we probably will start to have
39 : * real slowness issues on small VPN servers.)
40 : */
41 :
42 :
43 : // self
44 : //
45 : #include "eventdispatcher/tcp_client_message_connection.h"
46 :
47 :
48 : // snaplogger lib
49 : //
50 : #include <snaplogger/message.h>
51 :
52 :
53 : // snapdev lib
54 : //
55 : #include <snapdev/not_used.h>
56 :
57 :
58 : // last include
59 : //
60 : #include <snapdev/poison.h>
61 :
62 :
63 :
64 : namespace ed
65 : {
66 :
67 :
68 :
69 : /** \brief Initializes a client to read messages from a socket.
70 : *
71 : * This implementation creates a message in/out client.
72 : * This is the most useful client in our Snap! Communicator
73 : * as it directly sends and receives messages.
74 : *
75 : * \param[in] addr The address to connect to.
76 : * \param[in] port The port to connect to.
77 : * \param[in] mode Use this mode to connect as (PLAIN, ALWAYS_SECURE or SECURE).
78 : * \param[in] blocking Whether to keep the socket blocking or make it
79 : * non-blocking.
80 : */
81 0 : tcp_client_message_connection::tcp_client_message_connection(
82 : std::string const & addr
83 : , int const port
84 : , mode_t const mode
85 : , bool const blocking)
86 0 : : tcp_client_buffer_connection(addr, port, mode, blocking)
87 : {
88 0 : }
89 :
90 :
91 : /** \brief Process a line (string) just received.
92 : *
93 : * The function parses the line as a message (snap_communicator_message)
94 : * and then calls the process_message() function if the line was valid.
95 : *
96 : * \param[in] line The line of text that was just read.
97 : */
98 0 : void tcp_client_message_connection::process_line(std::string const & line)
99 : {
100 0 : if(line.empty())
101 : {
102 0 : return;
103 : }
104 :
105 0 : message msg;
106 0 : if(msg.from_message(line))
107 : {
108 0 : dispatch_message(msg);
109 : }
110 : else
111 : {
112 : // TODO: what to do here? This could be that the version changed
113 : // and the messages are not compatible anymore.
114 : //
115 : SNAP_LOG_ERROR
116 0 : << "snap_communicator::snap_tcp_client_message_connection::process_line() was asked to process an invalid message ("
117 0 : << line
118 0 : << ")";
119 : }
120 : }
121 :
122 :
123 : /** \brief Send a message.
124 : *
125 : * This function sends a message to the client on the other side
126 : * of this connection.
127 : *
128 : * \exception snap_communicator_runtime_error
129 : * This function throws this exception if the write() to the pipe
130 : * fails to write the entire message. This should only happen if
131 : * the pipe gets severed.
132 : *
133 : * \param[in] message The message to be sent.
134 : * \param[in] cache Whether to cache the message if there is no connection.
135 : *
136 : * \return Always true, although if an error occurs the function throws.
137 : */
138 0 : bool tcp_client_message_connection::send_message(message const & msg, bool cache)
139 : {
140 0 : snap::NOTUSED(cache);
141 :
142 : // transform the message to a string and write to the socket
143 : // the writing is asynchronous so the message is saved in a cache
144 : // and transferred only later when the run() loop is hit again
145 : //
146 0 : std::string buf(msg.to_message());
147 0 : buf += '\n';
148 0 : return write(buf.c_str(), buf.length()) == static_cast<ssize_t>(buf.length());
149 : }
150 :
151 :
152 :
153 6 : } // namespace ed
154 : // vim: ts=4 sw=4 et
|