From fb1b8c298f6527db998c5f46ee7609da048bbe04 Mon Sep 17 00:00:00 2001 From: Radegast Date: Fri, 14 Sep 2012 13:18:17 +0200 Subject: [PATCH] etlist: separate responses into a vector --- etlist/connection.cpp | 8 ++- etlist/connection.h | 6 +- etlist/etparser.cpp | 133 +++++++++++++++++++++++++++++------------- etlist/etparser.h | 21 +++++-- etlist/main.cpp | 11 ++-- 5 files changed, 121 insertions(+), 58 deletions(-) diff --git a/etlist/connection.cpp b/etlist/connection.cpp index f254286..576543e 100644 --- a/etlist/connection.cpp +++ b/etlist/connection.cpp @@ -55,7 +55,7 @@ std::string Connection::wrap_message(std::string message) return std::string(4, 0xff) + message; } -std::string Connection::get_response() +std::vector Connection::get_response() { return response_; } @@ -76,12 +76,14 @@ void Connection::HandleReceive(const boost::system::error_code& error, boost::asio::placeholders::bytes_transferred)); // std::cout.write(data_, bytes_recvd) << std::endl; - response_ += data_; + response_.push_back(data_); } +#if 0 else if (error) { - std::cout << "Receive error: " << error.message() << std::endl; + std::cout << "Receive error: [" << error.category().name() << "] " << error.message() << std::endl; } +#endif // io_service will quit when it has no more work to do } diff --git a/etlist/connection.h b/etlist/connection.h index 7b321fe..fd4f1de 100644 --- a/etlist/connection.h +++ b/etlist/connection.h @@ -40,7 +40,7 @@ public: std::string message = "getstatus", float timeout = 1.5); void close(); - std::string get_response(); + std::vector get_response(); private: boost::asio::deadline_timer timer_; boost::asio::io_service &io_service_; @@ -48,8 +48,8 @@ private: udp::endpoint receiver_endpoint_; enum { max_length = 2048 }; - char data_[max_length]; - std::string response_; + char data_[max_length]; + std::vector response_; void HandleReceive(const boost::system::error_code& error, size_t bytes_recvd); void HandleSend(); diff --git a/etlist/etparser.cpp b/etlist/etparser.cpp index b7331c4..542edde 100644 --- a/etlist/etparser.cpp +++ b/etlist/etparser.cpp @@ -17,46 +17,75 @@ * You should have received a copy of the GNU General Public License * along with ET: Legacy. If not, see . */ - -#include -#include -#include -#include // using 'setw' - #include "etparser.h" -ETParser::ETParser() +ETParser::ETParser(std::vector packets) { + for (int i = 0; i < packets.size(); i++) + { + ParseResponse(packets[i]); + } + // Just print it all out for now: + std::map ::iterator it; + for (it = response_variables_.begin(); it != response_variables_.end(); ++it) + { + std::cout << std::setw(22) << it->first << ": " << it->second << + std::endl; + } } -ETParser::~ETParser() +void ETParser::ParseResponse(std::string rsp_to_parse) { + set_response_name(rsp_to_parse); + if (get_variable("response_name") == "statusResponse" + || get_variable("response_name") == "infoResponse") + { + std::vector parts; + boost::split(parts, rsp_to_parse, boost::is_any_of("\n"), boost::token_compress_on); + + SplitVariables(parts.at(1)); + if (parts.size() > 1) + { + std::string players; + for (int i = 2; i < parts.size(); i++) + { + if (!parts[i].empty()) + { + players += parts[i] + std::string(1, 0xFF); + } + } + if (!players.empty()) + { + add_variable("players", players); + } + } + } + else if (get_variable("response_name") == "getserversResponse") + { + // TODO + } + else + { + std::cout << "UNKNOWN RESPONSE TYPE" << std::endl; + } } -void ETParser::ParseMessage(std::string recv_msg) +void ETParser::SplitVariables(std::string rsp_to_split) { // recv_msg.erase(recv_msg.find('\0'), recv_msg.npos); - // Omit OOB from the packet name - size_t headerEnd = recv_msg.find('\n'); - std::cout << "Parsing " << - recv_msg.substr(4, headerEnd - 4) << " packet.... "; - - std::map recv_tokens; - std::string key, value; - size_t tokenStart = 0; - size_t tokenEnd = 0; + size_t tokenStart = 0, tokenEnd = 0; for (;; ) { /* * Search for a key */ - tokenStart = recv_msg.find('\\', tokenEnd++); - tokenEnd = recv_msg.find('\\', ++tokenStart); + tokenStart = rsp_to_split.find('\\', tokenEnd++); + tokenEnd = rsp_to_split.find('\\', ++tokenStart); // No more keys if (tokenStart == std::string::npos) @@ -67,20 +96,20 @@ void ETParser::ParseMessage(std::string recv_msg) // Key without a value if (tokenEnd == std::string::npos) { - key = recv_msg.substr(tokenStart, - recv_msg.length() - tokenStart); - recv_tokens[key] = ""; + key = rsp_to_split.substr(tokenStart, + rsp_to_split.length() - tokenStart); + response_variables_[key] = std::string(""); std::cout << "Warning: adding a key with empty value." << std::endl; break; } - key = recv_msg.substr(tokenStart, tokenEnd - tokenStart); + key = rsp_to_split.substr(tokenStart, tokenEnd - tokenStart); /* * Search for a value */ - tokenStart = recv_msg.find('\\', tokenEnd++); - tokenEnd = recv_msg.find('\\', ++tokenStart); + tokenStart = rsp_to_split.find('\\', tokenEnd++); + tokenEnd = rsp_to_split.find('\\', ++tokenStart); // No more values if (tokenStart == std::string::npos) @@ -91,35 +120,55 @@ void ETParser::ParseMessage(std::string recv_msg) // Value is not at the end if (tokenEnd != std::string::npos) { - value = recv_msg.substr(tokenStart, tokenEnd - tokenStart); + value = rsp_to_split.substr(tokenStart, + tokenEnd - tokenStart); } else { // Last value - value = recv_msg.substr(tokenStart, recv_msg.length() - tokenStart); + value = rsp_to_split.substr(tokenStart, + rsp_to_split.length() - tokenStart); } - /* - * Store key->value pair in a map - */ - recv_tokens[key] = value; + response_variables_[key] = value; // FIXME: This should not happen, but it does. Why? - if (tokenStart >= recv_msg.length() || tokenEnd >= recv_msg.length()) + if (tokenStart >= rsp_to_split.length() || + tokenEnd >= rsp_to_split.length()) { break; } } +} - /* - * Display key->value pairs - */ - std::cout << recv_tokens.size() << " variables paired" << std::endl << std::endl; +std::string ETParser::get_variable(std::string key) +{ + return response_variables_.find(key)->second; +} - std::map ::iterator it; - for (it = recv_tokens.begin(); it != recv_tokens.end(); ++it) +void ETParser::add_variable(std::string key, std::string value) +{ + response_variables_.insert( + std::pair(key, value)); +} + +void ETParser::set_response_name(std::string rsp_header) +{ + try { - std::cout << std::setw(22) << it->first << ": " << it->second << - std::endl; + // Omit OOB (4x0xFF) from the packet start + rsp_header = rsp_header.substr(4); + + // getserversResponse is delimited by a backslash + // statusResponse and infoResponse are delimited by a newline + std::vector parts; + boost::split(parts, rsp_header, boost::is_any_of("\\ \n"), boost::token_compress_on); + + add_variable("response_name", parts[0]); } -} \ No newline at end of file + catch (std::out_of_range& exception) + { + std::cerr << "Invalid response: " << rsp_header << std::endl; + exit(EXIT_FAILURE); + } +} diff --git a/etlist/etparser.h b/etlist/etparser.h index d07ba4c..7b81434 100644 --- a/etlist/etparser.h +++ b/etlist/etparser.h @@ -20,16 +20,27 @@ #ifndef ETPARSER_H #define ETPARSER_H +#include +#include +#include +#include // using 'setw' + +#include +#include + class ETParser { public: - ETParser(); - virtual ~ETParser(); + ETParser(std::vector packets); - void SplitIntoParts(std::string msg_to_split); - void ParseMessage(std::string recv_msg); + void ParseResponse(std::string rsp_to_parse); + void SplitVariables(std::string rsp_to_split); + + void set_response_name(std::string rsp_header); + std::string get_variable(std::string key); + void add_variable(std::string key, std::string value); private: - + std::map response_variables_; }; #endif // ETPARSER_H diff --git a/etlist/main.cpp b/etlist/main.cpp index b2722dc..677b1a9 100644 --- a/etlist/main.cpp +++ b/etlist/main.cpp @@ -66,7 +66,7 @@ int main(int argc, char *argv[]) { std::cerr << "Usage: " << argv[0] << " -s " << std::endl; std::cerr << "Append -h or --help to see all program options." << std::endl; - return 1; + return EXIT_FAILURE; } /* @@ -82,15 +82,16 @@ int main(int argc, char *argv[]) /* * Parse the response */ - ETParser parser; - if (var_map.count("raw")) { - std::cout << client.get_response() << std::endl; + for (int i = 0; i < client.get_response().size(); i++) + { + std::cout << "Response #" << i << ": " << client.get_response()[i] << std::endl << std::endl; + } } else { - parser.ParseMessage(client.get_response()); + ETParser parser(client.get_response()); } } catch (std::exception& e)