3 * @brief simple basic IO handling.
5 * @copyright © Copyright 2007-2008 by Intra2net AG
7 * @contact info@intra2net.com
9 * Deals with POSIX file descriptors; provides an additional abstraction
10 * level above select() or poll() interface.
11 * Also provides basic functionality for dealing with timer events.
14 #ifndef __ASYNC_IO_HPP__
15 #define __ASYNC_IO_HPP__
21 #include <asyncio_utils.hpp>
23 #include <pointer_func.hpp>
25 #include <boost/signal.hpp>
26 #include <boost/shared_ptr.hpp>
33 using Utils::MilliTime;
36 * forward declarations
39 class IOImplementation;
42 * end of forward declarations
47 * direction for io operations.
59 Direction( _Direction direction = unspecified) : m_direction(direction) {}
61 operator _Direction () const { return m_direction; }
62 }; // eo struct IODirection;
67 * base class for time based events (timer events).
69 * consists basically of a point in time (when the event should be executed) and a method
70 * which will be called when the given time is reached (or passed).
79 bool active() const { return m_active; }
81 MilliTime getWhenTime() const {return m_when;}
82 MilliTime getRealWhenTime() const;
86 void setWhenTime(long sec, long msec=0);
87 void setWhenTime(const MilliTime& mt);
89 void setDeltaWhenTime(long sec, long msec=0);
90 void setDeltaWhenTime(const MilliTime& mt);
92 void activate(bool _active= true);
93 void deactivate() { activate(false); }
95 virtual void execute();
98 /// @a true when the event is active.
100 /// point in time when the event should be executed
102 /// mark from backend cycle that the event has to be executed.
104 }; // eo class TimerBase
109 * base class for filter classes.
111 * filter objects can be "plugged" into IO objects for manipulating the data streams.
112 * (for example: one could make a filter which handles the telnet protocol and plug it into a
115 * @note filter object can be used only by one io object.
118 : virtual public SharedBase
120 friend class IOImplementation;
122 typedef boost::shared_ptr< FilterBase > PtrType;
125 virtual ~FilterBase() { m_io = NULL; };
129 virtual std::string filterIncomingData(const std::string& data)= 0;
130 virtual std::string filterOutgoingData(const std::string& data)= 0;
132 virtual void endOfIncomingData();
133 virtual void reset();
137 void injectIncomingData(const std::string& data);
138 void injectOutgoingData(const std::string& data);
141 /// pointer to the io object which uses this filter:
142 IOImplementation *m_io;
143 }; // eo class FilterBase
145 typedef FilterBase::PtrType FilterBasePtr;
149 * identity filter; does nothing with the data (in other words: it's useless ;-) ).
151 class FilterIdentity : public FilterBase
154 virtual std::string filterIncomingData(const std::string& data) { return data; }
155 virtual std::string filterOutgoingData(const std::string& data) { return data; }
156 }; // eo class FilterIdentity
160 * @brief null filter; deletes everything it receives.
162 * usefull when output from a subprocess (like stderr) should be ignored...
164 class FilterNull : public FilterBase
167 virtual std::string filterIncomingData(const std::string& data) { return std::string(); }
168 virtual std::string filterOutgoingData(const std::string& data) { return std::string(); }
173 * the base class of the IO classes.
175 * provides the functionality to read from a file desriptor and write to a file descriptor (which can be
176 * identical (like for socket io), but also can be different (like pipes from/to a process)).
177 * The data stream can be filtered through plugged filter objects which are building a filter chain.
178 * Incoming data is filtered forward through the chain; outgoing data is filtered backward through the chain.
179 * (So the first filter is the one which modifies the data closest to the connections).
181 * @note the functionality is provided in conjunction with the @a Backend class which handles parts of
184 * @note this is a base class; it provides most "interesting" functionality in the protected section only.
185 * This way, derived classes can decide which of that functionality they want to export in their own public
186 * interfaces and which to keep hidden.
188 class IOImplementation
189 : public boost::signals::trackable
190 , virtual public SharedBase
192 friend class Backend;
193 friend class FilterBase;
197 typedef std::list< FilterBasePtr > FilterChain;
199 typedef boost::signal< void() > SignalType;
201 typedef boost::shared_ptr< IOImplementation > PtrType;
204 IOImplementation(int read_fd=-1, int write_fd=-1);
205 virtual ~IOImplementation();
207 virtual void close(Direction direction = Direction::both);
209 virtual bool wantRead();
210 virtual bool wantWrite();
212 virtual bool opened() const;
213 virtual bool eof() const;
214 virtual bool writable() const;
215 virtual bool empty() const;
219 void addFilter(FilterBasePtr filter);
220 void removeFilter(FilterBasePtr);
223 void lowSend(const std::string& data);
225 std::string::size_type getOutputBufferSize() const { return m_output_buffer.size(); }
227 void setWriteFd(int fd);
228 void setReadFd(int fd);
230 inline int readFd() const
235 inline int writeFd() const
240 inline bool isMarkedForReading() const { return m_marked_for_reading; }
241 inline bool isMarkedForWriting() const { return m_marked_for_writing; }
245 virtual void doRead();
246 virtual void doWrite();
248 void resetReadMark() { m_marked_for_reading= false; }
249 void resetWriteMark() { m_marked_for_writing= false; }
251 void injectIncomingData(FilterBasePtr from_filter, const std::string& _data);
252 void injectOutgoingData(FilterBasePtr from_filter, const std::string& _data);
255 /// last error number
257 /// the input buffer (i.e. the data read from @a m_read_fd)
258 std::string m_input_buffer;
260 /// the chain of filter which are applied to the data received are the data which should be send.
261 FilterChain m_filter_chain;
263 /// signal which is fired when end of file is detected
264 SignalType m_signal_eof;
265 /// signal which is fired when write is no longer possible
266 SignalType m_signal_not_writable;
267 /// signal which is fired when new data was read
268 SignalType m_signal_read;
269 /// signal which is fired when data was written
270 SignalType m_signal_write;
272 /// end of file (on @a m_read_fd) detected (used additionally when m_read_fd is valid)
275 /// unable-to-write (on @a m_write_fd) detected (used additionally when m_write_fd is valid)
279 /// the file descriptor to read from (-1 if none is given)
281 /// the file descriptor to write to (-1 if none is given)
283 /// output buffer; contains the data which needs to be written.
284 std::string m_output_buffer;
287 /// @a true when data is available to be read
288 bool m_marked_for_reading;
289 /// @a true when data can be written
290 bool m_marked_for_writing;
292 }; // eo class IOImplementation
297 * same as IOImplementation, but makes fd access functions public.
299 class IOImplementation2 : public IOImplementation
301 typedef IOImplementation inherited;
303 IOImplementation2(int read_fd=-1, int write_fd=-1) : inherited(read_fd, write_fd) {}
305 void setWriteFd(int fd) { inherited::setWriteFd(fd); }
306 void setReadFd(int fd) { inherited::setReadFd(fd); }
308 int readFd() const { return inherited::readFd(); }
309 int writeFd() const { return inherited::writeFd(); }
311 }; // eo class IOImplementation2
315 * provides sending data and receiving data via a signal.
317 * @note the received data is passed as parameter to the signal and no longer stored in the received buffer.
319 class SimpleIO : public IOImplementation
321 typedef IOImplementation inherited;
323 SimpleIO(int read_fd=-1, int write_fd=-1);
326 void sendString(const std::string& data);
328 boost::signal<void(const std::string&)> signal_received_string;
333 }; // eo class SimpleIO
337 * provides sending data and receiving data via a signal.
339 * @note the received data is passed as parameter to the signal and no longer stored in the received buffer.
341 class SimpleIO2 : public IOImplementation2
343 typedef IOImplementation2 inherited;
345 SimpleIO2(int read_fd=-1, int write_fd=-1);
346 virtual ~SimpleIO2();
348 void sendString(const std::string& data);
350 boost::signal<void(const std::string&)> signal_received_string;
355 }; // eo class SimpleIO2
359 * provides the backend for io handling.
361 * This (singleton) object provides the management of io events. It collects all wishes for reading/writing
362 * from the io objects and information from the timer events.
363 * It poll()s for the events and distributes them to the objects,
365 * The class provides the possibility for executing one io cycle (/step) or to run a backend loop.
367 * @note the Backend class needs to be a friend of IOImplementation since it accesses private members
368 * of IOImplementation while performing the io cycles.
373 typedef std::set< int > FdSetType;
377 bool doOneStep(int ms_timeout= -1);
383 Backend(const Backend& other);
388 /// the number of currently active backend loops
389 int m_count_active_loops;
390 /// the number of pending stop requests (where each one should exit one active backend loop)
391 int m_count_stop_requests;
393 /// the number of currently active backend cycles(/ steps)
394 static int m_count_active_steps;
397 static Backend* getBackend();
400 /// pointer to the active backend (which is delivered by Backend::getBackend)
401 static Backend* g_backend;
402 }; // eo class Backend
406 } // eo namespace AsyncIo