Line data Source code
1 :
2 : /* Copyright (c) 2005-2017, Stefan Eilemann <eile@equalizergraphics.com>
3 : * Daniel Nachbaur <danielnachbaur@gmail.com>
4 : *
5 : * This file is part of Collage <https://github.com/Eyescale/Collage>
6 : *
7 : * This library is free software; you can redistribute it and/or modify it under
8 : * the terms of the GNU Lesser General Public License version 2.1 as published
9 : * by the Free Software Foundation.
10 : *
11 : * This library is distributed in the hope that it will be useful, but WITHOUT
12 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14 : * details.
15 : *
16 : * You should have received a copy of the GNU Lesser General Public License
17 : * along with this library; if not, write to the Free Software Foundation, Inc.,
18 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 : */
20 :
21 : #ifndef CO_CONNECTION_H
22 : #define CO_CONNECTION_H
23 :
24 : #include <co/api.h>
25 : #include <co/types.h>
26 :
27 : #include <boost/noncopyable.hpp> // base class
28 : #include <lunchbox/bitOperation.h> // used inline
29 : #include <lunchbox/referenced.h> // base class
30 :
31 : #include <string.h>
32 : #include <sys/types.h>
33 : #include <vector>
34 :
35 : namespace co
36 : {
37 : namespace detail
38 : {
39 : class Connection;
40 : }
41 :
42 : /**
43 : * An interface definition for communication between hosts.
44 : *
45 : * Connections are stream-oriented communication lines. The parameters of a
46 : * Connection are described in a ConnectionDescription, which is used in
47 : * create(), listen() and connect(). A Connection has a Connection::State, which
48 : * changes when calling listen(), connect() or close(), or whenever the
49 : * underlying connection is closed by the operating system.
50 : *
51 : * The Connection class defines the interface for connections, various derived
52 : * classes implement it for the low-level communication protocols, e.g.,
53 : * SocketConnection for TCP/IP or RSPConnection for UDP-based reliable
54 : * multicast. An implementation may not implement all the functionality defined
55 : * in this interface.
56 : *
57 : * The Connection is used reference-counted throughout the Collage API.
58 : */
59 : class Connection : public lunchbox::Referenced, public boost::noncopyable
60 : {
61 : public:
62 : enum State //! The current state of the Connection @version 1.0
63 : {
64 : STATE_CLOSED, //!< Closed, initial state
65 : STATE_CONNECTING, //!< A connect() or listen() is in progress
66 : STATE_CONNECTED, //!< The connection has been connected and is open
67 : STATE_LISTENING, //!< The connection is listening for connects
68 : STATE_CLOSING //!< A close() is in progress
69 : };
70 :
71 : /**
72 : * Create a new connection.
73 : *
74 : * This factory method creates a new concrete connection for the requested
75 : * type. The description is set on the created Connection.
76 : *
77 : * @param desc the connection parameters.
78 : * @return the connection.
79 : * @version 1.0
80 : */
81 : CO_API static ConnectionPtr create(ConnectionDescriptionPtr desc);
82 :
83 : /** @name Data Access */
84 : //@{
85 : /** @return the State of this connection. @version 1.0 */
86 : CO_API State getState() const;
87 :
88 : /** @return true if the connection is closed. @version 1.0 */
89 1127 : bool isClosed() const { return getState() == STATE_CLOSED; }
90 : /** @return true if the connection is about to close. @version 1.0 */
91 0 : bool isClosing() const { return getState() == STATE_CLOSING; }
92 : /** @return true if the connection is connected. @version 1.0 */
93 2970217 : bool isConnected() const { return getState() == STATE_CONNECTED; }
94 : /** @return true if the connection is listening. @version 1.0 */
95 306929 : bool isListening() const { return getState() == STATE_LISTENING; }
96 : /** @return true if this is a multicast connection. @version 1.0 */
97 : CO_API bool isMulticast() const;
98 :
99 : /** @return the description for this connection. @version 1.0 */
100 : CO_API ConstConnectionDescriptionPtr getDescription() const;
101 :
102 : /** @internal */
103 : bool operator==(const Connection& rhs) const;
104 : //@}
105 :
106 : /** @name Connection State Changes */
107 : //@{
108 : /**
109 : * Connect to the remote peer.
110 : *
111 : * The ConnectionDescription of this connection is used to identify the
112 : * peer's parameters.
113 : *
114 : * @return true if the connection was successfully connected, false
115 : * if not.
116 : * @version 1.0
117 : */
118 0 : virtual bool connect() { return false; }
119 : /**
120 : * Put the connection into the listening state.
121 : *
122 : * The ConnectionDescription of this connection is used to identify the
123 : * listening parameters.
124 : *
125 : * @return true if the connection is listening for new incoming
126 : * connections, false if not.
127 : * @version 1.0
128 : */
129 0 : virtual bool listen() { return false; }
130 : /** Close a connected or listening connection. @version 1.0 */
131 0 : virtual void close() {}
132 : //@}
133 :
134 : /** @internal @name Listener Interface */
135 : //@{
136 : /** @internal Add a listener for connection state changes. */
137 : void addListener(ConnectionListener* listener);
138 :
139 : /** @internal Remove a listener for connection state changes. */
140 : void removeListener(ConnectionListener* listener);
141 : //@}
142 :
143 : /** @name Asynchronous accept */
144 : //@{
145 : /**
146 : * Start an accept operation.
147 : *
148 : * This method returns immediately. The Notifier will signal a new
149 : * connection request, upon which acceptSync() should be used to finish the
150 : * accept operation. Only one accept operation might be outstanding, that
151 : * is, acceptSync() has to be called before the next acceptNB().
152 : *
153 : * @sa acceptSync()
154 : * @version 1.0
155 : */
156 0 : virtual void acceptNB() { LBUNIMPLEMENTED; }
157 : /**
158 : * Complete an accept operation.
159 : *
160 : * @return the new connection, 0 on error.
161 : * @version 1.0
162 : */
163 0 : virtual ConnectionPtr acceptSync()
164 : {
165 0 : LBUNIMPLEMENTED;
166 0 : return 0;
167 : }
168 : //@}
169 :
170 : /** @name Asynchronous read */
171 : //@{
172 : /**
173 : * Start a read operation on the connection.
174 : *
175 : * This function returns immediately. The Notifier will signal data
176 : * availability, upon which recvSync() should be used to finish the
177 : * operation. The data will be appended to the given buffer. Only one read
178 : * operation might be outstanding, that is, readSync() has to be called
179 : * before the next readNB().
180 : *
181 : * @param buffer the buffer receiving the data.
182 : * @param bytes the number of bytes to read.
183 : * @sa recvSync()
184 : * @version 1.0
185 : */
186 : CO_API void recvNB(BufferPtr buffer, const uint64_t bytes);
187 :
188 : /**
189 : * Finish reading data from the connection.
190 : *
191 : * This function may block even if data availability was signaled, i.e.,
192 : * when only a part of the data requested has been received. The received
193 : * data is appended to the buffer, at most the number of bytes given to
194 : * recvNB(). This method uses readNB() and readSync() to fill a buffer,
195 : * potentially by using multiple reads.
196 : *
197 : * @param buffer return value, the buffer passed to recvNB().
198 : * @param block internal workaround parameter, do not use unless you
199 : * know exactly why.
200 : * @return true if all requested data has been read, false otherwise.
201 : * @version 1.0
202 : */
203 : CO_API bool recvSync(BufferPtr& buffer, const bool block = true);
204 :
205 : BufferPtr resetRecvData(); //!< @internal
206 : //@}
207 :
208 : /** @name Synchronous write to the connection */
209 : //@{
210 : /**
211 : * Send data using the connection.
212 : *
213 : * A send may be performed using multiple write() operations. For
214 : * thread-safe sending from multiple threads it is therefore crucial to
215 : * protect the send() operation internally. If the connection is not already
216 : * locked externally, it will use an internal mutex.
217 : *
218 : * @param buffer the buffer containing the message.
219 : * @param bytes the number of bytes to send.
220 : * @param isLocked true if the connection is locked externally.
221 : * @return true if all data has been read, false if not.
222 : * @sa lockSend(), unlockSend()
223 : * @version 1.0
224 : */
225 : CO_API bool send(const void* buffer, const uint64_t bytes,
226 : const bool isLocked = false);
227 :
228 : /** Lock the connection, no other thread can send data. @version 1.0 */
229 : CO_API void lockSend() const;
230 :
231 : /** Unlock the connection. @version 1.0 */
232 : CO_API void unlockSend() const;
233 :
234 : /** @internal Finish all pending send operations. */
235 0 : virtual void finish() {}
236 : //@}
237 :
238 : /**
239 : * The Notifier used by the ConnectionSet to detect readiness of a
240 : * Connection.
241 : */
242 : #ifdef _WIN32
243 : typedef void* Notifier;
244 : #else
245 : typedef int Notifier;
246 : #endif
247 : /** @return the notifier signaling events. @version 1.0 */
248 : virtual Notifier getNotifier() const = 0;
249 :
250 : protected:
251 : /** Construct a new connection. */
252 : Connection();
253 :
254 : /** Destruct this connection. */
255 : virtual ~Connection();
256 :
257 : /** @name Low-level IO methods */
258 : //@{
259 : enum ReadStatus //!< error codes for readSync()
260 : {
261 : READ_TIMEOUT = -2,
262 : READ_ERROR = -1
263 : // >= 0: nBytes read
264 : };
265 :
266 : /**
267 : * Start a read operation on the connection.
268 : *
269 : * This method is the low-level counterpart used by recvNB(), implemented by
270 : * the concrete connection.
271 : *
272 : * This function returns immediately. The operation's Notifier will
273 : * signal data availability, upon which readSync() is used to finish the
274 : * operation.
275 : *
276 : * @param buffer the buffer receiving the data.
277 : * @param bytes the number of bytes to read.
278 : * @sa readSync()
279 : */
280 : virtual void readNB(void* buffer, const uint64_t bytes) = 0;
281 :
282 : /**
283 : * Finish reading data from the connection.
284 : *
285 : * This method is the low-level counterpart used by recvSync(), implemented
286 : * by the concrete connection. It may return with a partial read.
287 : *
288 : * @param buffer the buffer receiving the data.
289 : * @param bytes the number of bytes to read.
290 : * @param block internal WAR parameter, ignore it in the implementation
291 : * unless you know exactly why not.
292 : * @return the number of bytes read, or -1 upon error.
293 : */
294 : virtual int64_t readSync(void* buffer, const uint64_t bytes,
295 : const bool block) = 0;
296 :
297 : /**
298 : * Write data to the connection.
299 : *
300 : * This method is the low-level counterpart used by send(), implemented by
301 : * the concrete connection. It may return with a partial write.
302 : *
303 : * @param buffer the buffer containing the message.
304 : * @param bytes the number of bytes to write.
305 : * @return the number of bytes written, or -1 upon error.
306 : */
307 : virtual int64_t write(const void* buffer, const uint64_t bytes) = 0;
308 : //@}
309 :
310 : /** @internal @name State Changes */
311 : //@{
312 : /** @internal Set the connection parameter description. */
313 : CO_API void _setDescription(ConnectionDescriptionPtr description);
314 :
315 : CO_API void _setState(const State state); //!< @internal
316 :
317 : /** @return the description for this connection. */
318 : CO_API ConnectionDescriptionPtr _getDescription();
319 : //@}
320 :
321 : private:
322 : detail::Connection* const _impl;
323 : };
324 :
325 : CO_API std::ostream& operator<<(std::ostream&, const Connection&);
326 : }
327 :
328 : #endif // CO_CONNECTION_H
|