From b2ba092858a40fc42afba6b529d5b97bcba363e2 Mon Sep 17 00:00:00 2001 From: Gerd v. Egidy Date: Mon, 30 Oct 2006 12:44:00 +0000 Subject: [PATCH] libt2n: (gerd) add hello peek --- src/command_client.cpp | 103 +++++++++++++++++++++++++++++++++++++++-------- src/command_client.hxx | 1 + src/connection.cpp | 25 +++++++++++- src/connection.hxx | 2 + 4 files changed, 111 insertions(+), 20 deletions(-) diff --git a/src/command_client.cpp b/src/command_client.cpp index 77daf0d..376d3f9 100644 --- a/src/command_client.cpp +++ b/src/command_client.cpp @@ -67,30 +67,97 @@ std::string command_client::read_packet(const long long &usec_timeout) void command_client::read_hello() { - istringstream hello(read_packet(hello_timeout_usec)); + 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[5]; - hello.read(chk,4); - chk[4]=0; - if (hello.fail() || hello.eof() || string("T2Nv") != chk) - throw t2n_version_mismatch("illegal hello received (T2N)"); + 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; - hello >> prot_version; - if (hello.fail() || hello.eof() || prot_version != PROTOCOL_VERSION) - throw t2n_version_mismatch("not compatible with the server protocol 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; - hello.read(chk,1); - if (hello.fail() || hello.eof() || chk[0] != ';') - throw t2n_version_mismatch("illegal hello received (1. ;)"); + 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; - hello.read(chk,4); - if (hello.fail() || hello.eof() || *((int*)chk) != 1) - throw t2n_version_mismatch("host byte order not matching"); + if (hello.read(&chk,1)) + { + if (chk != ';') + throw t2n_version_mismatch("illegal hello received (2. ;)"); + } + else + return false; - hello.read(chk,1); - if (hello.fail() || hello.eof() || chk[0] != ';') - throw t2n_version_mismatch("illegal hello received (2. ;)"); + return true; } void command_client::send_command(command* cmd, result_container &res) diff --git a/src/command_client.hxx b/src/command_client.hxx index 8c6b2bf..6ec6a1d 100644 --- a/src/command_client.hxx +++ b/src/command_client.hxx @@ -36,6 +36,7 @@ class command_client void read_hello(); std::string read_packet(const long long &usec_timeout); + bool check_hello(const std::string& hellostr); public: command_client(client_connection& _c, long long _command_timeout_usec=90000000, long long _hello_timeout_usec=30000000); diff --git a/src/connection.cpp b/src/connection.cpp index 9cffb89..d339f9f 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -30,8 +30,6 @@ namespace libt2n connection::packet_size_indicator connection::bytes_available() { - // max packet size is unsigned int - // no size information -> no packet if (buffer.size() < sizeof(packet_size_indicator)) return 0; @@ -65,6 +63,29 @@ bool connection::get_packet(std::string& data) 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) { diff --git a/src/connection.hxx b/src/connection.hxx index 94c3123..60ea862 100644 --- a/src/connection.hxx +++ b/src/connection.hxx @@ -74,6 +74,8 @@ class connection bool get_packet(std::string& data); + unsigned int peek_packet(std::string& data); + /// returns true if a complete data packet is in the buffer. retrieve it with get_packet(). bool packet_available() { return bytes_available(); } -- 1.7.1