/* * endpointset.cpp * * Created on: 27.03.2013 * Author: mario */ #include "endpoint_set.hpp" // ariba endpoints #include "tcpip_endpoint.hpp" // boost #include #include #include namespace ariba { namespace addressing2 { using namespace std; using boost::property_tree::ptree; // TODO maybe this function wants to go in a distinct header.. template T read_from_byte_array(const uint8_t*& buff, int& read_max) { assert ( sizeof(T) <= read_max ); const uint8_t* b1 = buff; buff += sizeof(T); read_max -= sizeof(T); return *( reinterpret_cast(b1) ); } /* factories */ //shared_ptr endpoint_set::create_EndpointSet(const std::string & str) //{ // EndpointSetPtr set(new endpoint_set(str)); // // return set; //} shared_ptr endpoint_set::create_EndpointSet(const ptree& pt) { EndpointSetPtr set(new endpoint_set(pt)); return set; } shared_ptr endpoint_set::create_EndpointSet() { EndpointSetPtr set(new endpoint_set()); return set; } endpoint_set::endpoint_set() { } endpoint_set::endpoint_set(const ptree& pt) { /* create & add endpoints */ BOOST_FOREACH( const ptree::value_type& child, pt ) { string cat = child.second.get("category"); // TCPIP if ( cat == "TCPIP" ) { string addr = child.second.get("addr"); int port = child.second.get("port"); TcpIP_EndpointPtr endp(new tcpip_endpoint(addr, port)); tcpip_endpoints.push_back(endp); } // TODO else if bluetooth } } //endpoint_set::endpoint_set(const string& str) //{ // // TODO see endpoint_set(const ptree& pt) // // // ptree pt; // // /* parse input string */ // // input string format is: JSON // if (str.substr(0, 4) == "JSON") // { // istringstream sstream(str.substr(4, string::npos)); // boost::property_tree::json_parser::read_json(sstream, pt); // } // // --- other formats can be supported here (e.g. XML) --- // else // { // throw invalid_argument("Could not parse endpoint_set from string."); // } // // // // /* create & add endpoints */ // BOOST_FOREACH(const ptree::value_type& child, pt.get_child("endpoint_set")) // { // string cat = child.second.get("category"); // // // TCPIP // if ( cat == "TCPIP" ) // { // string addr = child.second.get("addr"); // int port = child.second.get("port"); // // TcpIP_EndpointPtr endp(new tcpip_endpoint(addr, port)); // // tcpip_endpoints.push_back(endp); // } // // // TODO else if bluetooth // } //} endpoint_set::~endpoint_set() { } void endpoint_set::add_endpoint(EndpointPtr endpoint) { switch ( endpoint->get_category() ) { case endpoint_category::TCPIP: { // TODO try-catch --> log a warning shared_ptr tcpip_endp = boost::dynamic_pointer_cast(endpoint); // no duplicates bool duplicate = false; BOOST_FOREACH(const shared_ptr& x, tcpip_endpoints) { if ( tcpip_endp->equals(x) ) { duplicate = true; break; } } if ( ! duplicate ) { // * add * tcpip_endpoints.push_back(tcpip_endp); } break; } default: { // TODO log a warning ^^ break; } } } void endpoint_set::add_endpoints(const shared_ptr endpoints) { // TODO bluetooth, etc.... BOOST_FOREACH( EndpointPtr endp, endpoints->get_tcpip_endpoints() ) { add_endpoint(endp); } } const vector >& endpoint_set::get_tcpip_endpoints() const { return tcpip_endpoints; } //const vector > endpoint_set::get_tcpip_endpoints() const //{ // vector > ret; // ret.reserve(tcpip_endpoints.size()); // // BOOST_FOREACH( const_TcpIP_EndpointPtr address, tcpip_endpoints ) // { // ret.push_back(address); // } // // return ret; //} string endpoint_set::to_string() const { ostringstream out; BOOST_FOREACH( EndpointPtr endp, tcpip_endpoints ) { out << endp->to_string() << "; "; } return out.str(); } /** * Format: * * | 16-bit: overall size | + ( | 8 bit: type | + | variable length: endpoint | ) * N * */ reboost::shared_buffer_t endpoint_set::serialize() const { // TODO bluetooth, etc.... /* calculate size */ // size: two byte length field size_t overall_size = sizeof(uint16_t); BOOST_FOREACH( EndpointPtr endp, tcpip_endpoints ) { // size: endpoint + type overall_size += endp->size() + 1; } // overall_size value must fit into 16 bits assert ( overall_size <= numeric_limits::max() ); /* serialize */ reboost::shared_buffer_t buff(overall_size); uint8_t* buff_ptr = buff.mutable_data(); // overall size memcpy( buff_ptr, &overall_size, sizeof(uint16_t) ); buff_ptr += sizeof(uint16_t); // tcpip_endpoints BOOST_FOREACH( EndpointPtr endp, tcpip_endpoints ) { // // XXX AKTUELL BUG FINDING... // cout << " - SERIALIZE: (" << (int) (buff_ptr - buff.mutable_data()) << ")"; // type *buff_ptr = static_cast(endp->get_type()); buff_ptr++; // serialize tcpip_endpoint buff_ptr += endp->to_byte_array(buff_ptr); // // XXX AKTUELL BUG FINDING... // cout << endp->to_string() << " (" << (int) (buff_ptr - buff.mutable_data()) << ")" << endl; } // boundary check assert( buff_ptr <= buff.mutable_data() + buff.size() ); return buff; } reboost::shared_buffer_t endpoint_set::deserialize(reboost::shared_buffer_t buff) { assert( tcpip_endpoints.size() == 0); const uint8_t* buff_ptr = buff.data(); // NOTE: the data is const, the pointer is not. // read overall size (16 bit value) int bytes_left = sizeof(uint16_t); uint16_t overall_size = read_from_byte_array(buff_ptr, bytes_left); // check claimed overall size if ( overall_size > buff.size() ) { // todo throw cout << endl << "FATAL ERROR in »endpoint_set::deserialize«: overall_size > buff.size()" << endl; assert ( false ); } // calculate bytes to read bytes_left = overall_size - sizeof(uint16_t); // read endpoints while ( bytes_left > 0 ) { // // XXX AKTUELL BUG FINDING... // cout << " - DESERIALIZE: (" << (int) (buff_ptr - buff.data()) << ")"; ENDPOINT_TYPE type = static_cast( read_from_byte_array(buff_ptr, bytes_left) ); switch (type) { case endpoint_type::TCPIPv4: case endpoint_type::TCPIPv6: { // TODO try catch TcpIP_EndpointPtr endp(new tcpip_endpoint(type, buff_ptr, bytes_left)); add_endpoint(endp); // move pointers const int bytes_read = endp->size(); buff_ptr += bytes_read; bytes_left -= bytes_read; // // XXX AKTUELL BUG FINDING... // cout << endp->to_string() << " (" << (int) (buff_ptr - buff.data()) << ")" << endl; break; } // TODO case endpoint_type::bluetooth...: default: { // TODO throw cout << endl << "FATAL ERROR in »endpoint_set::deserialize«: Unknown type (" << type << ")" << endl; cout << "BUFFER (size = " << buff.size() << "):" << endl; cout << buff << endl << "-------------------------" << endl; assert(false); break; } } assert( bytes_left >= 0 ); } // return sub-buffer return buff(overall_size); } }} /* namespace addressing2::ariba */