[Homeros] Потеря данных в Voiceman

Michael Pozhidaev msp на altlinux.ru
Сб Мар 2 10:41:49 MSK 2013


Гм, принимается, но только в 1.6 ко всем дополнениям, которые там уже
копятся. Мини-фикс в 1.5.1 оставим пока единственным. Спасибо!

> Voiceman иногда теряет данные (куски текста, команды) из-за того, что
> последовательности utf-8 могут пересекать границу блока. Этот случай не
> обрабатывался. Исправление во вложении.
>
> Второй патч делает бип в случае обрубания строки по max input line.
> Просто чтобы было понятно, что текст прочитан не полностью.
>
> Ещё, кажется, клиент склеивает команды чтения без учёта max input line,
> что может привести к потере текста. Но я это пока не проверял.
>
> -- 
> Дмитрий Падучих
>
> From fad1c70a11bcc0127f136dad92e2e69ddd64a0b3 Mon Sep 17 00:00:00 2001
> From: Dmitri Paduchikh <dpaduchikh на gmail.com>
> Date: Sat, 2 Mar 2013 06:06:41 +0600
> Subject: [PATCH 1/2] daemon: fix loss of data when handling input lines from
>  clients.
>
> 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
>
>
> From 5bdd68df158e4dd9cfd459a760ad0efc854b5898 Mon Sep 17 00:00:00 2001
> From: Dmitri Paduchikh <dpaduchikh на gmail.com>
> Date: Sat, 2 Mar 2013 06:44:18 +0600
> Subject: [PATCH 2/2] daemon: produce beep at the point of input line
>  truncation.
>
> ---
>  daemon/main/main.cpp | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/daemon/main/main.cpp b/daemon/main/main.cpp
> index 8f2a9a1..64b48fa 100644
> --- a/daemon/main/main.cpp
> +++ b/daemon/main/main.cpp
> @@ -659,6 +659,7 @@ public:
>  		   "%u bytes. Truncating...", (unsigned)m_maxInputLine);
>  	    client.rejecting = 1;
>  	    m_protocol.process(readUTF8(buf), client);
> +	    m_protocol.process(L"B:3000:50", client);
>  	    buf.clear();
>  	  }
>        } //for();

-- 
Michael Pozhidaev. Tomsk, Russia.
Russian info page: http://www.marigostra.ru/


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