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