2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
8 As a special exception, if other files instantiate templates or use macros
9 or inline functions from this file, or you compile this file and link it
10 with other works to produce a work based on this file, this file
11 does not by itself cause the resulting work to be covered
12 by the GNU General Public License.
14 However the source code for this file must still be made available
15 in accordance with section (3) of the GNU General Public License.
17 This exception does not invalidate any other reasons why a work based
18 on this file might be covered by the GNU General Public License.
22 * @brief simple basic IO handling.
24 * @copyright © Copyright 2007-2008 by Intra2net AG
26 * Deals with POSIX file descriptors; provides an additional abstraction
27 * level above select() or poll() interface.
28 * Also provides basic functionality for dealing with timer events.
31 #ifndef __ASYNC_IO_HPP__
32 #define __ASYNC_IO_HPP__
38 #include <asyncio_config.hpp>
40 #include <asyncio_utils.hpp>
42 #include <boost/signal.hpp>
43 #include <boost/shared_ptr.hpp>
51 using Utils::MilliTime;
54 * forward declarations
57 class IOImplementation;
60 * end of forward declarations
65 * direction for io operations.
77 Direction( _Direction direction = unspecified) : m_direction(direction) {}
79 operator _Direction () const { return m_direction; }
80 }; // eo struct IODirection;
85 * base class for time based events (timer events).
87 * consists basically of a point in time (when the event should be executed) and a method
88 * which will be called when the given time is reached (or passed).
97 bool active() const { return m_active; }
99 MilliTime getWhenTime() const {return m_when;}
100 MilliTime getRealWhenTime() const;
104 void setWhenTime(long sec, long msec=0);
105 void setWhenTime(const MilliTime& mt);
107 void setDeltaWhenTime(long sec, long msec=0);
108 void setDeltaWhenTime(const MilliTime& mt);
110 void activate(bool _active= true);
111 void deactivate() { activate(false); }
113 virtual void execute();
116 /// @a true when the event is active.
118 /// point in time when the event should be executed
120 /// mark from backend cycle that the event has to be executed.
122 }; // eo class TimerBase
127 * base class for filter classes.
129 * filter objects can be "plugged" into IO objects for manipulating the data streams.
130 * (for example: one could make a filter which handles the telnet protocol and plug it into a
133 * @note filter object can be used only by one io object.
136 : virtual public Utils::SharedBase
138 friend class IOImplementation;
140 typedef boost::shared_ptr< FilterBase > PtrType;
143 virtual ~FilterBase() { m_io = NULL; };
147 virtual std::string filterIncomingData(const std::string& data)= 0;
148 virtual std::string filterOutgoingData(const std::string& data)= 0;
150 virtual void endOfIncomingData();
151 virtual void reset();
155 void injectIncomingData(const std::string& data);
156 void injectOutgoingData(const std::string& data);
159 /// pointer to the io object which uses this filter:
160 IOImplementation *m_io;
161 }; // eo class FilterBase
163 typedef FilterBase::PtrType FilterBasePtr;
167 * identity filter; does nothing with the data (in other words: it's useless ;-) ).
169 class FilterIdentity : public FilterBase
172 virtual std::string filterIncomingData(const std::string& data) { return data; }
173 virtual std::string filterOutgoingData(const std::string& data) { return data; }
174 }; // eo class FilterIdentity
178 * @brief null filter; deletes everything it receives.
180 * usefull when output from a subprocess (like stderr) should be ignored...
182 class FilterNull : public FilterBase
185 virtual std::string filterIncomingData(const std::string& data) { return std::string(); }
186 virtual std::string filterOutgoingData(const std::string& data) { return std::string(); }
191 * the base class of the IO classes.
193 * provides the functionality to read from a file descriptor and write to a file descriptor (which can be
194 * identical (like for socket io), but also can be different (like pipes from/to a process)).
195 * The data stream can be filtered through plugged filter objects which are building a filter chain.
196 * Incoming data is filtered forward through the chain; outgoing data is filtered backward through the chain.
197 * (So the first filter is the one which modifies the data closest to the connections).
199 * @note the functionality is provided in conjunction with the @a Backend class which handles parts of
202 * @note this is a base class; it provides most "interesting" functionality in the protected section only.
203 * This way, derived classes can decide which of that functionality they want to export in their own public
204 * interfaces and which to keep hidden.
206 class IOImplementation
207 : public boost::signals::trackable
208 , virtual public Utils::SharedBase
210 friend class Backend;
211 friend class FilterBase;
215 typedef std::list< FilterBasePtr > FilterChain;
217 typedef boost::signal< void() > SignalType;
219 typedef boost::shared_ptr< IOImplementation > PtrType;
222 IOImplementation(int read_fd=-1, int write_fd=-1);
223 virtual ~IOImplementation(); //lint !e1509 // boost::signals::trackable is not virtual
225 virtual void close(Direction direction = Direction::both);
227 virtual bool wantRead();
228 virtual bool wantWrite();
230 virtual bool opened() const;
231 virtual bool eof() const;
232 virtual bool writable() const;
233 virtual bool empty() const;
237 void addFilter(FilterBasePtr filter);
238 void removeFilter(FilterBasePtr);
241 void lowSend(const std::string& data);
243 std::string::size_type getOutputBufferSize() const { return m_output_buffer.size(); }
245 void setWriteFd(int fd);
246 void setReadFd(int fd);
248 inline int readFd() const
253 inline int writeFd() const
258 inline bool isMarkedForReading() const { return m_marked_for_reading; }
259 inline bool isMarkedForWriting() const { return m_marked_for_writing; }
263 virtual void doRead();
264 virtual void doWrite();
266 void resetReadMark() { m_marked_for_reading= false; }
267 void resetWriteMark() { m_marked_for_writing= false; }
269 void injectIncomingData(FilterBasePtr from_filter, const std::string& _data);
270 void injectOutgoingData(FilterBasePtr from_filter, const std::string& _data);
273 /// last error number
275 /// the input buffer (i.e. the data read from @a m_read_fd)
276 std::string m_input_buffer;
278 /// the chain of filter which are applied to the data received are the data which should be send.
279 FilterChain m_filter_chain;
281 /// signal which is fired when end of file is detected
282 SignalType m_signal_eof;
283 /// signal which is fired when write is no longer possible
284 SignalType m_signal_not_writable;
285 /// signal which is fired when new data was read
286 SignalType m_signal_read;
287 /// signal which is fired when data was written
288 SignalType m_signal_write;
290 /// end of file (on @a m_read_fd) detected (used additionally when m_read_fd is valid)
293 /// unable-to-write (on @a m_write_fd) detected (used additionally when m_write_fd is valid)
297 /// the file descriptor to read from (-1 if none is given)
299 /// the file descriptor to write to (-1 if none is given)
301 /// output buffer; contains the data which needs to be written.
302 std::string m_output_buffer;
305 /// @a true when data is available to be read
306 bool m_marked_for_reading;
307 /// @a true when data can be written
308 bool m_marked_for_writing;
310 }; // eo class IOImplementation
315 * same as IOImplementation, but makes fd access functions public.
317 class IOImplementation2 : public IOImplementation
319 typedef IOImplementation inherited;
321 IOImplementation2(int read_fd=-1, int write_fd=-1) : inherited(read_fd, write_fd) {}
323 void setWriteFd(int fd) { inherited::setWriteFd(fd); }
324 void setReadFd(int fd) { inherited::setReadFd(fd); }
326 int readFd() const { return inherited::readFd(); }
327 int writeFd() const { return inherited::writeFd(); }
329 }; // eo class IOImplementation2
333 * provides sending data and receiving data via a signal.
335 * @note the received data is passed as parameter to the signal and no longer stored in the received buffer.
337 class SimpleIO : public IOImplementation
339 typedef IOImplementation inherited;
341 SimpleIO(int read_fd=-1, int write_fd=-1);
344 void sendString(const std::string& data);
346 boost::signal<void(const std::string&)> signal_received_string;
351 }; // eo class SimpleIO
355 * provides sending data and receiving data via a signal.
357 * @note the received data is passed as parameter to the signal and no longer stored in the received buffer.
359 class SimpleIO2 : public IOImplementation2
361 typedef IOImplementation2 inherited;
363 SimpleIO2(int read_fd=-1, int write_fd=-1);
364 virtual ~SimpleIO2();
366 void sendString(const std::string& data);
368 boost::signal<void(const std::string&)> signal_received_string;
373 }; // eo class SimpleIO2
377 * provides the backend for io handling.
379 * This (singleton) object provides the management of io events. It collects all wishes for reading/writing
380 * from the io objects and information from the timer events.
381 * It poll()s for the events and distributes them to the objects,
383 * The class provides the possibility for executing one io cycle (/step) or to run a backend loop.
385 * @note the Backend class needs to be a friend of IOImplementation since it accesses private members
386 * of IOImplementation while performing the io cycles.
391 typedef std::set< int > FdSetType;
395 bool doOneStep(int ms_timeout= -1);
401 Backend(const Backend& other);
406 /// the number of currently active backend loops
407 int m_count_active_loops;
408 /// the number of pending stop requests (where each one should exit one active backend loop)
409 int m_count_stop_requests;
411 /// the number of currently active backend cycles(/ steps)
412 static int m_count_active_steps;
415 static Backend* getBackend();
418 /// pointer to the active backend (which is delivered by Backend::getBackend)
419 static Backend* g_backend;
420 }; // eo class Backend
424 } // eo namespace AsyncIo