X-Git-Url: http://developer.intra2net.com/git/?p=libt2n;a=blobdiff_plain;f=src%2Fconnection.cpp;h=30a0b19246dae9e4f277f561f135b00800457999;hp=d339f9f21b85ea38db0cf05358bbd9486b130d05;hb=af84dfb53a739a0c8c343d9172f1847fa908906d;hpb=b2ba092858a40fc42afba6b529d5b97bcba363e2 diff --git a/src/connection.cpp b/src/connection.cpp index d339f9f..30a0b19 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include @@ -28,6 +29,23 @@ namespace libt2n { +connection::~connection() +{ + // we want the connection_closed callbacks to be called before + close(); + + do_callbacks(connection_deleted); +} + +void connection::close() +{ + if (!is_closed()) + { + closed=true; + do_callbacks(connection_closed); + } +} + connection::packet_size_indicator connection::bytes_available() { // no size information -> no packet @@ -86,6 +104,39 @@ unsigned int connection::peek_packet(std::string& data) return psize; } +/// remove all data from buffer that is not a complete packet +void connection::remove_incomplete_packets() +{ + std::string::size_type p=0; + std::string::size_type end=buffer.size(); + + while (p < end) + { + // not enough space for size information -> no packet + if (p+sizeof(packet_size_indicator) > end) + break; + + packet_size_indicator psize=ntohl(*((packet_size_indicator*)(buffer.data()+p))); + + if (p+sizeof(packet_size_indicator)+psize > end) + { + // incomplete packet + break; + } + else + { + // move p to where the next packet will start + p+=sizeof(packet_size_indicator)+psize; + } + } + + if (p < end) + { + // incomplete packets there, remove them + buffer.erase(p); + } +} + /// send a blob to the peer void connection::write(const std::string& data) { @@ -97,4 +148,61 @@ void connection::write(const std::string& data) real_write(send_data); } +/** @brief add a callback + + @param event event the function will be called at + @param func functor (see boost function) that will be called + + @note 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 connection::add_callback(callback_event_type event, const boost::function& func) +{ + callbacks[event].push_back(func); +} + +/** @brief an event has occured, execute the callbacks that are registered for this event + + @param event event type that has occured +*/ +void connection::do_callbacks(callback_event_type event) +{ + std::list >::iterator i,ie=callbacks[event].end(); + for (i=callbacks[event].begin(); i != ie; i++) + (*i)(); +} + +/** @brief get the callbacks in place for one event + + @param event event the callbacks should be registered for + @return std::list of functors (boost::function) with the callbacks + + @note if you want to get the callbacks for all events, loop from 0 to __events_end +*/ +std::list > connection::get_callback_list(callback_event_type event) +{ + return callbacks[event]; +} + +/** @brief reopen a already closed connection, removes incomplete packets from the buffer + + @note Only call when the connection is closed. + + @note Justs cares about the data of connection, reconnecting has to be + done in a derived class. +*/ +void connection::reopen() +{ + if (!is_closed()) + throw std::logic_error("connection::reopen() called with connection still open"); + + closed=false; + + // incomplete buffer data is worthless with a new connection + remove_incomplete_packets(); + + do_callbacks(new_connection); +} + }