X-Git-Url: http://developer.intra2net.com/git/?p=libt2n;a=blobdiff_plain;f=src%2Fconnection.cpp;h=b4cf198abc9fe514af6bb06c831b1c934b47a8a9;hp=459194ded6c22a78d37f51ce4805f01103ce37cf;hb=a64066eb0e456c92c4c06959616443e531d4b39d;hpb=644c4d262aab14ee4ec1cfade83a2e99568098d3 diff --git a/src/connection.cpp b/src/connection.cpp index 459194d..b4cf198 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -19,52 +19,140 @@ #include #include +#include + +#include #include "connection.hxx" namespace libt2n { -connection::packet_size_indicator connection::bytes_available() +connection::~connection() +{ + // we want the connection_closed callbacks to be called before + close(); + + do_callbacks(connection_deleted); +} + +void connection::close() { - // max packet size is unsigned int + if (!is_closed()) + { + closed=true; + do_callbacks(connection_closed); + } +} +connection::packet_size_indicator connection::bytes_available() +{ // no size information -> no packet - if (buffer.size() < sizeof(unsigned int)) + if (buffer.size() < sizeof(packet_size_indicator)) return 0; - packet_size_indicator psize=*((packet_size_indicator*)(buffer.data())); + packet_size_indicator psize=ntohl(*((packet_size_indicator*)(buffer.data()))); // enough data for one packet in buffer? - if (buffer.size() < sizeof(unsigned int)+psize) + if (buffer.size() < sizeof(packet_size_indicator)+psize) return 0; // ok, full packet there return psize; } +/** @brief read a complete data packet from the buffer. The packet is removed from the + connection buffer. + @param[out] data the data package + @retval true if packet found +*/ bool connection::get_packet(std::string& data) { packet_size_indicator psize; if ((psize=bytes_available())) { - data.assign(buffer,sizeof(unsigned int),psize); - buffer.erase(0,sizeof(unsigned int)+psize); + data.assign(buffer,sizeof(packet_size_indicator),psize); + buffer.erase(0,sizeof(packet_size_indicator)+psize); return true; } else return false; } +/** @brief get (maybe incomplete) data of the next packet from the buffer. Does not remove the data + from the connection buffer. + @param[out] data the data package + @retval full size of the packet when it will be complete +*/ +unsigned int connection::peek_packet(std::string& data) +{ + // no size information -> no packet + if (buffer.size() < sizeof(packet_size_indicator)) + return 0; + + packet_size_indicator psize=ntohl(*((packet_size_indicator*)(buffer.data()))); + + // not the full data available? + packet_size_indicator currsize=psize; + if (buffer.size() < currsize+sizeof(packet_size_indicator)) + currsize=buffer.size()-sizeof(packet_size_indicator); + + data.assign(buffer,sizeof(packet_size_indicator),currsize); + + return psize; +} + +/// send a blob to the peer void connection::write(const std::string& data) { // prepend packet size to data - packet_size_indicator psize=data.size(); + packet_size_indicator psize=htonl(data.size()); std::string send_data(data); send_data.insert(0,(char*)&psize,sizeof(packet_size_indicator)); 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) +{ + if (event == new_connection) + throw std::logic_error("new_connection callback not allowed for server_connections"); + + 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]; +} + + }