[PATCH 1/2] daemon: fix loss of data when handling input lines from clients.

Dmitri Paduchikh dpaduchikh на gmail.com
Сб Мар 2 04:06:41 MSK 2013


This was happening because Voiceman does not decode utf-8 sequences crossing
the block boundary.  In such a case next block would start with bad utf-8
sequence and Voiceman would lose all data from that block.  This includes
all newline characters in this next block, so subsequent commands would be
lost as well.

This patch fixes the problem by handling input lines in utf-8, without
decoding them to wstring beforehand.
---
 daemon/core/Client.h |  4 ++--
 daemon/main/main.cpp | 35 ++++++++++++++---------------------
 2 files changed, 16 insertions(+), 23 deletions(-)

diff --git a/daemon/core/Client.h b/daemon/core/Client.h
index b17a63c..920ff87 100644
--- a/daemon/core/Client.h
+++ b/daemon/core/Client.h
@@ -47,8 +47,8 @@ public:
   virtual ~Client() {}
 
 public:
-  /**\brief The chain of received incomplete data*/
-  std::wstring chain;
+  /**\brief The buffer with received incomplete data */
+  std::string buf;
 
   /**\brief The current volume value associated with the connection*/
   TextParam volume;
diff --git a/daemon/main/main.cpp b/daemon/main/main.cpp
index fa9f568..8f2a9a1 100644
--- a/daemon/main/main.cpp
+++ b/daemon/main/main.cpp
@@ -635,41 +635,34 @@ public:
    */
   void processClientData(Client& client, const std::string& data)
   {
-    std::wstring text = readUTF8(data);
-    std::wstring::size_type offset = 0;
-    for(std::wstring::size_type i = 0;i < text.size();i++)
-      if (text[i] != '\r')
-	{
-	  if (offset > 0)
-	    text[i - offset] = text[i];
-	} else
-	offset++;
-    assert(offset <= text.size());
-    text.resize(text.size() - offset);
-    std::wstring buf = client.chain;
-    buf.reserve(buf.length() + text.length());
-    for(std::wstring::size_type i = 0;i < text.length();i++)
+    std::string& buf = client.buf;
+    buf.reserve(m_maxInputLine);
+
+    for (std::string::size_type i = 0; i < data.length(); i++)
       {
-	if (text[i] == '\n')
+	char ch = data[i];
+	if (ch == '\r') continue;
+	if (ch == '\n')
 	  {
 	    if (!client.rejecting)
-	      m_protocol.process(buf, client);
+	      m_protocol.process(readUTF8(buf), client);
 	    client.rejecting = 0;
 	    buf.clear();
 	    continue;
 	  } //'\n';
 	if (client.rejecting)
 	  continue;
-	buf += text[i];
-	if (m_maxInputLine > 0 && buf.length() > m_maxInputLine )
+	buf += ch;
+	if (m_maxInputLine > 0 && buf.length() >= m_maxInputLine )
 	  {
-	    logMsg(LOG_DEBUG, "Input line exceeds input line length limit. Truncating...");
+	    logMsg(LOG_DEBUG, "Input line exceeds input line length limit "
+		   "%u bytes. Truncating...", (unsigned)m_maxInputLine);
 	    client.rejecting = 1;
-	    m_protocol.process(buf, client);
+	    m_protocol.process(readUTF8(buf), client);
 	    buf.clear();
 	  }
       } //for();
-    client.chain = buf;
+    logMsg(LOG_DEBUG, "Stored %u bytes in buffer", (unsigned)buf.length());
   }
 
 private:
-- 
1.8.1.4




Подробная информация о списке рассылки Homeros