X-Git-Url: http://developer.intra2net.com/git/?p=libt2n;a=blobdiff_plain;f=src%2Fcommand_client.cpp;h=376d3f965fd1d44e36c3bd7817a55285505db74b;hp=0d387b9e0029faa8d93ded8be30fcc7b37e2486b;hb=b2ba092858a40fc42afba6b529d5b97bcba363e2;hpb=7087e18783f91d2b889e880462d1d1da24831c28 diff --git a/src/command_client.cpp b/src/command_client.cpp index 0d387b9..376d3f9 100644 --- a/src/command_client.cpp +++ b/src/command_client.cpp @@ -25,36 +25,192 @@ #include #include #include -#include + +#include #include "command_client.hxx" +#ifdef HAVE_CONFIG_H +#include +#endif + using namespace std; namespace libt2n { +command_client::command_client(client_connection& _c, long long _command_timeout_usec, long long _hello_timeout_usec) + : c(_c) +{ + command_timeout_usec=_command_timeout_usec; + hello_timeout_usec=_hello_timeout_usec; + + // for reconnects + c.add_callback(new_connection,bind(&command_client::read_hello, boost::ref(*this))); + + read_hello(); +} + +std::string command_client::read_packet(const long long &usec_timeout) +{ + string resultpacket; + bool got_packet=false; + long long my_timeout=usec_timeout; + while(!(got_packet=c.get_packet(resultpacket)) && my_timeout > 0 && !c.is_closed()) + c.fill_buffer(my_timeout,&my_timeout); + + if (!got_packet) + throw t2n_transfer_error("timeout exceeded"); + + return resultpacket; +} + +void command_client::read_hello() +{ + string resultpacket; + bool got_packet=false; + long long my_timeout=hello_timeout_usec; + while(!(got_packet=c.get_packet(resultpacket)) && my_timeout > 0 && !c.is_closed()) + { + c.fill_buffer(my_timeout,&my_timeout); + + c.peek_packet(resultpacket); + check_hello(resultpacket); // will throw before timeout if wrong data received + } + + if (!got_packet) + throw t2n_transfer_error("timeout exceeded"); + + if (!check_hello(resultpacket)) + throw t2n_version_mismatch("illegal hello received (incomplete): "+resultpacket); +} + +bool command_client::check_hello(const string& hellostr) +{ + istringstream hello(hellostr); + + char chk; + + if (hello.read(&chk,1)) + { + if (chk != 'T') + throw t2n_version_mismatch("illegal hello received (T2N)"); + } + else + return false; + + if (hello.read(&chk,1)) + { + if (chk != '2') + throw t2n_version_mismatch("illegal hello received (T2N)"); + } + else + return false; + + if (hello.read(&chk,1)) + { + if (chk != 'N') + throw t2n_version_mismatch("illegal hello received (T2N)"); + } + else + return false; + + if (hello.read(&chk,1)) + { + if (chk != 'v') + throw t2n_version_mismatch("illegal hello received (T2N)"); + } + else + return false; + + int prot_version; + if (hello >> prot_version) + { + if (prot_version != PROTOCOL_VERSION) + throw t2n_version_mismatch("not compatible with the server protocol version"); + } + else + return false; + + if (hello.read(&chk,1)) + { + if (chk != ';') + throw t2n_version_mismatch("illegal hello received (1. ;)"); + } + else + return false; + + unsigned int hbo; + if (hello.read((char*)&hbo,sizeof(hbo))) + { + if (hbo != 1) + throw t2n_version_mismatch("host byte order not matching"); + } + else + return false; + + if (hello.read(&chk,1)) + { + if (chk != ';') + throw t2n_version_mismatch("illegal hello received (2. ;)"); + } + else + return false; + + return true; +} + void command_client::send_command(command* cmd, result_container &res) { ostringstream ofs; command_container cc(cmd); boost::archive::binary_oarchive oa(ofs); - // TODO: exceptions - oa << cc; + try + { + oa << cc; + } + catch(boost::archive::archive_exception &e) + { + ostringstream msg; + msg << "archive_exception while serializing on client-side, code " << e.code << " (" << e.what() << ")"; + throw t2n_serialization_error(msg.str()); + } + catch(...) + { throw; } - c.write(ofs.str()); + std::ostream* ostr; + if ((ostr=c.get_logstream(fulldebug))!=NULL) + { + (*ostr) << "sending command, decoded data: " << std::endl; + boost::archive::xml_oarchive xo(*ostr); + xo << BOOST_SERIALIZATION_NVP(cc); + } - // TODO: fix timeout - string resultpacket; - while(!c.get_packet(resultpacket)) - c.fill_buffer(); + c.write(ofs.str()); - istringstream ifs(resultpacket); + istringstream ifs(read_packet(command_timeout_usec)); boost::archive::binary_iarchive ia(ifs); - // TODO: exceptions - ia >> res; + try + { + ia >> res; + } + catch(boost::archive::archive_exception &e) + { + ostringstream msg; + msg << "archive_exception while deserializing on client-side, code " << e.code << " (" << e.what() << ")"; + throw t2n_serialization_error(msg.str()); + } + catch(...) + { throw; } + + if ((ostr=c.get_logstream(fulldebug))!=NULL) + { + (*ostr) << "received result, decoded data: " << std::endl; + boost::archive::xml_oarchive xo(*ostr); + xo << BOOST_SERIALIZATION_NVP(res); + } } }