Ver Fonte

Added feature where we treat some ANSI as a newline.

Steve Thielemann há 3 anos atrás
pai
commit
9ad2c9e1b9
2 ficheiros alterados com 98 adições e 18 exclusões
  1. 90 14
      session.cpp
  2. 8 4
      session.h

+ 90 - 14
session.cpp

@@ -47,6 +47,14 @@ void high_ascii(std::string &str) {
   str = std::regex_replace(str, high_cleaner, "#");
 }
 
+std::smatch ansi_newline(const std::string &str) {
+  static std::regex ansi_nl("\x1b\[[0-9;]*[JK]",
+                            std::regex_constants::ECMAScript);
+  std::smatch m;
+  std::regex_search(str, m, ansi_nl);
+  return m;
+}
+
 std::string clean_string(const std::string &source) {
   // BOOST_LOG_NAMED_SCOPE("clean_string");
   std::string clean = source;
@@ -93,6 +101,15 @@ void Session::start(void) {
 
 Session::~Session() { BUGZ_LOG(info) << "~Session"; }
 
+/**
+ * Returns the current server prompt.
+ *
+ * NOTE:  This is the raw string from the server, so it can contain
+ * color codes.  Make sure you clean it before trying to test it for
+ * any text.
+ *
+ * @return const std::string&
+ */
 const std::string &Session::get_prompt(void) { return server_prompt; }
 
 void Session::parse_auth(void) {
@@ -152,6 +169,28 @@ void Session::dispatch_line(std::string line) {
   }
 
   std::string temp = clean_string(line);
+  // NOTE:  We get "TradeWars Game Server\n"  (Missing \r)
+  // We add the \r with our injection line.
+
+  if (temp.find("TradeWars Game Server") != std::string::npos) {
+    to_client("\rTradeWars Proxy v2++ READY (~ to activate)\n\r");
+  }
+
+  // additional analysis needed here
+  // state :  where are we, what is this line?
+  // collect all data we can from the server.  (P1)
+
+  if (temp.find("Selection (? for menu): ") != std::string::npos) {
+    char ch = temp[temp.length() - 1];
+    if (ch >= 'A' && ch < 'Q') {
+      BUGZ_LOG(warning) << "GAME " << ch << " activated!";
+    }
+  }
+
+  // "Selection (? for menu): ?"
+  // This gives us the current game that we're in.
+  // (excluding ?, #, ! and Q)
+
   BUGZ_LOG(info) << "SL: " << temp;
 }
 
@@ -171,10 +210,41 @@ void Session::process_lines(std::string &received) {
   size_t pos, rpos;
   server_prompt.append(received);
 
+  // I also need to break on r"\x1b[\[0-9;]*JK", treat these like \n
+
   while ((pos = server_prompt.find('\n', 0)) != std::string::npos) {
 
     std::string line;
 
+    std::smatch m = ansi_newline(server_prompt);
+    if (!m.empty()) {
+      // We found one.
+      size_t mpos = m.prefix().length();
+      // int mlen = m[0].length();
+
+      if (mpos < pos) {
+        // Ok, the ANSI newline is before the \n
+
+        // perform this process with the received line
+        std::smatch rm = ansi_newline(received);
+        if (!rm.empty()) {
+          size_t rpos = rm.prefix().length();
+          int rlen = rm[0].length();
+          if (show_client) {
+            line = received.substr(0, rpos + rlen);
+            to_client(line);
+          }
+          received = rm.suffix();
+        }
+
+        // perform this on the server_prompt line
+        line = m.prefix();
+        dispatch_line(line);
+        server_prompt = m.suffix();
+        // redo this loop -- there's still a \n in there
+        continue;
+      }
+    }
     // process "line" in received
 
     rpos = received.find('\n', 0);
@@ -209,15 +279,6 @@ void Session::process_lines(std::string &received) {
     // display on?
     // to_client(line);
 
-    // NOTE:  We get "TradeWars Game Server\n"  (Missing \r)
-    // We add the \r with our injection line.
-
-    // TODO(stevet): MOVE TO DEFAULT dispatcher
-    // our first injection
-    if (line.find("TradeWars Game Server") != std::string::npos) {
-      to_client("\rTradeWars Proxy v2++ READY (~ to activate)\n\r");
-    }
-
     // How should I handle \r in lines?  For now, remove it
     // but LOG that we did.
 
@@ -268,6 +329,7 @@ void Session::set_timer(void) {
 }
 
 void Session::reset_timer(void) { timer_.cancel(); }
+
 void Session::on_timer(const boost::system::error_code error) {
   if (error != boost::asio::error::operation_aborted) {
     // Ok, VALID timeout
@@ -347,6 +409,21 @@ void Session::on_resolve(
   }
 }
 
+void Session::client_input(const std::string &input) {
+  if (active) {
+    // do something amazing with the user's input.
+  } else {
+    if (input == "\x1b" || input == "~") {
+      std::string prompt = clean_string(get_prompt());
+
+      BUGZ_LOG(debug) << "CI: ACTIVATE prompt shows: [" << prompt << "]";
+    }
+  }
+  if (talk_direct)
+    to_server(input);
+  BUGZ_LOG(info) << "CI: " << input;
+}
+
 void Session::client_read(void) {
   auto self(shared_from_this());
 
@@ -386,9 +463,8 @@ void Session::client_read(void) {
             // Proxy Active?
             // BOOST_LOG_NAMED_SCOPE("Session");
 
-            if (talk_direct)
-              to_server(read_buffer);
-            BUGZ_LOG(info) << "CI: " << read_buffer;
+            std::string line(read_buffer, length);
+            client_input(line);
 
             // do_write(output);
           }
@@ -403,7 +479,7 @@ void Session::client_read(void) {
       });
 }
 
-void Session::to_client(std::string message) {
+void Session::to_client(const std::string &message) {
   auto self(shared_from_this());
   // output the cleaned string (so I can see what we're sending in the
   // logs)
@@ -426,7 +502,7 @@ void Session::to_client(std::string message) {
       });
 }
 
-void Session::to_server(std::string message) {
+void Session::to_server(const std::string &message) {
   auto self(shared_from_this());
   boost::asio::async_write(
       server_, boost::asio::buffer(message),

+ 8 - 4
session.h

@@ -35,8 +35,11 @@ public:
   void on_resolve(const boost::system::error_code error,
                   const boost::asio::ip::tcp::resolver::results_type results);
   void client_read(void);
-  void to_client(std::string message);
-  void to_server(std::string message);
+
+  void client_input(const std::string &input);
+  void to_client(const std::string &message);
+  void to_server(const std::string &message);
+
   void on_shutdown(boost::system::error_code ec);
 
   void dispatch_line(std::string line);
@@ -52,12 +55,13 @@ private:
   int time_ms;
   int keepalive_secs;
 
-  std::stack<Dispatch *> director;
+  // std::stack<Dispatch *> director;
 
   // FOR NOW:  These will go into the director
   bool show_client = true;
   bool talk_direct = true;
-
+  bool active = false;
+  
   /**
    * The client's socket
    */