X-Git-Url: http://developer.intra2net.com/git/?p=libt2n;a=blobdiff_plain;f=src%2Fconnection.cpp;h=c9283fe375950c613a581a59ced110e2cfb0b587;hp=b4cf198abc9fe514af6bb06c831b1c934b47a8a9;hb=4b995a82e29808cf8125889f83ec70fc7b5c77af;hpb=a64066eb0e456c92c4c06959616443e531d4b39d diff --git a/src/connection.cpp b/src/connection.cpp index b4cf198..c9283fe 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include @@ -45,6 +46,7 @@ void connection::close() } } +/// get the number of bytes being available as next complete packet connection::packet_size_indicator connection::bytes_available() { // no size information -> no packet @@ -103,6 +105,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) { @@ -125,9 +160,6 @@ void connection::write(const std::string& data) */ void connection::add_callback(callback_event_type event, const boost::function& func) { - if (event == new_connection) - throw std::logic_error("new_connection callback not allowed for server_connections"); - callbacks[event].push_back(func); } @@ -154,5 +186,24 @@ std::list > connection::get_callback_list(callback_even 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); +} }