X-Git-Url: http://developer.intra2net.com/git/?p=libt2n;a=blobdiff_plain;f=src%2Fcommand_server.cpp;h=2e3beb5b0d923e8ce63cf3f9f6e9b0ce1eea382a;hp=55c4cc1d865d6cade06b5d4220158fc325c6901c;hb=4b995a82e29808cf8125889f83ec70fc7b5c77af;hpb=01a464637ed95b0aacd58eb74bdd17df4a7851ab diff --git a/src/command_server.cpp b/src/command_server.cpp index 55c4cc1..2e3beb5 100644 --- a/src/command_server.cpp +++ b/src/command_server.cpp @@ -44,17 +44,19 @@ namespace libt2n { command_server::command_server(server& _s) - : s(_s) + : s(_s), guard_handle(0) { // register callback s.add_callback(new_connection,bind(&command_server::send_hello, boost::ref(*this), _1)); } +/// send a hello message to a new connection void command_server::send_hello(unsigned int conn_id) { server_connection* sc=s.get_connection(conn_id); + // TODO: Gerd: Throw exception if get_connection() returns NULL or just return? - ostringstream hello; + std::ostringstream hello; hello << "T2Nv" << PROTOCOL_VERSION << ';'; @@ -72,7 +74,7 @@ void command_server::handle_packet(const std::string& packet, server_connection* OBJLOGSTREAM(s,debug,"handling packet from connection " << conn->get_id()); // deserialize packet - istringstream ifs(packet); + std::istringstream ifs(packet); boost::archive::binary_iarchive ia(ifs); command_container ccont; result_container res; @@ -83,7 +85,7 @@ void command_server::handle_packet(const std::string& packet, server_connection* } catch(boost::archive::archive_exception &e) { - ostringstream msg; + std::ostringstream msg; msg << "archive_exception while deserializing on server-side, " "code " << e.code << " (" << e.what() << ")"; res.set_exception(new t2n_serialization_error(msg.str())); @@ -101,8 +103,7 @@ void command_server::handle_packet(const std::string& packet, server_connection* xo << BOOST_SERIALIZATION_NVP(ccont); } - // TODO: cast to command subclass (template) - command *cmd=ccont.get_command(); + command* cmd=cast_command(ccont.get_command()); if (cmd) { @@ -116,10 +117,17 @@ void command_server::handle_packet(const std::string& packet, server_connection* { throw; } } else - throw logic_error("uninitialized command called"); + { + std::ostringstream msg; + if (ccont.get_command()!=NULL) + msg << "illegal command of type " << typeid(ccont.get_command()).name() << " called"; + else + msg << "NULL command called"; + res.set_exception(new t2n_command_error(msg.str())); + } } - ostringstream ofs; + std::ostringstream ofs; boost::archive::binary_oarchive oa(ofs); try @@ -128,7 +136,7 @@ void command_server::handle_packet(const std::string& packet, server_connection* } catch(boost::archive::archive_exception &e) { - ostringstream msg; + std::ostringstream msg; msg << "archive_exception while serializing on server-side, " "code " << e.code << " (" << e.what() << ")"; res.set_exception(new t2n_serialization_error(msg.str())); @@ -151,18 +159,46 @@ void command_server::handle_packet(const std::string& packet, server_connection* /** @brief handle incoming commands @param[in,out] usec_timeout wait until new data is found, max timeout usecs. -1: wait endless, 0: instant return + @param[out] usec_timeout_remaining microseconds from the timeout that were not used */ void command_server::handle(long long usec_timeout, long long* usec_timeout_remaining) { - if (s.fill_buffer(usec_timeout,usec_timeout_remaining)) + guard_handle++; + try { - string packet; - unsigned int conn_id; + if (s.fill_buffer(usec_timeout,usec_timeout_remaining)) + { + std::string packet; + unsigned int conn_id; - while (s.get_packet(packet,conn_id)) - handle_packet(packet,s.get_connection(conn_id)); + while (s.get_packet(packet,conn_id)) + { + server_connection* conn=s.get_connection(conn_id); + if (!conn) + EXCEPTIONSTREAM(error,logic_error,"illegal connection id " << conn_id << " received"); + + try + { handle_packet(packet,conn); } + catch (t2n_transfer_error &e) + { + // shut down a connection with transfer errors (usually write errors) + conn->close(); + } + catch(...) + { throw; } + } + } } - s.cleanup(); + catch(...) + { + guard_handle--; + throw; + } + guard_handle--; + + // don't call cleanup on re-entered handle-calls + if (guard_handle == 0) + s.cleanup(); } }