***************************************************************************/
#include <sstream>
+#include <stdexcept>
+
+#include <boost/bind.hpp>
#include "server.hxx"
#include "log.hxx"
{
server_connection::server_connection(int _timeout)
- : connection()
+ : connection(), callbacks(__events_end)
{
set_timeout(_timeout);
reset_timeout();
my_server=0;
}
+server_connection::~server_connection()
+{
+ // we want the connection_closed callbacks to be called before
+ close();
+
+ do_callbacks(connection_deleted);
+}
+
+void server_connection::close()
+{
+ if (!is_closed())
+ {
+ connection::close();
+ do_callbacks(connection_closed);
+ }
+}
/// get pointer to logging stream, returns NULL if no logging needed
std::ostream* server_connection::get_logstream(log_level_values level)
last_action_time=time(NULL);
}
+/** @brief add a callback
+
+ @param event event the function will be called at
+ @param func functor (see boost function) that will be called
+
+ @example use boost::bind to bind to member functions and parameters like this:
+ 17 is a fixed parameter that is always added to the call
+ c.add_callback(connection_closed,bind(&my_class::func_to_call_back, boost::ref(*this), 17));
+*/
+void server_connection::add_callback(callback_event_type event, const boost::function<void ()>& func)
+{
+ if (event == new_connection)
+ throw std::logic_error("new_connection callback not allowed for server_connections");
+
+ callbacks[event].push_back(func);
+}
+
+void server_connection::do_callbacks(callback_event_type event)
+{
+ std::list<boost::function<void ()> >::iterator i,ie=callbacks[event].end();
+ for (i=callbacks[event].begin(); i != ie; i++)
+ (*i)();
+}
+
server::server()
: callbacks(__events_end)
{
@param event event the function will be called at
@param func functor (see boost function) that will be called
+
+ @example use boost::bind to bind to member functions like this:
+ s.add_callback(new_connection,bind(&my_class::func_to_call_back, boost::ref(*this), _1));
*/
-void server::add_callback(callback_event_type event, const boost::function<void (server_connection*)>& func)
+void server::add_callback(callback_event_type event, const boost::function<void (unsigned int)>& func)
{
callbacks[event].push_back(func);
+
+ // add callback to all existing connections
+ if (event != new_connection)
+ {
+ std::map<unsigned int, server_connection*>::iterator ie=connections.end();
+ for(std::map<unsigned int, server_connection*>::iterator i=connections.begin(); i != ie; i++)
+ i->second->add_callback(event,bind(func, i->first));
+ }
}
-void server::do_callbacks(callback_event_type event, server_connection* conn)
+void server::do_callbacks(callback_event_type event, unsigned int conn_id)
{
- std::list<boost::function<void (server_connection*)> >::iterator i,ie=callbacks[event].end();
+ std::list<boost::function<void (unsigned int)> >::iterator i,ie=callbacks[event].end();
for (i=callbacks[event].begin(); i != ie; i++)
- (*i)(conn);
+ (*i)(conn_id);
}
int server::add_connection(server_connection* newconn)
newconn->set_server(this);
connections[cid]=newconn;
+ // add all callbacks
+ for(int e=connection_closed; e != __events_end; e++)
+ {
+ std::list<boost::function<void (unsigned int)> >::iterator i,ie=callbacks[e].end();
+ for (i=callbacks[e].begin(); i != ie; i++)
+ newconn->add_callback(static_cast<callback_event_type>(e),bind(*i,cid));
+ }
+
LOGSTREAM(debug,"new connection accepted, id: " << cid);
- do_callbacks(new_connection,newconn);
+ do_callbacks(new_connection,cid);
return cid;
}