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/signals2.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::signals2::trackable
208 , virtual public Utils::SharedBase
210 friend class Backend;
211 friend class FilterBase;
215 typedef std::list< FilterBasePtr > FilterChain;
217 typedef boost::signals2::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::signals2::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;
235 virtual std::string getInput() const;
236 virtual std::string getInputClear();
237 virtual bool inputAvailable() const;
238 virtual std::string::size_type shortenInput(std::string::size_type len);
239 virtual std::string getline(char delim='\n');
243 void addFilter(FilterBasePtr filter);
244 void removeFilter(FilterBasePtr);
247 void lowSend(const std::string& data);
249 std::string::size_type getOutputBufferSize() const { return m_output_buffer.size(); }
251 void setWriteFd(int fd);
252 void setReadFd(int fd);
254 inline int readFd() const
259 inline int writeFd() const
264 inline bool isMarkedForReading() const { return m_marked_for_reading; }
265 inline bool isMarkedForWriting() const { return m_marked_for_writing; }
269 virtual void doRead();
270 virtual void doWrite();
272 void resetReadMark() { m_marked_for_reading= false; }
273 void resetWriteMark() { m_marked_for_writing= false; }
275 void injectIncomingData(FilterBasePtr from_filter, const std::string& _data);
276 void injectOutgoingData(FilterBasePtr from_filter, const std::string& _data);
279 /// last error number
281 /// the input buffer (i.e. the data read from @a m_read_fd)
282 std::string m_input_buffer;
284 /// the chain of filter which are applied to the data received are the data which should be send.
285 FilterChain m_filter_chain;
287 /// signal which is fired when end of file is detected
288 SignalType m_signal_eof;
289 /// signal which is fired when write is no longer possible
290 SignalType m_signal_not_writable;
291 /// signal which is fired when new data was read
292 SignalType m_signal_read;
293 /// signal which is fired when data was written
294 SignalType m_signal_write;
296 /// end of file (on @a m_read_fd) detected (used additionally when m_read_fd is valid)
299 /// unable-to-write (on @a m_write_fd) detected (used additionally when m_write_fd is valid)
303 /// the file descriptor to read from (-1 if none is given)
305 /// the file descriptor to write to (-1 if none is given)
307 /// output buffer; contains the data which needs to be written.
308 std::string m_output_buffer;
311 /// @a true when data is available to be read
312 bool m_marked_for_reading;
313 /// @a true when data can be written
314 bool m_marked_for_writing;
316 }; // eo class IOImplementation
321 * same as IOImplementation, but makes fd access functions public.
323 class IOImplementation2 : public IOImplementation
325 typedef IOImplementation inherited;
327 IOImplementation2(int read_fd=-1, int write_fd=-1) : inherited(read_fd, write_fd) {}
329 void setWriteFd(int fd) { inherited::setWriteFd(fd); }
330 void setReadFd(int fd) { inherited::setReadFd(fd); }
332 int readFd() const { return inherited::readFd(); }
333 int writeFd() const { return inherited::writeFd(); }
335 }; // eo class IOImplementation2
339 * provides sending data and receiving data via a signal.
341 * @note the received data is passed as parameter to the signal and no longer stored in the received buffer.
343 class SimpleIO : public IOImplementation
345 typedef IOImplementation inherited;
347 SimpleIO(int read_fd=-1, int write_fd=-1);
350 void sendString(const std::string& data);
352 boost::signals2::signal<void(const std::string&)> signal_received_string;
357 }; // eo class SimpleIO
361 * provides sending data and receiving data via a signal.
363 * @note the received data is passed as parameter to the signal and no longer stored in the received buffer.
365 class SimpleIO2 : public IOImplementation2
367 typedef IOImplementation2 inherited;
369 SimpleIO2(int read_fd=-1, int write_fd=-1);
370 virtual ~SimpleIO2();
372 void sendString(const std::string& data);
374 boost::signals2::signal<void(const std::string&)> signal_received_string;
379 }; // eo class SimpleIO2
383 * provides the backend for io handling.
385 * This (singleton) object provides the management of io events. It collects all wishes for reading/writing
386 * from the io objects and information from the timer events.
387 * It poll()s for the events and distributes them to the objects,
389 * The class provides the possibility for executing one io cycle (/step) or to run a backend loop.
391 * @note the Backend class needs to be a friend of IOImplementation since it accesses private members
392 * of IOImplementation while performing the io cycles.
397 typedef std::set< int > FdSetType;
401 bool doOneStep(int ms_timeout= -1);
407 Backend(const Backend& other);
412 /// the number of currently active backend loops
413 int m_count_active_loops;
414 /// the number of pending stop requests (where each one should exit one active backend loop)
415 int m_count_stop_requests;
417 /// the number of currently active backend cycles(/ steps)
418 static int m_count_active_steps;
421 static Backend* getBackend();
424 /// pointer to the active backend (which is delivered by Backend::getBackend)
425 static Backend* g_backend;
426 }; // eo class Backend
430 } // eo namespace AsyncIo