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_config.hpp>
23 #include <asyncio_utils.hpp>
25 #include <boost/signal.hpp>
26 #include <boost/shared_ptr.hpp>
32 #ifdef HAVE_LIBI2NCOMMON
35 using Utils::MilliTime;
38 * forward declarations
41 class IOImplementation;
44 * end of forward declarations
49 * direction for io operations.
61 Direction( _Direction direction = unspecified) : m_direction(direction) {}
63 operator _Direction () const { return m_direction; }
64 }; // eo struct IODirection;
69 * base class for time based events (timer events).
71 * consists basically of a point in time (when the event should be executed) and a method
72 * which will be called when the given time is reached (or passed).
81 bool active() const { return m_active; }
83 MilliTime getWhenTime() const {return m_when;}
84 MilliTime getRealWhenTime() const;
88 void setWhenTime(long sec, long msec=0);
89 void setWhenTime(const MilliTime& mt);
91 void setDeltaWhenTime(long sec, long msec=0);
92 void setDeltaWhenTime(const MilliTime& mt);
94 void activate(bool _active= true);
95 void deactivate() { activate(false); }
97 virtual void execute();
100 /// @a true when the event is active.
102 /// point in time when the event should be executed
104 /// mark from backend cycle that the event has to be executed.
106 }; // eo class TimerBase
111 * base class for filter classes.
113 * filter objects can be "plugged" into IO objects for manipulating the data streams.
114 * (for example: one could make a filter which handles the telnet protocol and plug it into a
117 * @note filter object can be used only by one io object.
120 : virtual public Utils::SharedBase
122 friend class IOImplementation;
124 typedef boost::shared_ptr< FilterBase > PtrType;
127 virtual ~FilterBase() { m_io = NULL; };
131 virtual std::string filterIncomingData(const std::string& data)= 0;
132 virtual std::string filterOutgoingData(const std::string& data)= 0;
134 virtual void endOfIncomingData();
135 virtual void reset();
139 void injectIncomingData(const std::string& data);
140 void injectOutgoingData(const std::string& data);
143 /// pointer to the io object which uses this filter:
144 IOImplementation *m_io;
145 }; // eo class FilterBase
147 typedef FilterBase::PtrType FilterBasePtr;
151 * identity filter; does nothing with the data (in other words: it's useless ;-) ).
153 class FilterIdentity : public FilterBase
156 virtual std::string filterIncomingData(const std::string& data) { return data; }
157 virtual std::string filterOutgoingData(const std::string& data) { return data; }
158 }; // eo class FilterIdentity
162 * @brief null filter; deletes everything it receives.
164 * usefull when output from a subprocess (like stderr) should be ignored...
166 class FilterNull : public FilterBase
169 virtual std::string filterIncomingData(const std::string& data) { return std::string(); }
170 virtual std::string filterOutgoingData(const std::string& data) { return std::string(); }
175 * the base class of the IO classes.
177 * provides the functionality to read from a file desriptor and write to a file descriptor (which can be
178 * identical (like for socket io), but also can be different (like pipes from/to a process)).
179 * The data stream can be filtered through plugged filter objects which are building a filter chain.
180 * Incoming data is filtered forward through the chain; outgoing data is filtered backward through the chain.
181 * (So the first filter is the one which modifies the data closest to the connections).
183 * @note the functionality is provided in conjunction with the @a Backend class which handles parts of
186 * @note this is a base class; it provides most "interesting" functionality in the protected section only.
187 * This way, derived classes can decide which of that functionality they want to export in their own public
188 * interfaces and which to keep hidden.
190 class IOImplementation
191 : public boost::signals::trackable
192 , virtual public Utils::SharedBase
194 friend class Backend;
195 friend class FilterBase;
199 typedef std::list< FilterBasePtr > FilterChain;
201 typedef boost::signal< void() > SignalType;
203 typedef boost::shared_ptr< IOImplementation > PtrType;
206 IOImplementation(int read_fd=-1, int write_fd=-1);
207 virtual ~IOImplementation();
209 virtual void close(Direction direction = Direction::both);
211 virtual bool wantRead();
212 virtual bool wantWrite();
214 virtual bool opened() const;
215 virtual bool eof() const;
216 virtual bool writable() const;
217 virtual bool empty() const;
221 void addFilter(FilterBasePtr filter);
222 void removeFilter(FilterBasePtr);
225 void lowSend(const std::string& data);
227 std::string::size_type getOutputBufferSize() const { return m_output_buffer.size(); }
229 void setWriteFd(int fd);
230 void setReadFd(int fd);
232 inline int readFd() const
237 inline int writeFd() const
242 inline bool isMarkedForReading() const { return m_marked_for_reading; }
243 inline bool isMarkedForWriting() const { return m_marked_for_writing; }
247 virtual void doRead();
248 virtual void doWrite();
250 void resetReadMark() { m_marked_for_reading= false; }
251 void resetWriteMark() { m_marked_for_writing= false; }
253 void injectIncomingData(FilterBasePtr from_filter, const std::string& _data);
254 void injectOutgoingData(FilterBasePtr from_filter, const std::string& _data);
257 /// last error number
259 /// the input buffer (i.e. the data read from @a m_read_fd)
260 std::string m_input_buffer;
262 /// the chain of filter which are applied to the data received are the data which should be send.
263 FilterChain m_filter_chain;
265 /// signal which is fired when end of file is detected
266 SignalType m_signal_eof;
267 /// signal which is fired when write is no longer possible
268 SignalType m_signal_not_writable;
269 /// signal which is fired when new data was read
270 SignalType m_signal_read;
271 /// signal which is fired when data was written
272 SignalType m_signal_write;
274 /// end of file (on @a m_read_fd) detected (used additionally when m_read_fd is valid)
277 /// unable-to-write (on @a m_write_fd) detected (used additionally when m_write_fd is valid)
281 /// the file descriptor to read from (-1 if none is given)
283 /// the file descriptor to write to (-1 if none is given)
285 /// output buffer; contains the data which needs to be written.
286 std::string m_output_buffer;
289 /// @a true when data is available to be read
290 bool m_marked_for_reading;
291 /// @a true when data can be written
292 bool m_marked_for_writing;
294 }; // eo class IOImplementation
299 * same as IOImplementation, but makes fd access functions public.
301 class IOImplementation2 : public IOImplementation
303 typedef IOImplementation inherited;
305 IOImplementation2(int read_fd=-1, int write_fd=-1) : inherited(read_fd, write_fd) {}
307 void setWriteFd(int fd) { inherited::setWriteFd(fd); }
308 void setReadFd(int fd) { inherited::setReadFd(fd); }
310 int readFd() const { return inherited::readFd(); }
311 int writeFd() const { return inherited::writeFd(); }
313 }; // eo class IOImplementation2
317 * provides sending data and receiving data via a signal.
319 * @note the received data is passed as parameter to the signal and no longer stored in the received buffer.
321 class SimpleIO : public IOImplementation
323 typedef IOImplementation inherited;
325 SimpleIO(int read_fd=-1, int write_fd=-1);
328 void sendString(const std::string& data);
330 boost::signal<void(const std::string&)> signal_received_string;
335 }; // eo class SimpleIO
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 SimpleIO2 : public IOImplementation2
345 typedef IOImplementation2 inherited;
347 SimpleIO2(int read_fd=-1, int write_fd=-1);
348 virtual ~SimpleIO2();
350 void sendString(const std::string& data);
352 boost::signal<void(const std::string&)> signal_received_string;
357 }; // eo class SimpleIO2
361 * provides the backend for io handling.
363 * This (singleton) object provides the management of io events. It collects all wishes for reading/writing
364 * from the io objects and information from the timer events.
365 * It poll()s for the events and distributes them to the objects,
367 * The class provides the possibility for executing one io cycle (/step) or to run a backend loop.
369 * @note the Backend class needs to be a friend of IOImplementation since it accesses private members
370 * of IOImplementation while performing the io cycles.
375 typedef std::set< int > FdSetType;
379 bool doOneStep(int ms_timeout= -1);
385 Backend(const Backend& other);
390 /// the number of currently active backend loops
391 int m_count_active_loops;
392 /// the number of pending stop requests (where each one should exit one active backend loop)
393 int m_count_stop_requests;
395 /// the number of currently active backend cycles(/ steps)
396 static int m_count_active_steps;
399 static Backend* getBackend();
402 /// pointer to the active backend (which is delivered by Backend::getBackend)
403 static Backend* g_backend;
404 }; // eo class Backend
408 } // eo namespace AsyncIo