[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